ipmiutil-3.1.5/0000755000000000000000000000000013566765332012072 5ustar rootrootipmiutil-3.1.5/AUTHORS0000644000076400007640000000054713566765332014533 0ustar mgportalloggersipmiutil: Andy Cress util/AnsiTerm.cpp Robert Nelson util/oem_dell.c Harsha S util/ihpm.c Frederic.Lelievre at ca.kontron.com, Francois.Isabelle at ca.kontron.com, Jean-Michel.Audet at ca.kontron.com, MarieJosee.Blais at ca.kontron.com ipmiutil-3.1.5/config.h.in0000644000000000000000000000631013566765325014117 0ustar rootroot/* config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ #undef HAVE_DOPRNT /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the `getpagesize' function. */ #undef HAVE_GETPAGESIZE /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `memcpy' function. */ #undef HAVE_MEMCPY /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have a working `mmap' system call. */ #undef HAVE_MMAP /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT /* Define to 1 if you have the `socket' function. */ #undef HAVE_SOCKET /* if socklen_t is defined, make note of it */ #undef HAVE_SOCKLEN_T /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strcspn' function. */ #undef HAVE_STRCSPN /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the `strftime' function. */ #undef HAVE_STRFTIME /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strspn' function. */ #undef HAVE_STRSPN /* Define to 1 if you have the `strtoul' function. */ #undef HAVE_STRTOUL /* Define to 1 if you have the header file. */ #undef HAVE_SYSLOG_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `vprintf' function. */ #undef HAVE_VPRINTF /* Define to 1 if the system has the type `wchar_t'. */ #undef HAVE_WCHAR_T /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Define to 1 if your declares `struct tm'. */ #undef TM_IN_SYS_TIME /* Version number of package */ #undef VERSION /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `long int' if does not define. */ #undef off_t /* if socklen_t is not defined, provide something useful */ #undef socklen_t ipmiutil-3.1.5/buildmin.cmd0000644000076400007640000000130713566765324015747 0ustar mgportalloggers@echo off REM # buildmin32.cmd REM # build ipmiutil for windows in standalone mode (minimal, 32bit) REM # without IPMI LAN 2.0 libraries, so no SOL. Use for bootables. REM # REM # First download a copy of getopt.c getopt.h. REM # copy getopt.* util REM # REM TODO, prebuild checking: REM check for getopt.c,h set | findstr VCINSTALLDIR if %errorlevel% EQU 1 goto vcerror echo %LIBPATH% |findstr /C:64 >NUL if %errorlevel% EQU 0 ( set MARCH=X64 set UTMAKE=ipmiutil2-64.mak ) else ( set MARCH=IX86 set UTMAKE=ipmiutil2.mak ) cd util nmake /nologo -f %UTMAKE% all cd .. echo buildmin %UTMAKE% done goto done :vcerror echo Need to first run vcvars.bat :done ipmiutil-3.1.5/INSTALL0000744000076400007640000002045613566765324014517 0ustar mgportalloggers------------------------------------- INSTALL for ipmiutil source ------------------------------------- The ipmiutil source package provides IPMI-based utilities and kernel patches for managing various servers in Linux or Windows. The same source files can be built in both Linux and Windows as shown below. ------------------------------------- Build instructions for Linux ------------------------------------- To build with some GPL code: If you are building ipmiutil for open-source, then the MD2 hash for IPMI LAN and the valinux driver interface (/dev/ipmikcs) can be supported. If so, you should specify the following during configure: "./configure --enable-gpl" The default is to build with only BSD-licensed code and not to include the MD2 and valinux features. The md2.h and ipmi_ioctl.h files with GPL code can be removed if this option is not enabled. To build a standalone binary without IPMI LAN 2.0 (lanplus plugin), which may be desirable for use on bootable media (USB/CDROM), to decrease the size or to avoid using libcrypto, you can specify the following during configure: "./configure --disable-lanplus" or "./configure --enable-standalone" builds it without lanplus libs and without GPL code. To add LanDesk IPMI support: Support for the LanDesk IPMI driver requires a library supplied by LanDesk (libipmiapi.a). After obtaining this library, place it in lib/libipmiapi.a. Then you can link ipmiutil to support it by specifying the following during configure: "./configure --enable-landesk=yes" Steps to build for Linux: # ./beforeconf.sh Which automates these functions: * copying libtool files * aclocal (may be needed if automake versions are different) * autoconf (may be needed if automake versions are different) * automake # ./configure --enable-landesk adds landesk library support [default=no] --disable-lanplus disable lanplus library support --enable-standalone build standalone, with no GPL or LanPlus libs. --enable-gpl build with some GPL code [default=no] # make To add the ifruset utility, which allows setting any FRU Product fields: # cd util; make ifruset # ifruset -? To build and install an rpm package, use one of the following: # make install # make rpm The make rpm produces a binary rpm, and a source rpm, which can be installed with "rpm -i *.rpm". To build and install a Debian package, do this: # dpkg-buildpackage then install it with "dpkg -i *.deb". ------------------------------------- Build instructions for Windows ------------------------------------- The ipmiutil Windows binaries for each release are pre-built and posted at http://ipmiutil.sourceforge.net, but here is how to build the ipmiutil EXEs for Windows from source. Note that the WIN32 compile flag is used. The ipmiutil buildwin.cmd shows how to compile and link the lib and exe files, although many people prefer instead to do builds with the Microsoft VisualStudio project GUI. See also ipmiutil UserGuide section 5.2 for more details if needed. 1) Install Visual Studio The build environment assumes that VisualStudio 6.0 VC98 or later is installed. 2) Download contrib files Before running buildwin.cmd, first download the contributed files for Windows (includes getopt.c and openssl). A copy of these files is available from http://ipmiutil.sf.net/FILES/ipmiutil-contrib.zip 3) Copy initial contrib files into ipmiutil Below are sample directories where ipmiutil*.tar.gz was unpacked, and where the openssl*.tar.gz was unpacked. > set ipmiutil_dir=c:\dev\ipmiutil > set openssl_dir=c:\dev\openssl First, copy the getopt.c & getopt.h into the util directory. From the directory where ipmiutil-contrib.zip was unpacked, > copy getopt.* %ipmiutil_dir%\util The iphlpapi.lib comes from VS 2003 .Net or Win2003 DDK. > copy iphlpapi.lib %ipmiutil_dir%\lib > copy iphlpapi.h %ipmiutil_dir%\util 4) Build the openssl libraries To build from original source you would then want to build a copy of openssl for Windows, and copy the built openssl files to lib & inc. Follow the openssl build instructions from INSTALL.W32 for VC++ to build these binaries. Note that perl must also be installed first. 5) Copy the resulting LIB and DLL binaries to ipmiutil > copy %openssl_dir%\out32dll\libeay32.lib %ipmiutil_dir%\lib > copy %openssl_dir%\out32dll\ssleay32.lib %ipmiutil_dir%\lib > copy %openssl_dir%\out32dll\libeay32.dll %ipmiutil_dir%\util > copy %openssl_dir%\out32dll\ssleay32.dll %ipmiutil_dir%\util > mkdir %ipmiutil_dir%\lib\lanplus\openssl > copy %openssl_dir%\include\openssl\*.h %ipmiutil_dir%\lib\lanplus\openssl 6) Set the Visual Studio variables with vcvars*.bat For your installation of Microsoft Visual Studio, it has batch files to set the Visual C variables. Run the appropriate architecture version of these batch files to set the VC variables. Example: C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat or C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat or C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\amd64\vcvarsamd64.bat 7) Run buildwin.cmd buildwin.cmd will build all of the Windows EXE and DLL files. If you are using ipmiutil for a bootable WinPE environment, and do not need Serial-Over-LAN functionality, the buildwin2.cmd will build the Windows EXE files without using the openssl libraries, to simplify the process. The openssl libraries are required for the IPMI LAN 2.0 crypto functions that Serial-Over-LAN requires. ------------------------------------- Build instructions for Solaris ------------------------------------- # iver=2.7.9 # uname -a SunOS unknown 5.10 Generic_127128-11 i86pc i386 i86pc # gunzip ipmiutil-${iver}.tar.gz # tar xvf ipmiutil-${iver}.tar # cd ipmiutil-${iver} # PATH=/usr/sbin:/usr/bin:/usr/ucb:/usr/openwin:/usr/ccs/bin:/usr/sfw/bin # ./configure # make # make tarsol This produces /tmp/ipmiutil-${iver}-solaris.tar with the binaries. # gzip /tmp/ipmiutil-${iver}-solaris.tar Solaris Release Notes: - Built with support for bmc, lan, and lanplus interfaces. Supports the Solaris 10 /dev/bmc driver via putmsg method. - Requests to slave addresses other than BMC are not supported by the Solaris bmc driver (e.g. to HSC at 0xc0), and are sent to the BMC sa instead. - Memory mapping logic returns an error (e.g. BIOS version). - idiscover -a broadcast ioctl works now in ipmiutil-2.3.1 To Install on Solaris: gunzip /tmp/ipmiutil-${iver}-solaris.tar.gz tar xvf /tmp/ipmiutil-${iver}-solaris.tar ./install.sh ------------------------------------- Build instructions for FreeBSD ------------------------------------- # iver=2.7.9 # gunzip ipmiutil-${iver}.tar.gz # tar xvf ipmiutil-${iver}.tar # cd ipmiutil-${iver} # ./configure # make # make tarbsd This produces /tmp/ipmiutil-${iver}-bsd.tar with the binaries. # gzip /tmp/ipmiutil-${iver}-bsd.tar FreeBSD Release Notes: - ipmiutil-2.3.5 supports FreeBSD with direct driverless KCS - ipmiutil-2.5.2 adds support for FreeBSD 7.x ipmi driver port To Install on FreeBSD: gunzip /tmp/ipmiutil-${iver}-bsd.tar.gz tar xvf /tmp/ipmiutil-${iver}-bsd.tar ./install.sh ------------------------------------- Build instructions for MAC OSX ------------------------------------- # iver=2.9.1 # tar -xvxf ipmiutil-${iver}.tar.gz # cd ipmiutil-${iver} # ./beforeconf.sh There are some warnings shown, but this does the aclocal/autoconf/automake. # ./configure # make # make tarbsd This produces /tmp/ipmiutil-${iver}-bsd.tar with the binaries. # mv /tmp/ipmiutil-${iver}-bsd.tar /tmp/ipmiutil-${iver}-macos.tar # gzip /tmp/ipmiutil-${iver}-macos.tar To Install on MacOS from a Terminal: gunzip /tmp/ipmiutil-${iver}-macos.tar.gz tar xvf /tmp/ipmiutil-${iver}-macos.tar ./install.sh Release Notes for MAC OSX: - ipmiutil-2.9.1 supports MacOSX client builds - Does not yet support AppleBMC.kext, pending documentation --------------------------------------- Build instructions for ARM (Android) --------------------------------------- # tar -xzvf ipmiutil-${iver}.tar.gz # cd ipmiutil-${iver} # ./configure --enable-standalone --host=arm # make ipmiutil-3.1.5/stamp-h0000644000076400007640000000001213566765324014743 0ustar mgportalloggerstimestamp ipmiutil-3.1.5/stamp-h.in0000644000076400007640000000001213566765324015350 0ustar mgportalloggerstimestamp ipmiutil-3.1.5/util/0000755000076400007640000000000013566765332014432 5ustar mgportalloggersipmiutil-3.1.5/util/iserial.c0000644000076400007640000016134113566765324016235 0ustar mgportalloggers/* * tmconfig.c * * This tool sets up the serial EMP port for the Terminal Mode settings. * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2002-2006 Intel Corporation. * * Options: * -b Set serial port up for Basic Mode (fBMode) * -B Set baud rate for serial port * -d Disable serial port for IPMI use * -f Flow Control setting, default=1 (RTS/CTS) * -r Read-only, view serial port parameters * -s configure serial port for Shared Basic Mode & Remote Console * -t Configure serial port for shared Terminal Mode (TMode) & Console * -u username Set username for EMP TMode login (default is null user 1) * -p password Set password for EMP TMode login * -l show LAN parameters also * -m0 switch MUX to Normal baseboard operation * -m1 switch MUX to BMC operation (BMode or TMode) * -x eXtra debug messages * -f special boot Flags * * Change Log: * 02/12/02 Andy Cress - created from pefconfig.c * 03/08/02 Andy Cress - added GET_USER_ACCESS to serial parameters shown * 03/11/02 Andy Cress - changed MUX param 8 value for -b * 03/13/02 Andy Cress - changed default behavior to be like -r, * added -c option to configure TMode * 03/15/02 Andy Cress v1.3 added bootflags * 04/12/02 Andy Cress v1.4 use always avail instead of shared mode * also, don't do boot flags if not specified * 07/02/02 Andy Cress v1.5 add more Usage, add -d option. * 07/25/02 Andy Cress v1.6 fixed passwd offset for fSetTMode (-c) * 08/02/02 Andy Cress v1.7 moved common ipmi_cmd() code to ipmicmd.c * 12/09/02 Andy Cress v1.8 make sure -d sets user1 to admin again, * combine -n/-t into -m for MUX, * fix -c to drop thru to SetTMode logic, * param 8 values changed, * Dont SetUser for TMode unless -u, * use DCD & RTS/CTS for TMode. * 12/12/02 Andy Cress v1.9 change access from 0x23 to 0x2b * 01/23/03 Andy Cress v1.10 decode UserAccess meanings * 01/29/03 Andy Cress v1.11 added MV OpenIPMI support * 07/31/03 Andy Cress v1.12 added -F to try force it * 09/10/03 Andy Cress v1.13 isolate ser_ch, add -n option to specify chan#, * abort if no serial channels * 05/05/04 Andy Cress v1.14 call ipmi_close before exit, added WIN32 * 06/29/04 Andy Cress v1.15 added fSetPsw even if not fSetUser3 * 11/01/04 Andy Cress v1.16 add -N / -R for remote nodes * 11/23/04 Andy Cress v1.17 recompile with ipmignu.c changes * 01/31/05 Andy Cress v1.18 allow IPMI 2.0 versions * 03/18/05 Andy Cress v1.19 fix for -n, show the ser_ch it is using. * 05/19/05 Andy Cress v1.20 show 4 users if IPMI20 * 06/13/05 Andy Cress v1.21 show multiple alert destinations * 08/10/05 Andy Cress v1.22 truncate extra string chars * 05/02/06 Andy Cress v1.23 add -B option for baud rate * 09/12/06 Andy Cress v1.26 use authmask to set Serial Param(2) * 09/29/06 Andy Cress v1.27 add -q for user number, add -f for Flow Control, * adjust Mode if known, clear SerialParam(3) if -d, * added ShowAccess if -r. */ /*M* Copyright (c) 2002-2006, Intel Corporation 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 Corporation 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*/ #ifdef WIN32 #include #include #include #include #include "getopt.h" #elif defined(DOS) #include #include #include #include #include "getopt.h" #else #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #include #endif #include "ipmicmd.h" #define SELprintf printf #define SER_CH 4 #define LAN_CH 1 #define MAXCHAN 16 #define PSW_LEN 16 /*see also PSW_MAX=20 in ipmicmd.h*/ /* Note: The optional IPMI 2.0 20-byte passwords are not supported here, * due to back-compatibility issues. */ /* serial channel access values */ #define ALWAYS_AUTH 0x22 #define ALWAYS_NOAUTH 0x2A #define SHARED_AUTH 0x23 #define SHARED_NOAUTH 0x2B typedef struct { unsigned short record_id; uchar record_type; int timestamp; unsigned short generator_id; uchar evm_rev; //event message revision uchar sensor_type; uchar sensor_number; uchar event_trigger; uchar event_data1; uchar event_data2; uchar event_data3; } SEL_RECORD; typedef struct { /* See IPMI Table 19-3 */ uchar data[30]; } SER_RECORD; /* * Global variables */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil serial"; #else static char * progver = "3.08"; static char * progname = "iserial"; #endif static int vend_id = 0; static int prod_id = 0; static char fdebug = 0; static char fpicmg = 0; static char freadonly = 0; static char fdoanyway = 0; static char fSetUser3 = 0; /* =1 set User3->admin and User1->user access*/ static char fSetPsw = 0; /* =1 set Password to user parameter */ static char fSetTMode = 0; /* =1 configure for TMode */ static char fBasebdOn = 0; /* =1 only do MUX switch BMC -> Baseboard */ static char fTModeOn = 0; /* =1 only do MUX switch Baseboard -> BMC */ static char fBMode = 0; /* =1 do Basic mode config stuff */ static char fShared = 0; /* =1 shared Basic mode & Remote console */ static char fDisable = 0; /* =1 to disable serial port IPMI */ static char fKnownMode = 0; /* =0 if unknown, =1 if TMode, =2 if BMode */ static char fgetlan = 0; static char fnotshared = 0; /* =1 if IPMI serial shared with OS/BIOS*/ static char fconsoleonly = 0; /* =1 BIOS console only, no serial mux */ static char fIPMI20 = 0; /* =1 IPMI v2.0 or greater */ static char fcanonical = 0; /* =1 IPMI v2.0 or greater */ static char fuser1admin = 0; /* =1 if default user 1 should be admin */ static char bdelim = ':'; static char bFlow = 1; /* Flow Control: 1=RTS/CTS, 0=none */ static char inactivity = 0; /* Inactivity Timeout (30 sec increments) */ static char newbaud = 0x07; /* default = 19.2K */ static uchar bootflags = 16; /* if < 16 use these bootflags */ static uchar ser_ch = SER_CH; static uchar lan_ch = LAN_CH; /* usu LAN 1 = 7 */ static uchar ser_user = 0x03; /* if -u specified, configure user 3 */ static uchar ser_access = 0x04; /* user priv 4=Admin, 3=Operator, 2=User */ static uchar usernum = 0; /* set non-zero to specify user number */ static uchar useridx = 0; /* user number index for get/show*/ static uchar max_users = 5; /* set in GetUserAccess() if unum==1 */ static uchar enabled_users = 0; /* set in GetUserAccess() if unum==1 */ static uchar show_users = 5; /* set in GetUserAccess() if unum==1 */ static char rguser[16] = "root"; /* default, settable via user param */ static char rgpasswd[PSW_LEN+1] = "password"; /* default, set via user param */ #define NLAN 27 static struct { int cmd; int sz; char desc[28]; } lanparams[NLAN] = { /* see IPMI Table 19-4 */ /* 0 */ { 0, 1, "Set in progress"}, /* 1 */ { 1, 1, "Auth type support"}, /* 2 */ { 2, 5, "Auth type enables"}, /* 3 */ { 3, 4, "IP address"}, /* 4 */ { 4, 1, "IP addr src"}, /* (DHCP/Static) */ /* 5 */ { 5, 6, "MAC addr"}, /* 6 */ { 6, 4, "Subnet mask"}, /* 7 */ { 7, 3, "IPv4 header"}, /* 8 */ { 8, 2, "Prim RMCP port "}, /* 9 */ { 9, 2, "Sec RMCP port "}, /* 10 */ {10, 1, "BMC grat ARP "}, /* 11 */ {11, 1, "grat ARP interval"}, /* 12 */ {12, 4, "Def gateway IP"}, /* 13 */ {13, 6, "Def gateway MAC"}, /* 14 */ {14, 4, "Sec gateway IP"}, /* 15 */ {15, 6, "Sec gateway MAC"}, /* 16 */ {16,18, "Community string"}, /* 17 */ {17, 1, "Num dest"}, /* 18 */ {18, 5, "Dest type"}, /* 19 */ {19, 13, "Dest address"}, /* 20 */ {96, 28, "OEM Alert String"}, /* 21 */ {97, 1, "Alert Retry Algorithm"}, /* 22 */ {98, 3, "UTC Offset"}, /* 23 */ {192, 4, "DHCP Server IP"}, /* 24 */ {193, 6, "DHCP MAC Address"}, /* 25 */ {194, 1, "DHCP Enable"}, /* 26 */ {201, 2, "Channel Access Mode (Lan)"} }; /* Special temp ids for other serial commands that aren't serial params */ #define CMDID_CA1 201 /*this is the first temp id*/ #define CMDID_UA1 202 #define CMDID_UA2 203 #define CMDID_UA3 204 #define CMDID_UA4 205 #define CMDID_MUX 210 #define CMDID_BOOT 211 #define NSER 28 /* was 32 */ static struct { int cmd; int sz; char desc[28]; } serparams[NSER] = { /* see IPMI Table 20-4 */ /* 0 */ { 0, 1, "Set in progress"}, /* 1 */ { 1, 1, "Auth type support"}, /* 2 */ { 2, 5, "Auth type enables"}, /* 3 */ { 3, 1, "Connection Mode"}, /* 4 */ { 4, 1, "Sess Inactiv Timeout"}, /* 5 */ { 5, 5, "Channel Callback"}, /* 6 */ { 6, 1, "Session Termination"}, /* 7 */ { 7, 2, "IPMI Msg Comm"}, /* 8 */ { 8, 2, "Mux Switch"}, /* 9 */ { 9, 2, "Modem Ring Time"}, /* 10 */ {10,17, "Modem Init String"}, /* 11 */ {11, 5, "Modem Escape Seq"}, /* 12 */ {12, 8, "Modem Hangup Seq"}, /* 13 */ {13, 8, "Modem Dial Command"}, /* 14 */ {14, 1, "Page Blackout Interval"}, /* 15 */ {15,18, "Community String"}, /* 16 */ {16, 1, "Num of Alert Dest"}, /* 17 */ {17, 5, "Destination Info"}, /* 18 */ {18, 1, "Call Retry Interval"}, /* 19 */ {19, 3, "Destination Comm Settings"}, /* 20 */ {20, 1, "Number Dial Strings"}, /* 21 */ {21,33, "Dest Dial String"}, /* 22 */ {22, 1, "Number Dest IP Addrs"}, /* 23 */ {23, 5, "Dest IP Address"}, /* 24 */ {29, 2, "Terminal Mode Config"}, /* 25 */ {CMDID_MUX, 1,"Get Serial MUX Status"}, /* 26 */ {CMDID_BOOT, 3,"Get Boot Options(3)"}, /* 27 */ {CMDID_CA1, 2,"Channel Access Mode (Ser)"} /* 28 *% {CMDID_UA1, 4,""}, //"Get User Access (1)", */ /* 29 *% {CMDID_UA2, 4,""}, //"Get User Access (2)", */ /* 30 *% {CMDID_UA3, 4,""}, //"Get User Access (3)", */ /* 31 *% {CMDID_UA4, 4,""} //"Get User Access (4)" */ }; static int GetDeviceID(SER_RECORD *pSerRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar inputData[24]; uchar completionCode; if (pSerRecord == NULL) return(-1); status = ipmi_cmd(GET_DEVICE_ID, inputData, 0, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { SELprintf("GetDeviceID: completion code=%x\n", completionCode); } else { // dont copy first byte (Parameter revision, usu 0x11) memcpy(pSerRecord,&responseData[0],responseLength); set_mfgid(&responseData[0],responseLength); return(0); // successful, done } } /* endif */ /* if get here, error */ return(-1); } /*end GetDeviceID() */ static int GetChanAcc(uchar chan, uchar parm, SER_RECORD *pSerRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar inputData[24]; uchar completionCode; if (pSerRecord == NULL) return(-1); responseLength = 3; inputData[0] = chan; inputData[1] = parm; /* 0x80 = active, 0x40 = non-volatile */ status = ipmi_cmd(GET_CHANNEL_ACC, inputData, 2, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { SELprintf("GetChanAcc: completion code=%x\n", completionCode); } else { memcpy(pSerRecord,&responseData[0],responseLength); return(0); // successful, done } } /* endif */ /* if get here, error */ return(-1); } /*GetChanAcc()*/ static int SetChanAcc(uchar chan, uchar parm, uchar val) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar inputData[24]; uchar completionCode; /* parm: 0x80 = active, 0x40 = set non-vol*/ responseLength = 1; inputData[0] = chan; /* channel */ inputData[1] = (parm & 0xc0) | (val & 0x3F); if (chan == lan_ch) inputData[2] = 0x04; /* LAN, don't set priv level*/ else inputData[2] = (parm & 0xc0) | 0x04; /* set Admin priv level */ /* serial defaults to 0x02 = User priv level */ status = ipmi_cmd(SET_CHANNEL_ACC, inputData, 3, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { SELprintf("SetChanAcc: completion code=%x\n", completionCode); } else { return(0); // successful, done } } /* endif */ /* if get here, error */ return(-1); } /*SetChanAcc()*/ static int GetSerEntry(uchar subfunc, uchar bset, SER_RECORD *pSerRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; uchar chan; if (pSerRecord == NULL) { if (fdebug) printf("GetSerEntry: error, output buffer is NULL\n"); return (-1); } chan = ser_ch; /* sample: 0=IPMB, 1=EMP/serial, 6=LAN2, 7=LAN1 */ inputData[0] = chan; // flags, channel 3:0 (1=EMP) inputData[1] = subfunc; // Param selector inputData[2] = bset; // Set selector inputData[3] = 0; // Block selector if (subfunc == 10) { /*modem init string*/ inputData[3] = 1; /*blocks start with 1*/ } else if (subfunc == 21) { inputData[3] = 1; /*blocks start with 1*/ } status = ipmi_cmd(GET_SER_CONFIG, inputData, 4, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { if (completionCode == 0x80) SELprintf("GetSerEntry(%d): Parameter not supported\n", subfunc); else SELprintf("GetSerEntry(%d): completion code=%x\n", subfunc,completionCode); // responseData[0]); } else { // dont copy first byte (Parameter revision, usu 0x11) memcpy(pSerRecord,&responseData[1],responseLength-1); pSerRecord->data[responseLength-1] = 0; //successful, done return(0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) printf("GetSerEntry: ipmi_cmd status=%d, completion code=%d\n", status,completionCode); return -1; } static int SetSerEntry(uchar subfunc, SER_RECORD *pSerRecord, int reqlen) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; if (pSerRecord == NULL) { if (fdebug) printf("SetSerEntry(%d): error, input buffer is NULL\n", subfunc); return (-1); } inputData[0] = ser_ch; // flags, channel 3:0 (EMP) inputData[1] = subfunc; // Param selector memcpy(&inputData[2],pSerRecord,reqlen); status = ipmi_cmd(SET_SER_CONFIG, inputData, (uchar)(reqlen+2), responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { if (completionCode == 0x80) SELprintf("SetSerEntry(%d): Parameter not supported\n", subfunc); else SELprintf("SetSerEntry(%d): completion code=%x\n", subfunc, completionCode); } else { //successful, done return(0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) printf("SetSerEntry: ipmi_cmd status=%d, completion code=%d\n", status,completionCode); return -1; } /* end SetSerEntry() */ #ifdef NEEDED int SerialIsOptional(uchar bparam) { /* These Serial Parameters are for optional Modem/Callback functions. */ uchar optvals[9] = { 5, 9, 10, 11, 12, 13, 14, 20, 21 }; int rv = 0; int i; for (i = 0; i < sizeof(optvals); i++) { if (optvals[i] == bparam) { rv = 1; break; } } return(rv); } #endif int SetMiscEntry(ushort icmd, SER_RECORD *pSerRecord, int reqlen) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; if (pSerRecord == NULL) { if (fdebug) printf("SetMiscEntry: error, input buffer is NULL\n"); return (-1); } memcpy(&inputData[0],pSerRecord,reqlen); status = ipmi_cmd(icmd, inputData, (uchar)reqlen, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { printf("SetMiscEntry(%04x): completion code=%x\n", icmd,completionCode); } else { //successful if (responseLength > 1) { // skip first byte (Parameter revision, usu 0x11) memcpy(pSerRecord,&responseData[1],responseLength-1); } return(0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) printf("SetMiscEntry: ipmi_cmd status=%d, completion code=%d\n", status,completionCode); return -1; } /* end SetMiscEntry() */ int GetMiscEntry(ushort icmd, SER_RECORD *pSerRecord, int reqlen) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; if (pSerRecord == NULL) { if (fdebug) printf("GetMiscEntry: error, output buffer is NULL\n"); return (-1); } memcpy(&inputData[0],pSerRecord,reqlen); status = ipmi_cmd(icmd, inputData, (uchar)reqlen, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { if (completionCode == 0x80) printf("GetMiscEntry(%d): Parameter not supported\n", icmd); else printf("GetMiscEntry(%d): completion code=%x\n", icmd,completionCode); } else { //successful if (responseLength > 1) memcpy(pSerRecord,&responseData[0],responseLength); return(0); } } if (fdebug) printf("GetMiscEntry(%d): ipmi_cmd status=%d, completion code=%x\n", icmd,status,completionCode); return -1; } /* end GetMiscEntry() */ void ShowUserAccess(uchar unum, uchar c0, uchar c1, uchar c2, uchar c, char *name) { /* channel is always ser_ch */ if (unum == 1 && !fcanonical) { printf("Users: showing %d of max %d users (%d enabled)\n", show_users,max_users,enabled_users); } printf("Get User Access(%d)%c %02x %02x %02x %02x%c ", unum,bdelim,c0,c1,c2,c,bdelim); if (c & 0x10) printf("IPMI, "); c = (c & 0x0f); switch(c) { case 1: printf("Callback"); break; case 2: printf("User "); break; case 3: printf("Operator"); break; case 4: printf("Admin"); break; case 5: printf("OEM "); break; case 0x0f: printf("No access"); break; default: printf("Reserved"); } printf(" (%s)\n",name); } int GetUserAccess(uchar unum, uchar *rdata, char *name) { int rv; /* rdata must be at least 2 bytes, and name must be at least 16 bytes */ rdata[0] = ser_ch; /* channel# */ rdata[1] = unum; /* user# */ rv = GetMiscEntry(GET_USER_ACCESS, (SER_RECORD *)rdata, 2); if (rv == 0 && name != NULL) { name[0] = unum; /* user# */ rv = GetMiscEntry(GET_USER_NAME, (SER_RECORD *)name, 1); if (rv != 0) name[0] = 0; rv = 0; } if (unum == 1) { /*get max_users and enabled_users*/ max_users = rdata[0] & 0x3f; enabled_users = rdata[1] & 0x3f; // if (enabled_users > show_users) show_users = enabled_users; if (show_users > max_users) show_users = max_users; } if (rv == 0) ShowUserAccess(unum,rdata[0],rdata[1],rdata[2],rdata[3],name); else printf("Get User Access(%d): error %d\n",unum,rv); return(rv); } static int GetLanEntry(uchar subfunc, SER_RECORD *pSerRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; uchar chan; uchar bset; if (pSerRecord == NULL) { if (fdebug) printf("GetLanEntry: error, output buffer is NULL\n"); return (-1); } chan = lan_ch; if (subfunc == 18 || subfunc == 19) bset = 1; /* dest id = 1 */ else bset = 0; inputData[0] = chan; // flags, channel 3:0 (LAN 1) inputData[1] = subfunc; // Param selector (3 = ip addr) inputData[2] = bset; // Set selector inputData[3] = 0; // Block selector status = ipmi_cmd(GET_LAN_CONFIG, inputData, 4, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { SELprintf("GetLanEntry: completion code=%x\n", completionCode); // responseData[0]); } else { // dont copy first byte (Parameter revision, usu 0x11) memcpy(pSerRecord,&responseData[1],responseLength-1); pSerRecord->data[responseLength-1] = 0; //successful, done return(0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) printf("GetLanEntry: ipmi_cmd status=%d, completion code=%d\n", status,completionCode); return -1; } /* end GetLanEntry() */ #ifdef NOT static int SetLanEntry(uchar subfunc, SER_RECORD *pSerRecord, int reqlen) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; if (pSerRecord == NULL) { if (fdebug) printf("SetLanEntry: error, input buffer is NULL\n"); return (-1); } inputData[0] = lan_ch; // flags, channel 3:0 (LAN 1) inputData[1] = subfunc; // Param selector (3 = ip addr) memcpy(&inputData[2],pSerRecord,reqlen); status = ipmi_cmd(SET_LAN_CONFIG,inputData,(uchar)(reqlen+2),responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { SELprintf("SetLanEntry: completion code=%x\n", completionCode); // responseData[0]); } else { //successful, done return(0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) printf("SetLanEntry: ipmi_cmd status=%d, completion code=%d\n", status,completionCode); return -1; } /* end SetLanEntry() */ #endif static int ReadSELinfo() { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar completionCode; uchar inputData[6]; int status; status = ipmi_cmd(GET_SEL_INFO, inputData, 0, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if (fdebug) SELprintf("Code %d SEL Ver %d Support %d\n", completionCode, responseData[0], responseData[13] ); //successful, done return(0); } else return(1); } /*end ReadSELinfo()*/ #define NBAUDS 10 static struct { unsigned char val; char str[8]; } mapbaud[NBAUDS] = { { 6, "9600" }, { 6, "9.6K" }, { 7, "19.2K" }, { 7, "19200" }, { 8, "38.4K" }, { 8, "38400" }, { 9, "57.6K" }, { 9, "57600" }, { 10, "115.2K" }, { 10, "115200" } }; static unsigned char Str2Baud(char * str) { unsigned char baud = 0; int i, n, len; len = (int)strlen(str); for (i = 0; i < len; i++) /*toupper*/ if (str[i] >= 'a' && str[i] <= 'z') str[i] &= 0x5F; for (i = 0; i < NBAUDS; i++) { n = (int)strlen(mapbaud[i].str); if (strncmp(str,mapbaud[i].str,n) == 0) { baud = mapbaud[i].val; break; } } if (i == NBAUDS || baud == 0) { printf("Invalid -B parameter value (%s), using 19.2K.\n",str); i = 1; /* default is 19.2K */ baud = mapbaud[i].val; /* =7 */ } if (fdebug) printf("new baud = %02x (%s)\n",baud,mapbaud[i].str); return(baud); } static char *Baud2Str(unsigned char bin) { char *baudstr; unsigned char b; b = bin & 0x0f; switch(b) { case 6: baudstr = "9600 "; break; case 7: baudstr = "19.2k"; break; case 8: baudstr = "38.4k"; break; case 9: baudstr = "57.6k"; break; case 10: baudstr = "115.2k"; break; default: baudstr = "nobaud"; } return(baudstr); } void ShowChanAccess(uchar chan, char *tag, uchar access, uchar access2) { printf("Channel Access Mode(%d=%s)%c %02x %02x %c ", chan,tag,bdelim,access,access2,bdelim); switch (access & 0x03) { case 0: printf("Access = Disabled, "); break; case 1: printf("Access = Pre-Boot, "); break; case 2: printf("Access = Always Avail, "); break; case 3: printf("Access = Shared, "); break; default: break; } if (access & 0x20) printf("PEF Alerts Disabled\n"); /*0*/ else printf("PEF Alerts Enabled\n"); /*1*/ } static int valid_priv(int c) { int rv; switch(c) { case 1: case 2: case 3: case 4: case 5: case 0x0f: rv = 1; break; default: rv = 0; break; } return(rv); } #ifdef METACOMMAND int i_serial(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int ret; SER_RECORD SerRecord; char uname[16]; int i, idx; int c; int rlen; uchar iData[2]; uchar rData[10]; uchar cc; int j; uchar bset; uchar nalert, ndial, ndest; uchar ialert, idial, idest; uchar authmask = 0; char mystr[80]; // progname = argv[0]; printf("%s ver %s \n",progname,progver); if (argc <= 1) freadonly = 1; /* default to readonly if no options */ while ( (c = getopt( argc, argv,"abcdef:gi:lm:n:p:#:q:rstu:v:xB:F:T:V:J:EYP:N:R:U:X:Z:?")) != EOF ) switch(c) { case 'x': fdebug = 1; break; case 'r': freadonly = 1; break; case 'l': fgetlan = 1; break; case 'd': fDisable = 1; freadonly = 0; break; case 'a': fcanonical = 1; /* canonical mode with delimeter */ bdelim = BDELIM; break; case 'c': /* configure Terminal Mode & Console */ case 't': fSetTMode = 1; /* set Terminal Mode & Console */ freadonly = 0; break; case 'e': fSetTMode = 1; /* set Terminal Mode not shared*/ fnotshared = 1; /* no BIOS console, not shared */ freadonly = 0; break; case 'g': fSetTMode = 1; /* set Terminal Mode, but BCR only */ fconsoleonly = 1; /* BIOS console only, disable mux */ freadonly = 0; break; case 'b': fBMode = 1; /* set Basic Mode only */ freadonly = 0; break; case 's': fBMode = 1; /* set Basic Mode & Console */ fShared = 1; freadonly = 0; break; case 'f': i = atoi(optarg); /*flow control*/ if (i >= 0 && i < 2) bFlow = (uchar)i; break; case 'i': i = atoi(optarg); /*inactivity timeout*/ if (i > 0 && i < 30) inactivity = 1; else inactivity = i / 30; break; case 'B': newbaud = Str2Baud(optarg); break; case 'm': /* set MUX to specific value */ i = atoi(optarg); if (fdebug) printf("MUX Mode %d\n",i); switch(i) { case 0: fBasebdOn = 1; break; case 1: fTModeOn = 1; break; default: fBasebdOn = 1; } break; case 'u': strncpy(rguser,optarg,16); rguser[15] = 0; /* Use specified user #3, and set user 1 to not admin */ fSetUser3 = 1; break; case 'p': strncpy(rgpasswd,optarg,PSW_LEN); rgpasswd[PSW_LEN] = 0; fSetPsw = 1; /* Hide password from 'ps' */ memset(optarg, ' ', strlen(optarg)); break; case 'q': case '#': usernum = atob(optarg); if (usernum > 15) usernum = 0; /*MAX_IPMI_USERS = 4*/ break; case 'n': ser_ch = atob(optarg); if (ser_ch > MAXCHAN) ser_ch = SER_CH; /*default=1*/ break; case 'v': /*user privilege level access */ i = atoi(optarg); if (valid_priv(i)) ser_access = i & 0x0f; else printf("Invalid privilege -v %d, using Admin\n",i); break; case 'X': bootflags = atob(optarg); fdoanyway = 1; /* undocumented, for test only */ break; case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: printf("Usage: %s [-bcdefglmnq#rstxB -u user -p passwd -NUPREFTVY]\n",progname); printf(" -b configure serial port for Basic Mode\n"); printf(" -c Configure serial port for shared Terminal Mode & Console\n"); printf(" -d Disable serial port for IPMI use.\n"); printf(" -e configure serial port for Terminal Mode only\n"); printf(" -f0 Flow control: 0=none, 1=RTS/CTS(default)\n"); printf(" -g configure serial port for console only, with BMode CTS\n"); printf(" -s configure serial port for Shared Basic Mode & Remote Console\n"); printf(" -l show some LAN parameters also\n"); printf(" -m0 switch MUX to Normal baseboard operation\n"); printf(" -m1 switch MUX to BMC operation (BMode or TMode)\n"); printf(" -B bval set Baud to bval for serial port\n"); printf(" -n ser_chan serial channel Number (default=1)\n"); printf(" -p password set Password for EMP TMode login\n"); printf(" -u username set Username for EMP TMode login\n"); printf(" -q/-# User number of Username for EMP\n"); printf(" -r Read-only, view serial port parameters (default)\n"); printf(" -t Configure serial port for shared Terminal Mode & Console (same as -c)\n"); printf(" -v4 access priVilege: 4=Admin, 3=Operator, 2=User\n"); printf(" -x eXtra debug messages\n"); print_lan_opt_usage(0); ret = ERR_USAGE; goto do_exit; } if (is_remote() && !freadonly) parse_lan_options('V',"4",0); ret = GetDeviceID( &SerRecord); if (ret != 0) { goto do_exit; } else { uchar ipmi_maj, ipmi_min; uchar *devrec; devrec = &SerRecord.data[0]; ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; vend_id = devrec[6] + (devrec[7] << 8) + (int)(devrec[8] << 16); prod_id = devrec[9] + (devrec[10] << 8); show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); if ((ipmi_maj == 0) || (ipmi_maj == 1 && ipmi_min < 5)) { /* IPMI 0.9 and 1.0 dont support this. */ printf("This system does not support EMP Terminal Mode.\n"); if (!fdoanyway) { ret = LAN_ERR_NOTSUPPORT; goto do_exit; } } if (ipmi_maj >= 2) fIPMI20 = 1; /* Determine if Basic or Terminal Mode is supported by product id */ if (vend_id == VENDOR_INTEL) { /*Intel*/ switch(prod_id) { case 0x4311: fKnownMode = 1; break; /*NSI2U, BMode*/ case 0x000C: fKnownMode = 1; break; /*TSRLT2, BMode*/ case 0x0100: fKnownMode = 1; break; /*Tiger2, BMode*/ case 0x001B: fKnownMode = 2; break; /*TIGPR2U, TMode*/ case 0x0022: fKnownMode = 2; break; /*TIGI2U, TMode*/ case 0x0026: fKnownMode = 2; break; /*Alcolu, TMode*/ case 0x0028: fKnownMode = 2; break; /*Alcolu, TMode*/ case 0x0811: fKnownMode = 2; break; /*TIGW1U, TMode*/ case 0x003E: fKnownMode = 2; /*NSN2U/CG2100, TMode*/ set_max_kcs_loops(URNLOOPS); /*longer KCS timeout*/ break; default: break; } } else if (vend_id == VENDOR_NSC) { /*NSC*/ if (prod_id == 0x4311) fKnownMode = 1; /*TIGPT1U, No EMP*/ } /* else * other vend_id, leave defaults */ if (fKnownMode > 0) { /* Adjust if we know that the user set the wrong one. */ if (fKnownMode == 1 && fSetTMode == 1) { printf("Adjusting from Terminal Mode to Basic Mode\n"); fSetTMode = 0; fBMode = 1; fShared = 1; } else if (fKnownMode == 2 && fBMode == 1) { printf("Adjusting from Basic Mode to Terminal Mode\n"); fSetTMode = 1; fBMode = 0; } } } /*end-else have device_id */ ret = ipmi_getpicmg( &SerRecord.data[0], 16, fdebug); if (ret == 0) fpicmg = 1; ret = ReadSELinfo(); if (ret == 0) { /* talking to BMC ok */ /* find the first Serial channel via Channel Info */ for (j = 1; j < MAXCHAN; j++) { iData[0] = (uchar)j; /*channel #*/ rlen = sizeof(rData); ret = ipmi_cmd(GET_CHANNEL_INFO, iData, 1, rData, &rlen, &cc, 0); if (ret != 0) break; if (rData[1] == 4) { /* 4 = LAN type*/ if (fdebug) printf("chan[%d] = lan\n",j); lan_ch = (uchar)j; } else if (rData[1] == 5) { /* 5 = Serial type*/ if (fdebug) printf("chan[%d] = serial\n",j); if (ser_ch != SER_CH) { /* user set it */ if (j == ser_ch) break; } else { /* find the first serial channel */ ser_ch = (uchar)j; break; } } else /* 7 = SMBus, 12 = System Interface */ if (fdebug) printf("chan[%d] = %d\n",j,rData[1]); } if (fdebug) printf("ser_ch = %d\n",ser_ch); if (j >= MAXCHAN) { printf("No serial channel support found (channel %d)\n",ser_ch); ret = LAN_ERR_NOTSUPPORT; goto do_exit; } if (fdebug && fSetUser3 == 1) printf("user %d/%d: username=%s, password=%p\n", usernum,ser_user, rguser,rgpasswd); if (fgetlan && !fcanonical) { int ival; printf("%s, GetLanEntry for channel %d ...\n",progname,lan_ch); for (idx = 0; idx < NLAN; idx++) { ival = lanparams[idx].cmd; if (ival == 8 || ival == 9) continue; /* not implemented */ if (ival >= 96 && ival <= 98) continue; /* not implemented */ if (ival == CMDID_CA1) { ret = GetChanAcc(lan_ch, 0x40, &SerRecord); } else { ret = GetLanEntry((uchar)ival, &SerRecord); } if (ret == 0) { // Show the LAN record uchar * pc; int sz; pc = (uchar *)&SerRecord; sz = lanparams[idx].sz; printf("Lan Param(%d) %s%c ",ival,lanparams[idx].desc,bdelim); if (ival == 16) { printf("%s \n",pc); /* string */ } else { /* print results for others */ for (i = 0; i < sz; i++) { if (ival == 3 || ival == 6 || ival == 12 || ival == 14 || ival == 192) printf("%d ",pc[i]); /* IP addresses in dec */ else printf("%02x ",pc[i]); /* show in hex */ } /* if (ival == 4) { pc[0]: 01 = static, 02 = DHCP } */ printf("\n"); } } else /* ret != 0 */ printf("GetLanEntry(%d), ret = %d\n",ival,ret); } /*end for*/ } printf("%s, GetSerEntry for channel %d ...\n",progname,ser_ch); nalert = 1; ialert = 1; ndial = 1; idial = 1; ndest = 1; idest = 1; for (idx = 0; idx < NSER; idx++) { int ival; ival = serparams[idx].cmd; /* * ival is either the Serial Param# or a temp id. * Do the appropriate Get command, based on ival. */ if (ival == CMDID_CA1) { ret = GetChanAcc(ser_ch, 0x40, &SerRecord); } else if (ival == CMDID_UA1) { useridx = 1; ret = GetUserAccess(useridx,(uchar *)&SerRecord,uname); } else if (ival == CMDID_UA2) { useridx = 2; ret = GetUserAccess(useridx,(uchar *)&SerRecord,uname); } else if (ival == CMDID_UA3) { useridx = 3; ret = GetUserAccess(useridx,(uchar *)&SerRecord,uname); } else if (ival == CMDID_UA4) { useridx = 4; if (fIPMI20 == 0) continue; /* IPMI 1.5 only has 3 users */ ret = GetUserAccess(useridx,(uchar *)&SerRecord,uname); } else if (ival == CMDID_MUX) { SerRecord.data[0] = ser_ch; /* channel 1 = EMP */ SerRecord.data[1] = 0x00; /* just get MUX status */ ret = SetMiscEntry(SET_SER_MUX, &SerRecord, 2); } else if (ival == CMDID_BOOT) { SerRecord.data[0] = 0x03; /* Boot Param 3 */ SerRecord.data[1] = 0x00; /* Set Selector */ SerRecord.data[2] = 0x00; /* %%%% */ ret = GetMiscEntry(GET_BOOT_OPTIONS, &SerRecord, 3); } else { if (fcanonical) { switch(ival) { /*only show certain parameters*/ case 3: case 4: case 6: case 7: case 8: case 29: break; default: continue; break; } } if (vend_id == VENDOR_SUPERMICROX && ival == 8) continue; if (vend_id == VENDOR_SUPERMICRO && ival == 8) continue; if (ival == 17 || ival == 19) bset = ialert; else if (ival == 21) bset = idial; else if (ival == 23) bset = idest; else bset = 0; /*default*/ ret = GetSerEntry((uchar)ival, bset, &SerRecord); } /* * Now the Get command is done, check the status, and * show the raw output. */ if (ret == 0) { // Show the SER record uchar * pc; int sz; pc = (uchar *)&SerRecord; sz = serparams[idx].sz; /* save some input data for later reuse */ if (ival == 16) nalert = pc[0]; else if (ival == 20) ndial = pc[0]; else if (ival == 22) ndest = pc[0]; if (ival == CMDID_CA1) ; else if (ival > CMDID_CA1) printf("%s%c ",serparams[idx].desc,bdelim); else printf("Serial Param(%d) %s%c ",ival,serparams[idx].desc,bdelim); if (ival == 1) { /* Auth Type support*/ authmask = pc[0]; /* auth type support mask */ mystr[0] = 0; if (authmask & 0x01) strcat(mystr,"None "); if (authmask & 0x02) strcat(mystr,"MD2 "); if (authmask & 0x04) strcat(mystr,"MD5 "); if (authmask & 0x10) strcat(mystr,"Pswd "); if (authmask & 0x20) strcat(mystr,"OEM "); printf("%02x %c %s\n",authmask,bdelim,mystr); } else if (ival == 10) { /* modem init string */ pc[sz] = 0; printf("%02x %s\n",pc[0],&pc[1]); } else if (ival == 21) { /* modem dial string */ pc[sz] = 0; printf("%02x %02x %s\n",pc[0],pc[1],&pc[2]); } else if ((ival >= 11 && ival <= 13) || ival == 15) { /* strings */ pc[sz] = 0; printf("%s\n",pc); } else if (ival == 23) { /* Dest IP Address */ printf("%02x %d %d %d %d\n", pc[0], /*dest index*/ pc[1],pc[2],pc[3],pc[4]); } else if (ival == CMDID_CA1) { /* Channel Access */ ShowChanAccess(ser_ch,"Ser",pc[0],pc[1]); } else if (ival == CMDID_UA1 || ival == CMDID_UA2 || ival == CMDID_UA3 || ival == CMDID_UA4) { // ShowUserAccess(useridx,pc[0],pc[1],pc[2],pc[3],uname); } /*endif UA*/ else /* hex data */ { for (i = 0; i < sz; i++) { printf("%02x ",pc[i]); /* show in hex */ } /* * Raw hex data display is complete, now do post-processing. * Interpret some hex data. */ if (ival == 4) { /* Session Inactivity Timeout */ c = pc[0]; if (c == 0) strcpy(mystr,"infinite"); else sprintf(mystr,"%d sec",(c * 30)); printf(" %c %s",bdelim,mystr); } else if (ival == 7) { /*IPMI Msg Comm*/ uchar v; char *flow; char *dtr; char *baud; v = pc[0] & 0xc0; switch(v) { case 0x40: flow = "RTS/CTS"; break; case 0x80: flow = "XON/XOFF"; break; case 0x00: default: flow = "no_flow"; } if ((pc[0] & 0x20) == 0) dtr="no_DTR"; else dtr = "DTR"; baud = Baud2Str(pc[1]); printf("%c %s, %s, %s",bdelim,flow,dtr,baud); } else if (ival == 19) { /*Dest Comm Settings*/ uchar v; char *flow; char *baud; uchar chsz,parity,stopb; v = pc[1] & 0xc0; switch(v) { case 0x40: flow = "RTS/CTS"; break; case 0x80: flow = "XON/XOFF"; break; case 0x00: default: flow = "no_flow"; } if ((pc[1] & 0x10) == 0) stopb = 1; else stopb = 2; if ((pc[1] & 0x08) == 0) chsz = 8; else chsz = 7; v = pc[1] & 0x07; switch(v) { case 1: parity = 'O'; break; case 2: parity = 'E'; break; case 0: default: parity = 'N'; } baud = Baud2Str(pc[2]); printf("%c %s, %d%c%d, %s",bdelim,flow,chsz,parity,stopb,baud); } #ifdef TEST /* This MUX reading is volatile and may not be accurate */ else if (ival == CMDID_MUX) { if ((pc[0] & 0x01) == 1) printf("%c BMC",bdelim); else printf("%c System",bdelim); /*BIOS*/ } #endif printf("\n"); } /*end else hex*/ } /*endif show*/ if (ival == 17 || ival == 19) { /* alert params */ if (ialert < nalert) { ialert++; idx--; /* repeat this param*/ } else ialert = 1; } if (ival == 21) { /* dial param */ if (idial < ndial) { idial++; idx--; /* repeat this param*/ } else idial = 1; } if (ival == 23) { /* dest param */ if (idest < ndest) { idest++; idx--; /* repeat this param*/ } else idest = 1; } } /*end for(idx) serial params*/ for (i = 1; i <= show_users; i++) ret = GetUserAccess((uchar)i,(uchar *)&SerRecord,uname); if (!freadonly) { /* set serial channel parameters */ uchar access; if (fBasebdOn) { /* -m0 */ SerRecord.data[0] = ser_ch; /* channel 1 = EMP */ SerRecord.data[1] = 0x03; /* force switch to Baseboard */ ret = SetMiscEntry(SET_SER_MUX, &SerRecord, 2); printf("SetSerialMux(System), ret = %d, value = %02x\n", ret,SerRecord.data[0]); } else if (fTModeOn) { /* -m1 */ SerRecord.data[0] = ser_ch; /* channel 1 = EMP */ SerRecord.data[1] = 0x04; /* force switch to BMC for TMode */ ret = SetMiscEntry(SET_SER_MUX, &SerRecord, 2); printf("SetSerialMux(BMC), ret = %d, value = %02x\n", ret,SerRecord.data[0]); } else if (fDisable) { /* -d */ /* * DISABLE SERIAL CHANNEL ACCESS */ if (vend_id == VENDOR_INTEL && fuser1admin) { /* First, make sure null user (1) has admin privileges again */ SerRecord.data[0] = 0x90 | ser_ch; /*0x91*/ SerRecord.data[1] = 0x01; /*user 1*/ SerRecord.data[2] = ser_access; /* usu 0x04 admin access*/ SerRecord.data[3] = 0x00; ret = SetMiscEntry(SET_USER_ACCESS, &SerRecord, 4); printf("SetUserAccess(1/%02x), ret = %d\n",ser_access,ret); } if (usernum != 0) { /*disable usernum if specified*/ SerRecord.data[0] = 0x80 | ser_ch; /*0x81*/ SerRecord.data[1] = usernum; SerRecord.data[2] = 0x0F; /*No access*/ SerRecord.data[3] = 0x00; ret = SetMiscEntry(SET_USER_ACCESS, &SerRecord, 4); printf("SetUserAccess(%d/none), ret = %d\n",usernum,ret); } ret = SetChanAcc(ser_ch, 0x80, 0x20); /*vol access=disabled*/ if (fdebug) printf("SetChanAcc(ser/disable), ret = %d\n",ret); ret = SetChanAcc(ser_ch, 0x40, 0x20); /*nvol access=disabled*/ printf("SetChanAcc(ser/disable), ret = %d\n",ret); ret = GetChanAcc(ser_ch, 0x40, &SerRecord); access = SerRecord.data[0]; printf("GetChanAcc(ser/disable), ret = %d, new value = %02x\n", ret,access); if ((vend_id != VENDOR_SUPERMICROX) && (vend_id != VENDOR_SUPERMICRO)) { /* Also disable the Serial Parameter 3: Connection Mode */ SerRecord.data[0] = 0x00; /* Connection Mode = none */ ret = SetSerEntry(3, &SerRecord,1); printf("SetSerEntry(3/disable), ret = %d\n",ret); } } else if (fSetTMode || fBMode) { /* * ENABLE SERIAL CHANNEL ACCESS * Enable: configure everything for TMode and/or BMode * * Set Serial/EMP Channel Access * Use serial channel in shared mode * 0x20 means alerting=off, disabled (system only) * 0x22 means alerting=off, always avail * which would only show BMC messages, not OS messages * 0x23 means alerting=off, always avail + shared + user-auth on * 0x2A means alerting=off, always avail + user-auth off * 0x2B means alerting=off, always avail + shared + user-auth off * 0x0B means alerting=on, always avail + shared + user-auth off * SSU won't set 0x2B, but we need shared access mode. */ if (fconsoleonly) { access = ALWAYS_NOAUTH; /*0x2A*/ } else if (fnotshared) { /* serial IPMI, but no console (-e only) */ if (fSetTMode) access = ALWAYS_NOAUTH; /*0x2A*/ else access = ALWAYS_AUTH; /*0x22*/ } else { /* shared with BIOS console, normal */ if (fSetTMode) access = SHARED_NOAUTH; /*0x2B*/ else access = SHARED_AUTH; /*0x23*/ } ret = SetChanAcc(ser_ch, 0x80, access); if (fdebug) printf("SetChanAcc(ser/active), ret = %d\n",ret); ret = SetChanAcc(ser_ch, 0x40, access); printf("SetChanAcc(ser), ret = %d\n",ret); ret = GetChanAcc(ser_ch, 0x80, &SerRecord); if (fdebug) { access = SerRecord.data[0]; printf("GetChanAcc(ser/active), ret = %d, new value = %02x\n", ret,access); } ret = GetChanAcc(ser_ch, 0x40, &SerRecord); access = SerRecord.data[0]; printf("GetChanAcc(ser), ret = %d, new value = %02x\n", ret,access); ShowChanAccess(ser_ch,"ser",access,SerRecord.data[1]); /* Needed if (fSetTMode), otherwise extra. */ { /* auth types: pswd, MD5, MD2, none */ if (authmask == 0) authmask = 0x17; SerRecord.data[0] = (0x16 & authmask); /*Callback level*/ SerRecord.data[1] = (0x16 & authmask); /*User level */ SerRecord.data[2] = (0x16 & authmask); /*Operator level*/ SerRecord.data[3] = (0x16 & authmask); /*Admin level */ SerRecord.data[4] = 0x00; /*OEM level*/ ret = SetSerEntry(2, &SerRecord,5); printf("SetSerEntry(2), ret = %d\n",ret); } if (fconsoleonly) SerRecord.data[0] = 0x81; /*direct, Basic only */ else if (fBMode) SerRecord.data[0] = 0x83; /*direct; PPP & Basic */ else SerRecord.data[0] = 0x87; /*direct; TMode, PPP, Basic*/ if ((vend_id != VENDOR_SUPERMICROX) && (vend_id != VENDOR_SUPERMICRO)) { ret = SetSerEntry(3, &SerRecord,1); printf("SetSerEntry(3), ret = %d\n",ret); } /* * BMode inactivity timeout = 2 (* 30 sec = 60 sec) * TMode inactivity timeout = 0 (infinite) */ if (fBMode) SerRecord.data[0] = 0x02; else SerRecord.data[0] = inactivity; /*usu 0, infinite*/ ret = SetSerEntry(4, &SerRecord,1); printf("SetSerEntry(4), ret = %d\n",ret); if ((vend_id != VENDOR_SUPERMICROX) && (vend_id != VENDOR_SUPERMICRO)) { // SerRecord.data[0] = 0x02; /* enable inactivity, ignore DCD */ SerRecord.data[0] = 0x03; /* enable inactivity, enable DCD */ ret = SetSerEntry(6, &SerRecord,1); printf("SetSerEntry(6), ret = %d\n",ret); /* flow control: 60=RTS/CTS+DTR, 20=none+DTR */ SerRecord.data[0] = (bFlow << 6) | 0x20; SerRecord.data[1] = newbaud; /* baud default = 19.2K bps */ ret = SetSerEntry(7, &SerRecord,2); printf("SetSerEntry(7) baud %s, ret = %d\n",Baud2Str(newbaud),ret); if (fBMode) { SerRecord.data[0] = 0x1e; /* mux 2way control, GetChanAuth, PPP */ } else { /*TMode*/ // SerRecord.data[0] = 0x1e; /* mux 2way control,GetChanAuth,PPP */ SerRecord.data[0] = 0x16; /* mux 2way control, GetChanAuth,no PPP*/ /* 2way: ( and Q */ } if (fconsoleonly) SerRecord.data[1] = 0x09; /* enable serial port sharing, hb=not */ else if (fBMode && !fShared) /* Basic Mode and NOT shared */ SerRecord.data[1] = 0x0a; /* enable serial port sharing,heartbeat*/ else SerRecord.data[1] = 0x08; /* enable serial port sharing, hb=off */ ret = SetSerEntry(8, &SerRecord,2); printf("SetSerEntry(8), ret = %d\n",ret); } if (fSetUser3) { if (usernum == 0) usernum = ser_user; /* user 3 */ /* * Set up admin user for Serial User (usu User# 3) * Username: root * Password: password * * cmdtool 20 18 45 3 72 6F 6F 74 0 0 0 0 0 0 0 0 0 0 0 0 * cmdtool 20 18 47 3 2 70 61 73 73 77 6F 72 64 0 0 0 0 0 0 0 0 * cmdtool 20 18 47 3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */ SerRecord.data[0] = usernum; /* user 3 */ memset(&SerRecord.data[1],0,16); memcpy(&SerRecord.data[1],rguser,strlen(rguser)); ret = SetMiscEntry(SET_USER_NAME, &SerRecord, 17); printf("SetUserName(%d), ret = %d\n",usernum,ret); /* set password for user 3 */ SerRecord.data[0] = usernum; SerRecord.data[1] = 0x02; memset(&SerRecord.data[2],0,PSW_LEN); memcpy(&SerRecord.data[2],rgpasswd,strlen(rgpasswd)); ret = SetMiscEntry(SET_USER_PASSWORD, &SerRecord, 2+PSW_LEN); printf("SetUserPassword(%d,2), ret = %d\n",usernum,ret); /* enable user 3 */ SerRecord.data[0] = usernum; SerRecord.data[1] = 0x01; memset(&SerRecord.data[2],0,PSW_LEN); ret = SetMiscEntry(SET_USER_PASSWORD, &SerRecord, 2+PSW_LEN); printf("SetUserPassword(%d,1), ret = %d\n",usernum,ret); /* Testing User #3 password */ // cmdtool 20 18 47 3 3 70 61 73 73 77 6F 72 64 0 0 0 0 0 0 0 0 SerRecord.data[0] = usernum; SerRecord.data[1] = 0x03; memset(&SerRecord.data[2],0,PSW_LEN); memcpy(&SerRecord.data[2],rgpasswd,strlen(rgpasswd)); ret = SetMiscEntry(SET_USER_PASSWORD, &SerRecord, 2+PSW_LEN); printf("SetUserPassword(%d,3), ret = %d\n",usernum,ret); /* Set User #3 access up w/ ADMIN privilege for serial channel */ // cmdtool 20 18 43 91 3 4 0 SerRecord.data[0] = 0x90 | ser_ch; /*0x91*/ SerRecord.data[1] = usernum; /* user 3 */ SerRecord.data[2] = ser_access; /*usu 0x04; Admin*/ SerRecord.data[3] = 0x00; ret = SetMiscEntry(SET_USER_ACCESS, &SerRecord, 4); printf("SetUserAccess(%d/%02x), ret = %d\n",usernum,ser_access,ret); if (ipmi_reserved_user(vend_id,0x01) == 0) { /* Set NULL user access up w/ USER privilege for serial channel */ // cmdtool 20 18 43 91 1 2 0 SerRecord.data[0] = 0x90 | ser_ch; /*0x91*/ SerRecord.data[1] = 0x01; /* user 1 (default) */ SerRecord.data[2] = 0x02; /* user privilege */ SerRecord.data[3] = 0x00; ret = SetMiscEntry(SET_USER_ACCESS, &SerRecord, 4); printf("SetUserAccess(1/user), ret = %d\n",ret); } } else { /* No username specified, use NULL user 1 for Serial */ if (ipmi_reserved_user(vend_id,0x01) == 0) { /* Set NULL user password, if specified */ if (fSetPsw) { SerRecord.data[0] = 0x01; /*user 1*/ SerRecord.data[1] = 0x02; memset(&SerRecord.data[2],0,PSW_LEN); memcpy(&SerRecord.data[2],rgpasswd,strlen(rgpasswd)); ret = SetMiscEntry(SET_USER_PASSWORD, &SerRecord, 2+PSW_LEN); printf("SetUserPassword(1,2), ret = %d\n",ret); /* make sure user 1 is enabled */ SerRecord.data[0] = 0x01; SerRecord.data[1] = 0x01; memset(&SerRecord.data[2],0,PSW_LEN); ret = SetMiscEntry(SET_USER_PASSWORD, &SerRecord, 2+PSW_LEN); printf("SetUserPassword(1,1), ret = %d\n",ret); } /* Set NULL user access up w/ ADMIN privilege for serial channel */ // cmdtool 20 18 43 91 1 4 0 SerRecord.data[0] = 0x90 | ser_ch; /*0x91*/ SerRecord.data[1] = 0x01; /* user 1 */ SerRecord.data[2] = ser_access; /* admin */ SerRecord.data[3] = 0x00; ret = SetMiscEntry(SET_USER_ACCESS, &SerRecord, 4); printf("SetUserAccess(1/%02x), ret = %d\n",ser_access,ret); } } if (fSetTMode) { /* * Set the TMode configuration: * Enable line editing * Delete seq = bksp-sp-bksp * Enable echo * Handshake (hb) = off * Output newline seq = CR-LF * Input newline seq = CR */ if ((vend_id != VENDOR_SUPERMICROX) && (vend_id != VENDOR_SUPERMICRO)) { #ifdef TEST SerRecord.data[0] = 0xA6; /* sets bit for volatile - wrong */ SerRecord.data[1] = 0x11; ret = SetSerEntry(29, &SerRecord,2); #endif SerRecord.data[0] = 0x66; SerRecord.data[1] = 0x11; ret = SetSerEntry(29, &SerRecord,2); printf("SetSerEntry(29), ret = %d\n",ret); } /* Force mux switch to the BMC and start talking... */ /* Set Serial/Modem Mux */ /* cmdtool 20 30 12 1 4 */ SerRecord.data[0] = ser_ch; /* channel 1 = EMP */ SerRecord.data[1] = 0x02; /* was 0x04 to force switch to BMC */ i = SetMiscEntry(SET_SER_MUX, &SerRecord, 2); printf("SetSerialMux(BMC), ret = %d, value = %02x\n", i,SerRecord.data[0]); } /*endif fSetTMode*/ else { /* fBMode */ if (fShared) { uchar bval; /* workaround for BMC bug w BIOS Console Redirect */ SerRecord.data[0] = 0x03; /* Boot Param 3 */ if (bootflags < 16) { /* user specified a boot flag */ SerRecord.data[1] = bootflags; /* Flags */ bval = SerRecord.data[1]; ret = SetMiscEntry(SET_BOOT_OPTIONS, &SerRecord, 2); printf("SetBootOptions(3), new value = %02x, ret = %d\n", bval,ret); } /* Force mux switch to the Baseboard initially */ SerRecord.data[0] = ser_ch; /* channel 1 = EMP */ SerRecord.data[1] = 0x03; /* force switch to Baseboard */ i = SetMiscEntry(SET_SER_MUX, &SerRecord, 2); printf("SetSerialMux(System), ret = %d, value = %02x\n", i,SerRecord.data[0]); } else { /* not shared, BMode only */ /* Force mux switch to the BMC and start talking... */ SerRecord.data[0] = ser_ch; /* channel 1 = EMP */ SerRecord.data[1] = 0x04; /* 0x04 to force switch to BMC */ i = SetMiscEntry(SET_SER_MUX, &SerRecord, 2); printf("SetSerialMux(BMC), ret = %d, value = %02x\n", i,SerRecord.data[0]); } } /*end-else BMode*/ } /*end-else Enable (not Disable) */ else { /*not enable or disable BMode/TMode */ if (!fcanonical) printf("Please specify a configuration mode (b,d,e,m,s,t)\n"); } } /*endif not readonly */ } /* endif ok */ do_exit: ipmi_close_(); // show_outcome(progname,ret); return(ret); } /* end main()*/ /************************ DPC configuration stuff on serial. 16:25:08.165 outgoing: set system boot options[08] 20 00 E0 81 6C 08 02 02 07 16:25:08.165 outgoing: set system boot options[08] 20 00 E0 81 70 08 06 01 0B 28 11 02 45 1F 96 3C 84 16:25:08.165 outgoing: set system boot options[08] 20 00 E0 81 74 08 04 FF FF 01 16:25:08.165 outgoing: set system boot options[08] 20 00 E0 81 78 08 03 00 FC 16:25:08.245 INCOMING: SET SYSTEM BOOT OPTIONS[08] 81 04 7B 20 6C 08 -[00]- 6C 16:25:08.245 INCOMING: SET SYSTEM BOOT OPTIONS[08] 81 04 7B 20 70 08 -[00]- 68 16:25:08.245 outgoing: set system boot options[08] 20 00 E0 81 7C 08 05 80 00 4A 00 00 2C 16:25:08.255 outgoing: chassis control[02] 20 00 E0 81 80 02 03 FA ************************/ /* end iserial.c */ ipmiutil-3.1.5/util/AnsiTerm.h0000644000076400007640000002332013566765324016326 0ustar mgportalloggers/* * AnsiTerm.h * Windows ANSI Terminal Emulation * * Author: Robert Nelson robertnelson at users.sourceforge.net * Copyright (c) 2009 Robert Nelson * * 10/07/09 Robert Nelson - Created * See ChangeLog for further changes */ /* Copyright (c) 2009, Robert Nelson 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. 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. */ #pragma once class CAnsiTerm { public: struct KeyCode { unsigned char bKeyDown:1; unsigned char bEnhanced:1; unsigned char bCapsLock:1; unsigned char bScrollLock:1; unsigned char bNumLock:1; unsigned char bShift:1; unsigned char bControl:1; unsigned char bAlt:1; unsigned char RepeatCount; unsigned char VirtualKeyCode; unsigned char AsciiChar; }; private: enum ControlCharacters { CH_NUL = 0x00, // Ignored on input CH_ENQ = 0x05, // Transmit answerback CH_BEL = 0x07, // Ring Bell CH_BS = 0x08, // Move left one character, no effect in column 0 CH_HT = 0x09, // Tab CH_LF = 0x0A, // Line feed or new line depending on line mode CH_VT = 0x0B, // Vertical tab, same as line feed CH_FF = 0x0C, // Form feed, same as line feed CH_CR = 0x0D, // Carriage return, return to column 0 CH_SO = 0x0E, // Shift Out, Invoke G1 charset CH_SI = 0x0F, // Shift In, Invoke G0 charset CH_XON = 0x11, // Resume transmission CH_XOF = 0x13, // Suspend transmission CH_CAN = 0x18, // Cancel, aborts the current control sequence CH_SUB = 0x1A, // Same as Cancel CH_ESC = 0x1B, // Escape, start of control sequence CH_DEL = 0x7F // Delete, ignored }; enum DECModes { DECCKM = 1, // Cursor Key Mode (set = application codes) DECANM = 2, // Ansi Mode (set = ansi) DECCOLM = 3, // 80/132 Column Mode (set = 132) DECSCLM = 4, // Scroll Mode (set = smooth) DECSCNM = 5, // Screen Mode (set = black on white) DECOM = 6, // Origin Mode (set = origin relative to top margin) DECAWM = 7, // Autowrap Mode (set = wrap) DECARM = 8, // Autorepeat Mode (set = repeat) DECINLM = 9, // Interlace Mode (set = interlace) DECTCEM = 25 // Text Cursor Enable Mode }; enum DisplayState { DS_None, DS_Normal, DS_UTF8, DS_Escape, DS_CSIParam, DS_DECPrivate, DS_SelectG0, DS_SelectG1 }; enum SelectedCharset { CharsetG0, CharsetG1 }; enum CharacterSet { AsciiCharset = 0, SpecialGraphicsCharset = 1, UKCharset = 2 }; enum EraseType { EraseCursorToEnd = 0, EraseBeginningToCursor = 1, EraseAll = 2 }; static const int kMaxParameterCount = 16; static const int kOutputBufferSize = 256; static const int kMinGraphicsChar = 0x5F; static const int kMaxGraphicsChar = 0x7E; static const int kColorTableSize = 16; static const WORD kDefaultAttribute = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; struct CSICode { char chCode; DisplayState dsNextState; bool (CAnsiTerm::*pfnProcess)(void); }; struct CSIFunction { char chCode; bool (CAnsiTerm::*pfnProcess)(void); }; protected: typedef struct _CONSOLE_SCREEN_BUFFER_INFOEX { ULONG cbSize; COORD dwSize; COORD dwCursorPosition; WORD wAttributes; SMALL_RECT srWindow; COORD dwMaximumWindowSize; WORD wPopupAttributes; BOOL bFullscreenSupported; COLORREF ColorTable[16]; } CONSOLE_SCREEN_BUFFER_INFOEX, *PCONSOLE_SCREEN_BUFFER_INFOEX; typedef BOOL (WINAPI *PFN_GetConsoleScreenBufferInfoEx)( HANDLE hConsoleOutput, PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx); typedef BOOL (WINAPI *PFN_SetConsoleScreenBufferInfoEx)( HANDLE hConsoleOutput, PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx); static PFN_GetConsoleScreenBufferInfoEx s_pfnGetConsoleScreenBufferInfoEx; static PFN_SetConsoleScreenBufferInfoEx s_pfnSetConsoleScreenBufferInfoEx; private: static CSICode s_CSITable[]; static CSIFunction s_DECFunction[]; static CSIFunction s_CSIFunction[]; static wchar_t s_GraphicChars[kMaxGraphicsChar - kMinGraphicsChar + 1]; static wchar_t s_OemToUnicode[256]; static COLORREF s_ColorTable[kColorTableSize]; public: CAnsiTerm(void); virtual ~CAnsiTerm(void); void WindowSizeChanged(bool bInitial); int ProcessInput(KeyCode keyCode, unsigned char *pOutput, int iOutputLen); bool ProcessOutput(const unsigned char *szData, int iLength); protected: virtual bool ResetTerm(void); virtual bool GetCursorPosition(void); virtual bool SetCursorPosition(void); virtual bool DisplayCursor(void); virtual bool ScrollDisplay(int nLines, bool bWindowOnly); virtual bool EraseLine(EraseType eType); virtual bool EraseDisplay(EraseType eType); virtual bool UpdateTextAttribute(void); virtual DWORD OutputText(void); private: bool ProcessBackspace(void); bool ProcessTab(void); bool ProcessLinefeed(bool bNewLine); bool ProcessReverseLinefeed(void); bool ProcessReturn(void); void AddOutputData(wchar_t wchData) { m_OutputBuffer[m_dwOutputCount++] = wchData; if (m_dwOutputCount >= kOutputBufferSize) { OutputText(); } } void DisplayCSI(char ch); bool ProcessSCSG0(char ch); bool ProcessSCSG1(char ch); bool ProcessDECALN(void); bool ProcessDECDHLB(void); bool ProcessDECDHLT(void); bool ProcessDECDWL(void); bool ProcessDECID(void); bool ProcessDECKPAM(void); bool ProcessDECKPNM(void); bool ProcessDECLL(void); bool ProcessDECRC(void); bool ProcessDECREQTPARM(void); bool ProcessDECSC(void); bool ProcessDECSTBM(void); bool ProcessDECSWL(void); bool ProcessDECTST(void); bool ProcessCUB(void); bool ProcessCUD(void); bool ProcessCUF(void); bool ProcessCUP(void); bool ProcessCUU(void); bool ProcessDA(void); bool ProcessDSR(void); bool ProcessED(void); bool ProcessEL(void); bool ProcessHTS(void); bool ProcessHVP(void); bool ProcessIND(void); bool ProcessNEL(void); bool ProcessRCP(void); bool ProcessRI(void); bool ProcessRIS(void); bool ProcessRM(void); bool ProcessSCP(void); bool ProcessSGR(void); bool ProcessSM(void); bool ProcessTBC(void); private: HANDLE m_hConsole; DWORD m_dwOrigConsoleMode; WORD m_wOrigConsoleAttribute; DWORD m_dwOrigCursorSize; COLORREF m_OrigColorTable[kColorTableSize]; bool m_bResetColorTable; DisplayState m_State; SelectedCharset m_SelectedCharset; CharacterSet m_G0Charset; CharacterSet m_G1Charset; COORD m_BufferSize; COORD m_WindowSize; COORD m_WindowOrigin; COORD m_Cursor; COORD m_SavedCursor; SHORT m_sTopMargin; SHORT m_sBottomMargin; WORD m_Attribute; wchar_t m_OutputBuffer[kOutputBufferSize]; DWORD m_dwOutputCount; unsigned char m_UTF8Buffer[3]; int m_UTF8Count; int m_UTF8Size; int m_Parameters[kMaxParameterCount]; int m_ParameterCount; bool m_bParametersStart; bool m_bPrivateParameters; // Modes bool m_bLineFeedNewLineMode; // LNM bool m_bCursorKeyMode; // DECCKM // Always set - VT52 not supported bool m_bAnsiMode; // DECANM // Not used - column width is based on width of console window bool m_bColumnMode; // DECCOLM // Not used - always reset bool m_bScrollingMode; // DECSCLM // Not implemented - always reset bool m_bScreenMode; // DECSCNM bool m_bOriginMode; // DECOM bool m_bAutoWrapMode; // DECAWM // Not implemented - always set bool m_bAutoRepeatingMode; // DECARM // Not implemented - always reset bool m_bInterlaceMode; // DECINLM bool m_bDisplayCursor; // DECTCEM }; ipmiutil-3.1.5/util/mem_if.c0000644000076400007640000006675713566765324016060 0ustar mgportalloggers/*----------------------------------------------------------------------* * mem_if.c * Get SMBIOS Tables and associated data. * This code is 64-bit safe. * Note that for Windows, this should be compiled with /TP (as C++). * * 12/17/07 ARCress - created * 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 *----------------------------------------------------------------------*/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2002-2008, 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 Corporation 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. *----------------------------------------------------------------------*/ #ifdef WIN32 #define _WIN32_DCOM #pragma once #include #include #include //deprecated iostream.h #include //ole32.lib #include #include //Wbemcli.h,Wbemidl.h Wbemuuid.lib #elif defined(DOS) #include #include #include #else // Linux or Solaris #include #include #include #include #include #include #include #include #include #ifdef __linux__ #include #endif #endif #if defined(SOLARIS) || defined(BSD) || defined(HPUX) #define EXEC_PAGESIZE 4096 #endif #define DOS_MEM_RANGE_BASE 0xF0000 //starting memory range for smbios tables #define DOS_NUM_BYTES_TO_MAP 0x0FFFE //number bytes to map for smbios tables //smbios defines #define SMBIOS_STRING "_SM_" //server management bios string #define SMBIOS_MAJOR_REV 2 //major rev for smbios spec 2.3 #define SMBIOS_MINOR_REV 1 //minor rev for smbios spce 2.3 #define SMBIOS_STRUCTURE_TYPE_OFFSET 0 //offset in structure for type #define SMBIOS_STRUCTURE_LENGTH_OFFSET 1 //offset in structure for length #define SMBIOS_TABLE_LENGTH_OFFSET 0x5 //offset for length of table #define SMBIOS_MAJOR_REV_OFFSET 0x6 //offset for major rev of smbios #define SMBIOS_MINOR_REV_OFFSET 0x7 //offset for minor rev of smbios #define SMBIOS_TABLE_ENTRY_POINT_OFFSET 0x18 //offset for smbios structure table entry point #define SMBIOS_TABLE_SIZE_OFFSET 0x16 //offset for smbios structure table size #define NIBBLE_SIZE 4 //bit size of a nibble #ifdef WIN32 extern "C" { char fsm_debug = 0; } /*=1 to show smbios debug messages*/ #else char fsm_debug = 0; /*=1 to show smbios debug messages*/ #endif static int s_iTableRev = 0; //static globabl var to store table revision #ifndef WIN32 typedef int BOOL; typedef unsigned long ULONG; typedef unsigned char UCHAR; typedef unsigned short USHORT; BOOL MapPhysicalMemory(ULONG tdStartAddress, ULONG ulSize, ULONG* ptdVirtualAddress); BOOL UnMapPhysicalMemory(ULONG tdVirtualAddress, ULONG ulSize); int OpenIMemoryInterface(void); int CloseIMemoryInterface(void); #endif // Linux, not __WINDOWS__ #ifdef WIN32 /* Windows Memory routines */ static BYTE m_byMajorVersion = 0; static BYTE m_byMinorVersion = 0; static BYTE * m_pbBIOSData = NULL; static DWORD m_dwLen = 0; extern "C" { int getSmBiosTables(UCHAR **ptableAddress) { int bRet = 0; HRESULT hres; IWbemLocator *pLoc = 0; IWbemServices *pSvc = 0; IEnumWbemClassObject* pEnumerator = NULL; // Initialize COM. hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { return bRet; } // Obtain the initial locator to Windows Management // on a particular host computer. hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc); if (FAILED(hres)) { CoUninitialize(); return bRet; } // Connect to the root\cimv2 namespace with the // current user and obtain pointer pSvc // to make IWbemServices calls. hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\WMI"), // WMI namespace NULL, // User name NULL, // User password 0, // Locale NULL, // Security flags 0, // Authority 0, // Context object &pSvc // IWbemServices proxy ); if (FAILED(hres)) { pLoc->Release(); CoUninitialize(); return bRet; } // Set the IWbemServices proxy so that impersonation // of the user (client) occurs. hres = CoSetProxyBlanket( pSvc, // the proxy to set RPC_C_AUTHN_WINNT, // authentication service RPC_C_AUTHZ_NONE, // authorization service NULL, // Server principal name RPC_C_AUTHN_LEVEL_CALL, // authentication level RPC_C_IMP_LEVEL_IMPERSONATE, // impersonation level NULL, // client identity EOAC_NONE // proxy capabilities ); if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return bRet; // Program has failed. } hres = pSvc->CreateInstanceEnum( L"MSSMBios_RawSMBiosTables", 0, NULL, &pEnumerator); if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return bRet; // Program has failed. } else { do { IWbemClassObject* pInstance = NULL; ULONG dwCount = NULL; hres = pEnumerator->Next(WBEM_INFINITE, 1, &pInstance, &dwCount); if (SUCCEEDED(hres)) { VARIANT varBIOSData; VariantInit(&varBIOSData); CIMTYPE type; hres = pInstance->Get(bstr_t("SmbiosMajorVersion"),0,&varBIOSData,&type,NULL); if (FAILED(hres)) { VariantClear(&varBIOSData); } else { m_byMajorVersion = (BYTE)varBIOSData.iVal; VariantInit(&varBIOSData); hres = pInstance->Get(bstr_t("SmbiosMinorVersion"),0,&varBIOSData,&type,NULL); if(FAILED(hres)) { VariantClear(&varBIOSData); } else { m_byMinorVersion = (BYTE)varBIOSData.iVal; s_iTableRev = (m_byMajorVersion << 4) + m_byMinorVersion; VariantInit(&varBIOSData); hres = pInstance->Get(bstr_t("SMBiosData"),0,&varBIOSData,&type,NULL); if(SUCCEEDED(hres)) { if ( ( VT_UI1 | VT_ARRAY ) != varBIOSData.vt ) { } else { SAFEARRAY *parray = NULL; parray = V_ARRAY(&varBIOSData); BYTE* pbData = (BYTE*)parray->pvData; m_dwLen = parray->rgsabound[0].cElements; m_pbBIOSData = (BYTE *)malloc(m_dwLen); memcpy(m_pbBIOSData,pbData,m_dwLen); *ptableAddress = m_pbBIOSData; bRet = m_dwLen; } } VariantClear(&varBIOSData); } } break; } } while (hres == WBEM_S_NO_ERROR); } // Cleanup // ======== pSvc->Release(); pLoc->Release(); CoUninitialize(); return(bRet); } /*end getSmBiosTables*/ int closeSmBios(UCHAR *ptableAddress, ULONG ulSmBiosLen) { int rv = 0; /* memory interface already closed */ free(ptableAddress); return(rv); } } /*end extern C*/ #else /* Linux Memory routines */ #define MEM_DRIVER "/dev/mem" #define FALSE 0 #define TRUE 1 //intialize static handle amd counter static int m_iDriver = 0; static int m_iCount = 0; ////////////////////////////////////////////////////////////////////////////// // OpenIMemoryInterface ////////////////////////////////////////////////////////////////////////////// // Name: OpenIMemoryInterface // Purpose: create handle to driver if first time // Context: static m_iDriver & m_iCount // Returns: int rv (0 = success) // Parameters: none // Notes: /////////////////////////////////////////////////////////////////////////////// int OpenIMemoryInterface(void) { int rv = -1; /* ARM64 does not handle /dev/mem the same. * It exposes SMBIOS at /sys/firmware/dmi/tables/, but because * IO memory is memory mapped, cannot use legacy /dev/mem. */ #ifndef __arm__ #ifndef __aarch64__ //check to see if driver has been previously defined if (!m_iDriver) { //open the driver m_iDriver = open(MEM_DRIVER, O_RDONLY); if (m_iDriver > 0) { //increment instance counter m_iCount++; } else { //couldn't open the driver...so make it zero again m_iDriver = 0; } } else { //handle exists...so inc instance counter. m_iCount++; } if (m_iDriver > 0) rv = 0; #endif #endif return(rv); } /////////////////////////////////////////////////////////////////////////////// // CloseIMemoryInterface // Name: destructor // Purpose: close driver handle and null out field // Context: // Returns: // Parameters: none // Notes: /////////////////////////////////////////////////////////////////////////////// int CloseIMemoryInterface(void) { int rv = 0; //check if an instance has been created by looking at the counter if (!m_iCount) { m_iCount--; //decrement instance counter if (m_iCount == 0) { close(m_iDriver); m_iDriver = 0; //and null it out } } return(rv); } /////////////////////////////////////////////////////////////////////////////// // MapPhysicalMemory /////////////////////////////////////////////////////////////////////////////// // Name: MapPhysicalMemory // Purpose: given the starting address and size, the virtualize // memory is mapped. // Returns: True if success // Parameters: [IN] tdStartAddress = physical address to map // [IN] ulSize = number of bytes to map // [OUT] ptdVirtualAddress = ptr to virtual address /////////////////////////////////////////////////////////////////////////////// BOOL MapPhysicalMemory(ULONG tdStartAddress, ULONG ulSize, ULONG* ptdVirtualAddress) { long tdVirtualAddr = 0; ULONG ulDiff; //check if we have a valid driver handle if (!m_iDriver) return FALSE; //error //check for valid input params if (!tdStartAddress || !ulSize) return FALSE; //error //align the offset to a valid page boundary and adust its length ulDiff = (ULONG)(tdStartAddress % EXEC_PAGESIZE); if (fsm_debug) printf("MapPhys: tdStart=%lx, page=%x, diff=%lx\n", tdStartAddress,EXEC_PAGESIZE,ulDiff); tdStartAddress -= ulDiff; ulSize += ulDiff; tdVirtualAddr = (long)mmap((caddr_t)0, (size_t)ulSize, PROT_READ, MAP_SHARED, m_iDriver, (off_t)tdStartAddress); if (fsm_debug) printf("MapPhys: mmap(tdStart=%lx,size=%lx) = %lx\n", tdStartAddress,ulSize,tdVirtualAddr); if (tdVirtualAddr == -1) return FALSE; *ptdVirtualAddress = tdVirtualAddr + ulDiff; return TRUE; } /////////////////////////////////////////////////////////////////////////////// // UnMapPhysicalMemory /////////////////////////////////////////////////////////////////////////////// // Name: UnMapPhysicalMemory // Purpose: given the virtual address, unmaps it...frees memory. // Returns: True if success // Parameters: [IN] tdVirtualAddress = virtual address to unmap // [IN] ulSize = not needed for windows // Notes: none /////////////////////////////////////////////////////////////////////////////// BOOL UnMapPhysicalMemory(ULONG tdVirtualAddress, ULONG ulSize) { ULONG ulDiff = 0; ulDiff = (ULONG)(tdVirtualAddress % EXEC_PAGESIZE); tdVirtualAddress -= ulDiff; ulSize += ulDiff; if (munmap((void *)tdVirtualAddress,ulSize) != 0) return FALSE; return TRUE; } /////////////////////////////////////////////////////////////////////////////// // getSmBiosTables // Purpose: returns smbios tables pointer // Returns: pointer to the virtual address where SMBIOS tables begins ////////////////////////////////////////////////////////////////////////////// int getSmBiosTables(UCHAR **ptableAddress) { ULONG tdStartAddress = DOS_MEM_RANGE_BASE; ULONG ulSize = DOS_NUM_BYTES_TO_MAP; ULONG ulSmBiosLen = 0; ULONG tdVirtualAddress = 0; int iInc; UCHAR *pSmBios = NULL; UCHAR ucCheckSum = 0; UCHAR ucVal, ucVal1; int rv; if (fsm_debug) printf("getSmBiosTables start\n"); //get interface to Memory rv = OpenIMemoryInterface(); if (fsm_debug) printf("OpenIMemoryInterface rv = %d\n",rv); //map memory into user space if ((rv != 0) || !MapPhysicalMemory(tdStartAddress,ulSize,&tdVirtualAddress)) { #ifdef SOLARIS /* mmap always fails on Solaris, so skip the error message, * unless in debug mode. */ if (fsm_debug) #endif fprintf(stderr, "Cannot map memory.\n"); return ulSmBiosLen; /*==0*/ } //now find the entry point for smbios for(iInc=0; iInc < (long)ulSize; iInc+=sizeof(int) ) { if (!memcmp((UCHAR *)(tdVirtualAddress+iInc),SMBIOS_STRING,sizeof(int))) { //cast entry point to a byte pointer pSmBios = (UCHAR *)(tdVirtualAddress+iInc); break; } } if (pSmBios == NULL) { fprintf(stderr, "Can't find SMBIOS address entry point.\n"); UnMapPhysicalMemory(tdVirtualAddress,ulSize); return ulSmBiosLen; } if (fsm_debug) { printf("Found pSmBios=%p tdV=%lx, inc=%x\n",pSmBios, tdVirtualAddress,iInc); // dump_buf("SMBIOS",pSmBios,64,1); } //now sum up the bytes in the table for checksum checking for(iInc=0; iInc= 18)) { switch(VirtualAddress[i+16] >>6) { case 0x00: *inc = 1; break; /* 1-byte bound*/ case 0x01: *inc = 4; break; /* 4-byte bound*/ case 0x02: *inc = 16; break; /*16-byte bound*/ default: break; /**inc = 1; above*/ } } rv = 0; break; } //Skip this record and go to the end of it. for (j = i+length; j < (int)SMBiosLen; j++) { if (VirtualAddress[j] == 0x00 && VirtualAddress[j+1] == 0x00) { i = j+2; break; } } } closeSmBios(VirtualAddress,SMBiosLen); return rv; } //getIPMI_struct /////////////////////////////////////////////////////////////////////////////// // get_MemDesc ////////////////////////////////////////////////////////////////////////////// // Name: get_MemDesc // Purpose: find Type 17 record to get the Memory Locator Description // Returns: 0 for success, or -1 if not found. // if success, the desc string will have valid data ////////////////////////////////////////////////////////////////////////////// int get_MemDesc(UCHAR array, UCHAR dimm, char *desc, int *psize) { UCHAR *VirtualAddress; ULONG SMBiosLen = 0; int length, j, i; int iarray, idimm; UCHAR Type; int rv = -1; char dimmstr[32]; char bankstr[32]; SMBiosLen = getSmBiosTables( &VirtualAddress); if ((SMBiosLen == 0) || !VirtualAddress) return rv; if (desc == NULL) return(-1); bankstr[0] = 0; dimmstr[0] = 0; if (fsm_debug) printf("get_MemDesc(%d,%d)\n",array,dimm); iarray = 0; idimm = 0; for(i=0; i<(int)SMBiosLen; ) { Type = VirtualAddress[i]; length = (int)VirtualAddress[i+1]; if (Type == 127) //end of table record break; else if (Type == 16) //Found a Memory Array */ { /* usually only one onboard memory array */ if (array == iarray) ; /*match*/ else iarray++; } else if (Type == 17) //Found a Memory Device */ { int bank, k, n, nStr, nBLoc, sz; if (dimm == idimm) { if (fsm_debug) { printf("Memory record %d.%d: ",iarray,idimm); for (j = i; j < (i+length+16); j++) { if (((j-i) % 16) == 0) printf("\n"); printf("%02x ",VirtualAddress[j]); } printf("\n"); } /* * Memory Device record * walk through strings to find Locator */ sz = VirtualAddress[i+12] + (VirtualAddress[i+13] << 8); /*Size*/ bank = VirtualAddress[i+15]; /*Set*/ nStr = VirtualAddress[i+16]; /*Locator string num*/ nBLoc = VirtualAddress[i+17]; /*BankLocator string num*/ if (fsm_debug) printf("bank=%d nStr=%d sz=%x\n",bank,nStr,sz); k = i + length; /*hdr len (usu 0x1B)*/ n = 1; /* string number index */ for (j = k; j < (int)SMBiosLen; j++) { if (VirtualAddress[j] == 0x00 && VirtualAddress[j-1] == 0x00) break; else if (VirtualAddress[j] == 0x00) { if (fsm_debug) printf("str[%d] = %s\n", n,&VirtualAddress[k]); if (n == nBLoc) { /*bank string*/ strcpy(bankstr,(char *)&VirtualAddress[k]); break; /*string number*/ } if (n == nStr) { strcpy(dimmstr,(char *)&VirtualAddress[k]); } n++; k = j + 1; } } if ((desc != NULL) && (j < (int)SMBiosLen)) { sprintf(desc,"%s/%s",bankstr,dimmstr); rv = 0; } else { /* have header, but not string */ char b; if ((idimm % 2) == 0) b = 'A'; else b = 'B'; sprintf(desc,"DIMM%d%c",bank,b); rv = 0; } *psize = sz; break; } else idimm++; /*else go to next dimm*/ } //Skip this record and go to the end of it. for (j = i+length; j < (int)SMBiosLen; j++) { if (VirtualAddress[j] == 0x00 && VirtualAddress[j+1] == 0x00) { i = j+2; break; } } } closeSmBios(VirtualAddress,SMBiosLen); /* fill in a default if error */ if ((rv != 0) && (desc != NULL)) sprintf(desc,"DIMM(%d)",dimm); return rv; } //get_MemDesc /////////////////////////////////////////////////////////////////////////////// // get_BiosVersion ////////////////////////////////////////////////////////////////////////////// // Name: get_BiosVersion // Purpose: finds Type 0 record and gets the BIOS ID string // Returns: -1 if not found and 0 if found. Param contains the string ////////////////////////////////////////////////////////////////////////////// int get_BiosVersion(char *bios_str) { #define BIOS_VERSION 0x05 //Specifies string number of BIOS Ver string UCHAR *VirtualAddress; ULONG SMBiosLen = 0; int recLength, j, i, k = 0, str_num; UCHAR recType; int rv = -1; SMBiosLen = getSmBiosTables( &VirtualAddress); if ((SMBiosLen == 0) || !VirtualAddress) return rv; i=0; while (i<(int)SMBiosLen) { recType = VirtualAddress[i]; recLength = (int)VirtualAddress[i+1]; // end of table record, error if (recType == 127) return -1; else if (recType == 0) { // BIOS Information (Type 0) record found //Set index j to the end of the formated part of record. j = i + recLength; //First grab string number of the BIOS Version string //This non-zero number specifies which string at the end //of the record is the BIOS Version string. str_num = VirtualAddress[i + BIOS_VERSION]; //Now skip over strings at the end of the record till we //get to the BIOS Version string for (str_num--;str_num > 0; str_num--) { //Skipping over one string at a time for (; VirtualAddress[j] != 0x00; j++); j++; //Advance index past EOS. } //Copy the BIOS Version string into buffer from caller. for (; VirtualAddress[j] != 0x00; j++) { bios_str[k++] = VirtualAddress[j]; } bios_str[k] = '\0'; rv = 0; break; /*exit while loop*/ } else { //Not a Type 0, so skip to the end of this structure for (j = i+recLength; j < (int)SMBiosLen; j++) { if (VirtualAddress[j] == 0x00 && VirtualAddress[j+1] == 0x00) { i = j+2; break; } } } } /*end while*/ closeSmBios(VirtualAddress,SMBiosLen); return rv; } int get_ChassisSernum(char *chs_str, char fdbg) { #define CHASSIS_SERNUM 0x07 //Specifies string number of BIOS Ver string UCHAR *VirtualAddress; ULONG SMBiosLen = 0; int recLength, j, i, k = 0, str_num; UCHAR recType; int rv = -1; SMBiosLen = getSmBiosTables( &VirtualAddress); if ((SMBiosLen == 0) || !VirtualAddress) return rv; i=0; while (i<(int)SMBiosLen) { recType = VirtualAddress[i]; recLength = (int)VirtualAddress[i+1]; if (recType == 127) return -1; // end of table record, error else if (recType == 3) { // Chassis Information (Type 3) record found j = i + recLength; str_num = VirtualAddress[i + CHASSIS_SERNUM]; for (str_num--;str_num > 0; str_num--) { for (; VirtualAddress[j] != 0x00; j++); j++; } for (; VirtualAddress[j] != 0x00; j++) { chs_str[k++] = VirtualAddress[j]; } chs_str[k] = '\0'; /* also copy Chassis Manuf */ j = i + recLength; memcpy(&chs_str[k+1],&VirtualAddress[j],20); rv = 0; break; /*exit while loop*/ } else { //Not a Type 0, so skip to the end of this structure for (j = i+recLength; j < (int)SMBiosLen; j++) { if (VirtualAddress[j] == 0x00 && VirtualAddress[j+1] == 0x00) { i = j+2; break; } } } } /*end while*/ closeSmBios(VirtualAddress,SMBiosLen); return rv; } int get_SystemGuid(UCHAR *guid) { UCHAR *VirtualAddress; ULONG SMBiosLen = 0; int recLength, i, j, n, k = 0; UCHAR recType; int rv = -1; SMBiosLen = getSmBiosTables( &VirtualAddress); if ((SMBiosLen == 0) || !VirtualAddress) return rv; i=0; while (i<(int)SMBiosLen) { recType = VirtualAddress[i]; recLength = (int)VirtualAddress[i+1]; // end of table record, error if (recType == 127) return -1; else if (recType == 1) { // System Board Information (Type 1) record found //Set index j to the end of the formated part of record. j = i + recLength; n = i + 8; /*UUID offset 8*/ //Copy the UUID string into buffer from caller. for (k = 0; k < 16; k++) { guid[k] = VirtualAddress[n + k]; } rv = 0; break; /*exit while loop*/ } else { //else skip to the end of this structure for (j = i+recLength; j < (int)SMBiosLen; j++) { if (VirtualAddress[j] == 0x00 && VirtualAddress[j+1] == 0x00) { i = j+2; break; } } } } /*end while*/ closeSmBios(VirtualAddress,SMBiosLen); return rv; } #ifdef WIN32 } #endif #ifdef COMP_BIN int main(int argc, char **argv) { char biosver[80]; UCHAR ifs,ver,sa,inc; int rv; int base; biosver[0] = 0; rv = get_BiosVersion(biosver); printf("get_BiosVersion rv=%d Ver=%s\n",rv,biosver); rv = get_IpmiStruct( &ifs, &ver, &sa, &base, &inc); printf("get_IpmiStruct rv=%d if=%02x ver=%02x sa=%02x base=%x, spacing=%d\n", rv, ifs,ver,sa,base,inc); rv = get_SystemGuid(biosver); printf("get_SystemGuid rv=%d Ver=%s\n",rv,biosver); // exit(rv); return(rv); } #endif /* end mem_if.c */ ipmiutil-3.1.5/util/ifwum.h0000644000076400007640000000521613566765324015737 0ustar mgportalloggers/* * Copyright (c) 2003 Sun Microsystems, 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: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution 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. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #ifndef IPMI_KFWUM_H #define IPMI_KFWUM_H // #include // #include #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int #define IPMI_NETFN_APP 0x6 #define IPMI_NETFN_FIRMWARE 0x8 #define IPMI_BMC_SLAVE_ADDR 0x20 #define BMC_GET_DEVICE_ID 0x1 #define IPM_DEV_MANUFACTURER_ID(x) \ ((uint32_t) ((x[2] & 0x0F) << 16 | x[1] << 8 | x[0])) //struct valstr { // uint16_t val; // const char * str; //}; #pragma pack(1) struct ipm_devid_rsp { uint8_t device_id; uint8_t device_revision; uint8_t fw_rev1; uint8_t fw_rev2; uint8_t ipmi_version; uint8_t adtl_device_support; uint8_t manufacturer_id[3]; uint8_t product_id[2]; uint8_t aux_fw_rev[4]; }; // __attribute__ ((packed)); #pragma pack() /* routines from lib/lanplus/helper.c */ uint16_t buf2short(uint8_t * buf); //const char * val2str(uint16_t val, const struct valstr * vs); #endif /* IPMI_KFWUM_H */ ipmiutil-3.1.5/util/imbapi.c0000644000076400007640000022614213566765324016047 0ustar mgportalloggers/*M* // PVCS: // $Workfile: imbapi.c $ // $Revision: 1.12 $ // $Modtime: 06 Aug 2001 13:16:56 $ // // Purpose: This file contains the entry point that opens the IMB device // in order to issue the IMB driver API related IOCTLs. // This file implements the IMB driver API for the Server // Management Agents. // // $Log: //epg-scc/sst/projectdatabases/isc/isc3x/LNWORK/SRC/imbapi/imbapi.c.v $ // // 04/04/02 ARCress - Mods for open-source & various compile cleanup mods // 05/28/02 ARCress - fixed buffer size error // 04/08/03 ARCress - misc cleanup // 01/20/04 ARCress - added WIN32 flags // 05/24/05 ARCress - added LINK_LANDESK flags // 08/24/06 ARCress - mods for addtl DEBUG (dbgmsg) // 03/19/08 ARCress - fix for SendTimedLan(IpmiVersion) if IPMI 2.0 *M*/ /*----------------------------------------------------------------------* The BSD License 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 Corporation 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. *----------------------------------------------------------------------*/ #if defined(SOLARIS) || defined(BSD) #undef IMB_API #else /* Ok for WIN32, LINUX, SCO_UW, etc., but not Solaris */ #define IMB_API 1 #endif #ifdef IMB_API #ifdef WIN32 #define NO_MACRO_ARGS 1 #include #include #define uint unsigned int #else /* LINUX, SCO_UW, UNIX */ #include #include #include #include #include #include #include #include #include #include #include #endif #include "imb_api.h" #ifdef SCO_UW #define NO_MACRO_ARGS 1 #define __FUNCTION__ "func" #define IMB_DEVICE "/dev/instru/mismic" #else #define IMB_DEVICE "/dev/imb" #define PAGESIZE EXEC_PAGESIZE #endif /*Just to make the DEBUG code cleaner.*/ #if defined(DBG_IPMI) || defined(LINUX_DEBUG) #include static void dbgmsg( char *pattn, ... ) { va_list arglist; FILE *fdlog; fdlog = fopen( "imbdbg.log", "a+" ); if (fdlog == NULL) fdlog = stdout; va_start( arglist, pattn ); vfprintf( fdlog, pattn, arglist ); va_end( arglist ); fclose(fdlog); } #endif #ifdef NO_MACRO_ARGS #define DEBUG(format, args) /*not_debug*/ #else #ifdef LINUX_DEBUG #define DEBUG(format, args...) dbgmsg(format, ##args) // #define DEBUG(format, args...) printf(format, ##args) #else #define DEBUG(format, args...) /*not_debug*/ #endif #endif #define IMB_OPEN_TIMEOUT 400 #define IMB_MAX_RETRIES 2 #define IMB_DEFAULT_TIMEOUT (1000) /*timeout for SendTimedImb in msec*/ #define ERR_NO_DRV -16 /*cannot open IPMI driver*/ #define LOCAL_IPMB 1 /*instead of METACOMMAND_IPMB*/ int ipmi_timeout_ia = IMB_DEFAULT_TIMEOUT; /* in msec */ #ifdef METACOMMAND_IPMB /*++++ not used*/ extern int ipmi_cmd_ipmb(BYTE cmd, BYTE netfn, BYTE sa, BYTE bus, BYTE lun, BYTE *pdata, int sdata, BYTE *presp, int *sresp, BYTE *pcc, char fdebugcmd); /*ipmilan.c*/ #endif #ifdef METACOMMAND extern FILE *fpdbg; extern FILE *fperr; #else static FILE *fpdbg = NULL; static FILE *fperr = NULL; #endif /* uncomment out the #define below or use -DLINUX_DEBUG_MAX in the makefile // if you want a dump of the memory to debug mmap system call in // MapPhysicalMemory() below. // //#define LINUX_DEBUG_MAX 1 */ //#define IMB_MEMORY 1 */ /*keep it simple. use global varibles for event objects and handles //pai 10/8 */ /* UnixWare should eventually have its own source code file. Right now // new code has been added based on the existing policy of using // pre-processor directives to separate os-specific code (pai 11/21) */ static int IpmiVersion; static HandleType AsyncEventHandle = 0; // static void * AsyncEventObject = 0; /*//////////////////////////////////////////////////////////////////////////// // GLOBAL VARIABLES ///////////////////////////////////////////////////////////////////////////// */ #if defined(__i386__) || defined(__i586__) || defined(__i686__) // static DWORD ioctl_sendmsg = 0x1082; /* force 0x1082 if 32-bit */ static DWORD ioctl_sendmsg = IOCTL_IMB_SEND_MESSAGE; #else static DWORD ioctl_sendmsg = IOCTL_IMB_SEND_MESSAGE; #endif static IO_STATUS_BLOCK NTstatus; /*dummy place holder. See deviceiocontrol. */ static HandleType hDevice1; /*used in open_imb() */ static HandleType hDevice; /*used to call DeviceIoControl()*/ /*mutex_t deviceMutex; */ #ifdef LINUX_DEBUG static char fdebug = 1; #else static char fdebug = 0; #endif #ifdef LINK_LANDESK #define SendTimedImbpRequest ia_SendTimedImbpRequest #define StartAsyncMesgPoll ia_StartAsyncMesgPoll #define SendTimedI2cRequest ia_SendTimedI2cRequest #define SendTimedEmpMessageResponse ia_SendTimedEmpMessageResponse #define SendTimedEmpMessageResponse_Ex ia_SendTimedEmpMessageResponse_Ex #define SendTimedLanMessageResponse ia_SendTimedLanMessageResponse #define SendTimedLanMessageResponse_Ex ia_SendTimedLanMessageResponse_Ex #define SendAsyncImbpRequest ia_SendAsyncImbpRequest #define GetAsyncImbpMessage ia_GetAsyncImbpMessage #define GetAsyncImbpMessage_Ex ia_GetAsyncImbpMessage_Ex #define IsAsyncMessageAvailable ia_IsAsyncMessageAvailable #define RegisterForImbAsyncMessageNotification ia_RegisterForImbAsyncMessageNotification #define UnRegisterForImbAsyncMessageNotification ia_UnRegisterForImbAsyncMessageNotification #define SetShutDownCode ia_SetShutDownCode #define GetIpmiVersion ia_GetIpmiVersion #endif int open_imb(int fskipcmd); void set_fps(void) { if (fpdbg == NULL) fpdbg = stdout; if (fperr == NULL) fperr = stdout; } #ifndef WIN32 DWORD GetLastError(void) { return(NTstatus.Status); } /*/////////////////////////////////////////////////////////////////////////// // DeviceIoControl ///////////////////////////////////////////////////////////////////////////// */ /*F* // Name: DeviceIoControl // Purpose: Simulate NT DeviceIoControl using unix calls and structures. // Context: called for every NT DeviceIoControl // Returns: FALSE for fail and TRUE for success. Same as standarad NTOS call // as it also sets Ntstatus.status. // Parameters: Standard NT call parameters, see below. // Notes: none *F*/ static BOOL DeviceIoControl( HandleType dummy_hDevice, /* handle of device */ DWORD dwIoControlCode, /* control code of operation to perform*/ LPVOID lpvInBuffer, /* address of buffer for input data */ DWORD cbInBuffer, /* size of input buffer */ LPVOID lpvOutBuffer, /* address of output buffer */ DWORD cbOutBuffer, /* size of output buffer */ LPDWORD lpcbBytesReturned, /* address of actual bytes of output */ LPOVERLAPPED lpoOverlapped /* address of overlapped struct */ ) { struct smi s; int rc, max_i; int ioctl_status; DEBUG("DeviceIoControl: hDevice1=%x hDevice=%x ioctl=%x\n", hDevice1,hDevice,dwIoControlCode); rc = open_imb(1); /*open if needed, set fskipcmd to avoid recursion*/ if (rc == 0) { #ifdef DBG_IPMI dbgmsg("DeviceIoControl: open_imb failed %d\n", rc); #endif return FALSE; } /*-------------dont use locking-------------- //lock the mutex, before making the request.... if(mutex_lock(&deviceMutex) != 0) { return(FALSE); } *-------------------------------------------*/ #ifndef NO_MACRO_ARGS DEBUG("%s: ioctl cmd = 0x%lx ", __FUNCTION__,dwIoControlCode); DEBUG("cbInBuffer %d cbOutBuffer %d\n", cbInBuffer, cbOutBuffer); #endif /* Test for Intel imb driver max buf size */ /* Max was 41, too small. Calculate real max - ARCress 6/01/05 */ max_i = MAX_IMB_PACKET_SIZE + MIN_IMB_REQ_BUF_SIZE; /*33 + 13*/ if (cbInBuffer > max_i) cbInBuffer = max_i; s.lpvInBuffer = lpvInBuffer; s.cbInBuffer = cbInBuffer; s.lpvOutBuffer = lpvOutBuffer; s.cbOutBuffer = cbOutBuffer; s.lpcbBytesReturned = lpcbBytesReturned; s.lpoOverlapped = lpoOverlapped; s.ntstatus = (LPVOID)&NTstatus; /*dummy place holder. Linux IMB driver //doesnt return status or info via it.*/ #ifdef IMB_DEBUG if (fdebug) { int j, n; char *tag; unsigned int *bi; unsigned char *b; printf("ioctl %x smi buffer:\n",dwIoControlCode); /* show arg/smi structure */ bi = (unsigned int *)&s; n = ( sizeof(struct smi) / sizeof(int) ); printf("smi(%p), (sz=%d/szint=%d)->%d:\n", bi, sizeof(struct smi), sizeof(int),n); for (j = 0; j < n; j++) { switch(j) { case 0: tag = "version "; break; case 2: tag = "reserved1"; break; case 4: tag = "reserved2"; break; case 6: tag = "ntstatus "; break; case 8: tag = "pinbuf "; break; case 10: tag = "sinbuf "; break; case 12: tag = "poutbuf"; break; case 14: tag = "soutbuf"; break; case 16: tag = "cbRet "; break; case 18: tag = "pOverlap"; break; default: tag = "other "; } printf("bi[%d]%s: %08x \n",j,tag,bi[j]); } /*end for*/ } #endif if ( (ioctl_status = ioctl(hDevice1, dwIoControlCode,&s) ) <0) { #ifndef NO_MACRO_ARGS DEBUG("%s %s: ioctl cmd = 0x%x failed %d \n", __FILE__,__FUNCTION__,dwIoControlCode,ioctl_status); #endif #ifdef DBG_IPMI dbgmsg("DeviceIoControl: ioctl cmd = 0x%x failed %d \n", dwIoControlCode,ioctl_status); #endif /* mutex_unlock(&deviceMutex); */ return FALSE; } /*-------------dont use locking-------------- mutex_unlock(&deviceMutex); *-------------------------------------------*/ #ifndef NO_MACRO_ARGS DEBUG("%s: ioctl_status %d bytes returned = %d \n", __FUNCTION__, ioctl_status, *lpcbBytesReturned); #endif /*MR commented this just as in Sol1.10. lpcbBytesReturned has the right data // *lpcbBytesReturned = NTstatus.Information; */ if (ioctl_status == STATUS_SUCCESS) { #ifndef NO_MACRO_ARGS DEBUG("%s returning true\n", __FUNCTION__); #endif return (TRUE); } else { #ifndef NO_MACRO_ARGS DEBUG("%s returning false\n", __FUNCTION__); #endif return (FALSE); } } #endif static void _dump_buf(char *tag, BYTE *pbuf, int sz, char fshowascii) { BYTE line[17]; BYTE a; int i, j; char *stag; FILE *fpdbg1; #ifdef DBG_IPMI fpdbg1 = fopen( "imbdbg.log", "a+" ); if (fpdbg1 == NULL) fpdbg1 = stdout; #else fpdbg1 = stdout; #endif if (tag == NULL) stag = "dump_buf"; /*safety valve*/ else stag = tag; fprintf(fpdbg1,"%s (len=%d): ", stag,sz); line[0] = 0; line[16] = 0; j = 0; if (sz < 0) { fprintf(fpdbg1,"\n"); return; } /*safety valve*/ for (i = 0; i < sz; i++) { if (i % 16 == 0) { line[j] = 0; j = 0; fprintf(fpdbg1,"%s\n %04x: ",line,i); } if (fshowascii) { a = pbuf[i]; if (a < 0x20 || a > 0x7f) a = '.'; line[j++] = a; } fprintf(fpdbg1,"%02x ",pbuf[i]); } if (fshowascii) { if ((j > 0) && (j < 16)) { /* space over the remaining number of hex bytes */ for (i = 0; i < (16-j); i++) fprintf(fpdbg1," "); } else j = 16; line[j] = 0; } fprintf(fpdbg1,"%s\n",line); #ifdef DBG_IPMI if (fpdbg1 != stdout) fclose(fpdbg1); #endif return; } #ifdef LOCAL_IPMB #define SMS_MSG_LUN 0x02 extern void os_usleep(int s, int u); /*subs.c*/ static int sendSeq = 1; static BYTE cksum(const BYTE *buf, register int len) { /* 8-bit 2s compliment checksum */ register BYTE csum; register int i; csum = 0; for (i = 0; i < len; i++) csum = (csum + buf[i]) % 256; csum = -csum; return(csum); } // SendTimedIpmbpRequest ACCESN_STATUS SendTimedIpmbpRequest ( IMBPREQUESTDATA *reqPtr, /* request info and data */ int timeOut, /* how long to wait, in mSec units */ BYTE *respDataPtr, /* where to put response data */ int *respDataLen, /* how much response data there is */ BYTE *completionCode /* request status from bmc controller*/ ) { BYTE responseData[MAX_IMB_REQ_SIZE]; ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; DWORD respLength = sizeof( responseData ); DWORD reqLength; BYTE requestData[MAX_IMB_RESP_SIZE]; ImbRequestBuffer * req = (ImbRequestBuffer *) requestData; BOOL status; int i; req->req.rsSa = BMC_SA; req->req.cmd = SEND_MESSAGE; req->req.netFn = APP_NETFN; req->req.rsLun = BMC_LUN; /*=0*/ req->req.data[0] = reqPtr->busType; req->req.data[1] = reqPtr->rsSa; req->req.data[2] = ((reqPtr->netFn << 2) | (reqPtr->rsLun & 0x03)); req->req.data[3] = cksum(&req->req.data[1],2); req->req.data[4] = BMC_SA; req->req.data[5] = ((sendSeq << 2) | (SMS_MSG_LUN & 0x03)); req->req.data[6] = reqPtr->cmdType; for (i = 0; i < reqPtr->dataLength; i++) req->req.data[7+i] = reqPtr->data[i]; req->req.data[7+i] = cksum(&req->req.data[4], reqPtr->dataLength + 3); req->req.dataLength = reqPtr->dataLength + 8; req->flags = 0; req->timeOut = timeOut * 1000; /* convert to uSec units */ reqLength = req->req.dataLength + MIN_IMB_REQ_BUF_SIZE; status = DeviceIoControl( hDevice, ioctl_sendmsg, requestData, reqLength, & responseData, sizeof( responseData ), & respLength, NULL); if (fdebug) printf("sendIpmb: send_message status=%d rlen=%lu cc=%x\n", status,respLength,resp->cCode); if ( status != TRUE ) { DWORD error; error = GetLastError(); return ACCESN_ERROR; } if ( respLength == 0 ) { return ACCESN_ERROR; } sendSeq++; if ( resp->cCode != 0) { *completionCode = resp->cCode; *respDataLen = 0; return ACCESN_OK; } /* * Sent ok, wait for GetMessage response */ for (i=0; i < 10; i++) /* RETRIES=10 for GetMessage */ { //req->req.busType = PUBLIC_BUS; /*=0*/ req->req.rsSa = BMC_SA; req->req.cmd = GET_MESSAGE; req->req.netFn = APP_NETFN; req->req.rsLun = BMC_LUN; /*=0*/ req->req.dataLength = 0; reqLength = req->req.dataLength + MIN_IMB_REQ_BUF_SIZE; status = DeviceIoControl( hDevice, ioctl_sendmsg, requestData, reqLength, & responseData, sizeof( responseData ), & respLength, NULL); if (fdebug) printf("sendIpmb: get_message status=%d rlen=%lu cc=%x\n", status,respLength,resp->cCode); if ( status != TRUE ) { DWORD error; error = GetLastError(); return ACCESN_ERROR; } if ( respLength == 0 ) { return ACCESN_ERROR; } if ( (resp->cCode != 0x80) && (resp->cCode != 0x83) ) break; /*success, exit loop*/ os_usleep(0,1000); /* 1 msec*/ } /*end-for*/ /* * give the caller his response */ *completionCode = resp->cCode; *respDataLen = 0; if (( respLength > 1 ) && ( respDataPtr)) { /* check that resp cmd & netfn match */ *respDataLen = respLength - 7; memcpy( respDataPtr, &resp->data[7], *respDataLen); } return ACCESN_OK; } #endif /*/////////////////////////////////////////////////////////////////////////// // SendTimedImbpRequest ///////////////////////////////////////////////////////////////////////////// */ /*F* // Name: SendTimedImbpRequest // Purpose: This function sends a request for BMC implemented function // Context: Used by Upper level agents (sis modules) to access BMC implemented functionality. // Returns: OK else error status code // Parameters: // reqPtr // timeOut // respDataPtr // respLen // Notes: none *F*/ ACCESN_STATUS SendTimedImbpRequest ( IMBPREQUESTDATA *reqPtr, /* request info and data */ int timeOut, /* how long to wait, in mSec units */ BYTE *respDataPtr, /* where to put response data */ int *respDataLen, /* how much response data there is */ BYTE *completionCode /* request status from bmc controller*/ ) { BYTE responseData[MAX_IMB_REQ_SIZE]; ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; DWORD respLength = sizeof( responseData ); DWORD reqLength; BYTE requestData[MAX_IMB_RESP_SIZE]; ImbRequestBuffer * req = (ImbRequestBuffer *) requestData; BOOL status; req->req.rsSa = reqPtr->rsSa; req->req.cmd = reqPtr->cmdType; req->req.netFn = reqPtr->netFn; req->req.rsLun = reqPtr->rsLun; req->req.dataLength = (BYTE)reqPtr->dataLength; #ifndef NO_MACRO_ARGS DEBUG("cmd=%02x, pdata=%p, datalen=%d, size=%d\n", req->req.cmd, reqPtr->data, reqPtr->dataLength, sizeof(requestData)); #endif memcpy( req->req.data, reqPtr->data, reqPtr->dataLength ); req->flags = 0; req->timeOut = timeOut * 1000; /* convert to uSec units */ #ifndef NO_MACRO_ARGS DEBUG("%s: rsSa 0x%x cmd 0x%x netFn 0x%x rsLun 0x%x\n", __FUNCTION__, req->req.rsSa, req->req.cmd, req->req.netFn, req->req.rsLun); #endif reqLength = req->req.dataLength + MIN_IMB_REQ_BUF_SIZE; status = DeviceIoControl( hDevice, ioctl_sendmsg, requestData, reqLength, & responseData, sizeof( responseData ), & respLength, NULL ); #ifndef NO_MACRO_ARGS DEBUG("%s: DeviceIoControl returned status = %d\n",__FUNCTION__, status); #endif #ifdef DBG_IPMI printf("%s: rsSa %x cmd %x netFn %x lun %x, status=%d, cc=%x, rlen=%d\n", __FUNCTION__, req->req.rsSa, req->req.cmd, req->req.netFn, req->req.rsLun, status, resp->cCode, respLength ); dbgmsg("SendTimedImb: rsSa %x cmd %x netFn %x lun %x, status=%d, cc=%x, rlen=%d\n", req->req.rsSa, req->req.cmd, req->req.netFn, req->req.rsLun, status, resp->cCode, respLength ); if (req->req.cmd == 0x34) { _dump_buf("requestData",requestData,reqLength,0); //if DBG_IPMI _dump_buf("responseData",responseData,respLength,0); //if DBG_IPMI } #endif if( status != TRUE ) { DWORD error; error = GetLastError(); return ACCESN_ERROR; } if( respLength == 0 ) { return ACCESN_ERROR; } /* * give the caller his response */ *completionCode = resp->cCode; *respDataLen = 0; if(( respLength > 1 ) && ( respDataPtr)) { *respDataLen = respLength - 1; memcpy( respDataPtr, resp->data, *respDataLen); } return ACCESN_OK; } /*//////////////////////////////////////////////////////////////////// // open_imb ////////////////////////////////////////////////////////////////////// */ /*F* // Name: open_imb // Purpose: To open imb device // Context: Called from each routine to make sure that open is done. // Returns: returns 0 for Fail and 1 for Success, sets hDevice to open // handle. // Parameters: none // Notes: none *F*/ #ifdef WIN32 #define IMB_DEVICE_WIN "\\\\.\\Imb" int open_imb(int fskipcmd) { /* This routine will be called from all other routines before doing any interfacing with imb driver. It will open only once. */ IMBPREQUESTDATA requestData; BYTE respBuffer[MAX_IMB_RESP_SIZE]; DWORD respLength; BYTE completionCode; int ret; set_fps(); if (hDevice1 == 0) /*INVALID_HANDLE_VALUE*/ { // // Open IMB driver device // hDevice = CreateFile( IMB_DEVICE_WIN, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hDevice == NULL || hDevice == INVALID_HANDLE_VALUE) { if (fdebug) printf("ipmi_open_ia: error opening %s to imbdrv.sys\n", IMB_DEVICE_WIN); return (0); /*FALSE*/ } if (fskipcmd) { IpmiVersion = IPMI_15_VERSION; return (1); /*TRUE*/ } // Detect the IPMI version for processing requests later. // This is a crude but most reliable method to differentiate // between old IPMI versions and the 1.0 version. If we had used the // version field instead then we would have had to revalidate all the // older platforms (pai 4/27/99) requestData.cmdType = GET_DEVICE_ID; requestData.rsSa = BMC_SA; requestData.rsLun = BMC_LUN; requestData.netFn = APP_NETFN ; requestData.busType = PUBLIC_BUS; requestData.data = NULL; requestData.dataLength = 0; respLength = sizeof(respBuffer); ret = SendTimedImbpRequest ( &requestData, IMB_OPEN_TIMEOUT, respBuffer, &respLength, &completionCode); if ( (ret != ACCESN_OK ) || ( completionCode != 0) ) { if (fdebug) /*GetDeviceId failed*/ printf("ipmi_open_ia: imbdrv request error, ret=%d ccode=%x\n", ret,completionCode); CloseHandle(hDevice); return (0); /*FALSE*/ } hDevice1 = hDevice; if (respLength < (IPMI10_GET_DEVICE_ID_RESP_LENGTH-1)) IpmiVersion = IPMI_09_VERSION; else { if ( respBuffer[4] == 0x01 ) IpmiVersion = IPMI_10_VERSION; else /* IPMI 1.5 or 2.0 */ IpmiVersion = IPMI_15_VERSION; } } return (1); /*TRUE*/ } /*end open_imb for Win32 */ #else /* LINUX, SCO_UW, etc. */ int open_imb(int fskipcmd) { /* This routine will be called from all other routines before doing any interfacing with imb driver. It will open only once. */ IMBPREQUESTDATA requestData; BYTE respBuffer[MAX_IMB_RESP_SIZE]; int respLength; BYTE completionCode; int ret_code; set_fps(); if (hDevice1 == 0) { #ifndef NO_MACRO_ARGS DEBUG("%s: opening the driver, ioctl_sendmsg = %x\n", __FUNCTION__, ioctl_sendmsg); #endif /* %%%%* IOCTL_IMB_SEND_MESSAGE = 0x1082 printf("ipmi_open_ia: " "IOCTL_IMB_SEND_MESSAGE =%x \n" "IOCTL_IMB_GET_ASYNC_MSG=%x \n" "IOCTL_IMB_MAP_MEMORY = %x \n" "IOCTL_IMB_UNMAP_MEMORY= %x \n" "IOCTL_IMB_SHUTDOWN_CODE=%x \n" "IOCTL_IMB_REGISTER_ASYNC_OBJ =%x \n" "IOCTL_IMB_DEREGISTER_ASYNC_OBJ=%x \n" "IOCTL_IMB_CHECK_EVENT =%x \n" "IOCTL_IMB_POLL_ASYNC =%x \n", IOCTL_IMB_SEND_MESSAGE, IOCTL_IMB_GET_ASYNC_MSG, IOCTL_IMB_MAP_MEMORY, IOCTL_IMB_UNMAP_MEMORY, IOCTL_IMB_SHUTDOWN_CODE, IOCTL_IMB_REGISTER_ASYNC_OBJ, IOCTL_IMB_DEREGISTER_ASYNC_OBJ, IOCTL_IMB_CHECK_EVENT , IOCTL_IMB_POLL_ASYNC); *%%%%*/ /*O_NDELAY flag will cause problems later when driver makes //you wait. Hence removing it. */ /*if ((hDevice1 = open(IMB_DEVICE,O_RDWR|O_NDELAY)) <0) */ if ((hDevice1 = open(IMB_DEVICE,O_RDWR)) <0) { hDevice1 = 0; #ifndef WIN32 /* dont always display open errors if Linux */ if (fdebug) #endif { /*debug or not 1st time */ printf("imbapi ipmi_open_ia: open(%s) failed, %s\n", IMB_DEVICE,strerror(errno)); } return (0); } if (fskipcmd) { IpmiVersion = IPMI_15_VERSION; return (1); /*TRUE*/ } /* Detect the IPMI version for processing requests later. // This is a crude but most reliable method to differentiate // between old IPMI versions and the 1.0 version. If we had used the // version field instead then we would have had to revalidate all // the older platforms (pai 4/27/99) */ requestData.cmdType = GET_DEVICE_ID; requestData.rsSa = BMC_SA; requestData.rsLun = BMC_LUN; requestData.netFn = APP_NETFN ; requestData.busType = PUBLIC_BUS; requestData.data = NULL; requestData.dataLength = 0; respLength = sizeof(respBuffer); #ifndef NO_MACRO_ARGS DEBUG("%s: opened driver, getting IPMI version\n", __FUNCTION__); #endif ret_code = SendTimedImbpRequest(&requestData, IMB_OPEN_TIMEOUT, respBuffer, &respLength, &completionCode); if ( (ret_code != ACCESN_OK) || (completionCode != 0) ) { printf("ipmi_open_ia: SendTimedImbpRequest error. Ret = %d CC = 0x%02X\n", ret_code, completionCode); close(hDevice1); hDevice1 = 0; return (0); } if (respLength < (IPMI10_GET_DEVICE_ID_RESP_LENGTH-1)) IpmiVersion = IPMI_09_VERSION; else { if ( respBuffer[4] == 0x01 ) IpmiVersion = IPMI_10_VERSION; else /* IPMI 1.5 or 2.0 */ IpmiVersion = IPMI_15_VERSION; } #ifndef NO_MACRO_ARGS DEBUG("%s: IPMI version 0x%x\n", __FUNCTION__, IpmiVersion); #endif /* //initialise a mutex if(mutex_init(&deviceMutex , USYNC_THREAD, NULL) != 0) { return(0); } */ } return (1); } /*end open_imb()*/ #endif int close_imb(void) { int rc = 0; if (hDevice1 != 0) { #ifdef WIN32 CloseHandle(hDevice1); #else rc = close(hDevice1); #endif } return(rc); } #ifndef LINK_LANDESK /* If there is not a LANDESK lib, provide these 2 functions for apps * that may be already be coded to that interface. */ int initIPMI(void) { /* for compatibility with LanDesk programs*/ int rc; rc = open_imb(0); /*sets hDevice1*/ if (rc == 1) rc = 0; else rc = -1; return(rc); } int termIPMI(void) { /* for compatibility with LanDesk programs*/ return(close_imb()); } #endif /*---------------------------------------------------------------------* * ipmi_open_ia & ipmi_close_ia *---------------------------------------------------------------------*/ int ipmi_open_ia(char fdebugcmd) { int rc = 0; fdebug = fdebugcmd; rc = open_imb(0); /*sets hDevice1*/ if (rc == 1) rc = 0; else rc = -1; return(rc); } int ipmi_close_ia(void) { int rc = 0; rc = close_imb(); return(rc); } int ipmi_cmdraw_ia(BYTE cmd, BYTE netfn, BYTE lun, BYTE sa, BYTE bus, BYTE *pdata, BYTE sdata, BYTE *presp, int *sresp, BYTE *pcc, char fdebugcmd) { IMBPREQUESTDATA requestData; int status = 0; char *imbDev; BYTE * pc; int sz, i; #ifndef WIN32 struct stat stbuf; #endif if (fdebug) printf("ipmi_cmdraw_ia(%02x,%02x,%02x,%02x,bus=%02x)\n", cmd,netfn,lun,sa,bus); #ifdef METACOMMAND_IPMB /*++++ not used*/ if (bus != PUBLIC_BUS) { if (fdebug) printf("ipmi_cmdraw_ia: bus=%x, using ipmb\n",bus); status = ipmi_cmd_ipmb(cmd,netfn,lun,sa,bus,pdata,sdata,presp,sresp, pcc,fdebugcmd); return(status); } #endif set_fps(); requestData.cmdType = cmd; requestData.rsSa = sa; requestData.busType = bus; requestData.netFn = netfn; requestData.rsLun = lun; requestData.dataLength = sdata; requestData.data = pdata; if (fdebugcmd) { sz = sizeof(IMBPREQUESTDATA); pc = (BYTE *)&requestData.cmdType; fprintf(fpdbg,"ipmi_cmdraw_ia: request (len=%d): ",sz); for (i = 0; i < sz; i++) fprintf(fpdbg,"%02x ",pc[i]); fprintf(fpdbg,"\n"); pc = requestData.data; sz = requestData.dataLength; fprintf(fpdbg," req.data=%p, dlen=%d: ", pc, sz); for (i = 0; i < sz; i++) fprintf(fpdbg,"%02x ",pc[i]); fprintf(fpdbg,"\n"); } #ifdef WIN32 imbDev = "[imbdrv]"; if (1) #elif HPUX imbDev = "/dev/ipmi"; #else imbDev = "/dev/imb"; if (stat(imbDev, &stbuf) == -1) { fprintf(fperr,"ipmi_cmdraw_ia: No IMB driver found (%s)\n",imbDev); return(ERR_NO_DRV); } else /* imb device node is there */ #endif { sz = *sresp; /* note that sresp must be pre-set */ memset(presp, 0, sz); for ( i =0 ; i < IMB_MAX_RETRIES; i++) { *sresp = sz; /* retries may need to re-init *sresp */ #ifdef LOCAL_IPMB if (bus != PUBLIC_BUS) status = SendTimedIpmbpRequest(&requestData, ipmi_timeout_ia, presp, sresp, pcc); else #endif status = SendTimedImbpRequest(&requestData, ipmi_timeout_ia, presp, sresp, pcc); if((status) == 0 ) { break; } if (fdebugcmd) // only gets here if error fprintf(fpdbg,"ipmi_cmdraw_ia: sendImbRequest error status=%x, ccode=%x\n", (uint)status, *pcc); } } if (fdebugcmd) { /* if debug, show both good and bad statuses */ fprintf(fpdbg,"ipmi_cmdraw_ia: sendImbRequest status=%x, ccode=%x\n", (uint)status, *pcc); if (status == 0) { BYTE * pc; int sz; sz = *sresp; pc = (BYTE *)presp; fprintf(fpdbg,"ipmi_cmdraw_ia: response (len=%d): ",sz); for (i = 0; i < sz; i++) fprintf(fpdbg,"%02x ",pc[i]); fprintf(fpdbg,"\n"); } } if (status == 1) status = -3; /*LAN_ERR_RECV_FAIL, a meaningful error*/ return(status); } /* end ipmi_cmdraw_ia() */ /*---------------------------------------------------------------------*/ /*Used only by UW. Left here for now. IMB driver will not accept this //ioctl. */ ACCESN_STATUS StartAsyncMesgPoll() { DWORD retLength; BOOL status; #ifndef NO_MACRO_ARGS DEBUG("%s: DeviceIoControl cmd = %x\n",__FUNCTION__,IOCTL_IMB_POLL_ASYNC); #endif status = DeviceIoControl ( hDevice, IOCTL_IMB_POLL_ASYNC, NULL, 0, NULL, 0, & retLength, 0 ); #ifndef NO_MACRO_ARGS DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); #endif if( status == TRUE ) { return ACCESN_OK; } else { return ACCESN_ERROR; } } /*///////////////////////////////////////////////////////////////////////////// // SendTimedI2cRequest ///////////////////////////////////////////////////////////////////////////// */ /*F* // Name: SendTimedI2cRequest // Purpose: This function sends a request to a I2C device // Context: Used by Upper level agents (sis modules) to access dumb I2c devices // Returns: ACCESN_OK else error status code // Parameters: // reqPtr // timeOut // respDataPtr // respLen // Notes: none *F*/ ACCESN_STATUS SendTimedI2cRequest ( I2CREQUESTDATA *reqPtr, /* I2C request */ int timeOut, /* how long to wait, mSec units */ BYTE *respDataPtr, /* where to put response data */ int *respDataLen, /* size of response buffer and */ /* size of returned data */ BYTE *completionCode /* request status from BMC */ ) { BOOL status; BYTE responseData[MAX_IMB_RESP_SIZE]; ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; DWORD respLength = sizeof( responseData ); BYTE requestData[MAX_IMB_RESP_SIZE]; ImbRequestBuffer * req = (ImbRequestBuffer *) requestData; struct WriteReadI2C { /* format of a write/read I2C request */ BYTE busType; BYTE rsSa; BYTE count; BYTE data[1]; } * wrReq = (struct WriteReadI2C *) req->req.data; #define MIN_WRI2C_SIZE 3 /* size of write/read request minus any data */ /* // If the Imb driver is not present return AccessFailed */ req->req.rsSa = BMC_SA; req->req.cmd = WRITE_READ_I2C; req->req.netFn = APP_NETFN; req->req.rsLun = BMC_LUN; req->req.dataLength = reqPtr->dataLength + MIN_WRI2C_SIZE; wrReq->busType = reqPtr->busType; wrReq->rsSa = reqPtr->rsSa; wrReq->count = reqPtr->numberOfBytesToRead; memcpy( wrReq->data, reqPtr->data, reqPtr->dataLength ); req->flags = 0; req->timeOut = timeOut * 1000; /* convert to uSec units */ status = DeviceIoControl( hDevice, ioctl_sendmsg, requestData, sizeof( requestData ), & responseData, sizeof( responseData ), & respLength, NULL ); #ifndef NO_MACRO_ARGS DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); #endif if( status != TRUE ) { DWORD error; error = GetLastError(); return ACCESN_ERROR; } if( respLength == 0 ) { return ACCESN_ERROR; } /* // give the caller his response */ *completionCode = resp->cCode; *respDataLen = respLength - 1; if(( *respDataLen ) && (respDataPtr)) memcpy( respDataPtr, resp->data, *respDataLen); return ACCESN_OK; } /*This is not a API exported by the driver in stricter sense. It is //added to support EMP functionality. Upper level software could have //implemented this function.(pai 5/4/99) */ /*///////////////////////////////////////////////////////////////////////////// // SendTimedEmpMessageResponse ///////////////////////////////////////////////////////////////////////////// */ /*F* // Name: SendTimedEmpMessageResponse // Purpose: This function sends a response message to the EMP port // Context: // Returns: OK else error status code // Parameters: // // Notes: none *F*/ ACCESN_STATUS SendTimedEmpMessageResponse ( ImbPacket *ptr, /* pointer to the original request from EMP */ char *responseDataBuf, int responseDataLen, int timeOut /* how long to wait, in mSec units */ ) { BOOL status; BYTE responseData[MAX_IMB_RESP_SIZE]; /*ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; */ DWORD respLength = sizeof( responseData ); BYTE requestData[MAX_IMB_RESP_SIZE]; ImbRequestBuffer * req = (ImbRequestBuffer *) requestData; int i,j; /*form the response packet first */ req->req.rsSa = BMC_SA; if (IpmiVersion == IPMI_09_VERSION) req->req.cmd = WRITE_EMP_BUFFER; else req->req.cmd = SEND_MESSAGE; req->req.netFn = APP_NETFN; req->req.rsLun = 0; i = 0; if (IpmiVersion != IPMI_09_VERSION) req->req.data[i++] = EMP_CHANNEL; req->req.data[i++] = ptr->rqSa; req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3)); if (IpmiVersion == IPMI_09_VERSION) req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) +1); else req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) +1); req->req.data[i++] = BMC_SA; /*though software is responding, we have to //provide BMCs slave address as responder //address. */ req->req.data[i++] = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) ); req->req.data[i++] = ptr->cmd; for ( j = 0 ; j < responseDataLen ; ++j,++i) req->req.data[i] = responseDataBuf[j]; req->req.data[i] = 0; if (IpmiVersion == IPMI_09_VERSION) j = 0; else j = 1; for ( ; j < ( i -3); ++j) req->req.data[i] += req->req.data[j+3]; req->req.data[i] = ~(req->req.data[i]) +1; ++i; req->req.dataLength = (BYTE)i; req->flags = 0; req->timeOut = timeOut * 1000; /* convert to uSec units */ status = DeviceIoControl( hDevice, ioctl_sendmsg, requestData, sizeof(requestData), responseData, sizeof( responseData ), & respLength, NULL ); #ifndef NO_MACRO_ARGS DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); #endif if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) ) { return ACCESN_ERROR; } return ACCESN_OK; } /*This is not a API exported by the driver in stricter sense. It is added to support // EMP functionality. Upper level software could have implemented this function.(pai 5/4/99) */ /*/////////////////////////////////////////////////////////////////////////// // SendTimedEmpMessageResponse_Ex //////////////////////////////////////////////////////////////////////////// */ /*F* // Name: SendTimedEmpMessageResponse_Ex // Purpose: This function sends a response message to the EMP port // Context: // Returns: OK else error status code // Parameters: // // Notes: none *F*/ ACCESN_STATUS SendTimedEmpMessageResponse_Ex ( ImbPacket * ptr, /* pointer to the original request from EMP */ char *responseDataBuf, int responseDataLen, int timeOut, /* how long to wait, in mSec units*/ BYTE sessionHandle, /*This is introduced in IPMI1.5,this is required to be sent in //send message command as a parameter,which is then used by BMC //to identify the correct DPC session to send the mesage to. */ BYTE channelNumber /*There are 3 different channels on which DPC communication goes on //Emp - 1,Lan channel one - 6,Lan channel two(primary channel) - 7. */ ) { BOOL status; BYTE responseData[MAX_IMB_RESP_SIZE]; /* ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; */ DWORD respLength = sizeof( responseData ); BYTE requestData[MAX_IMB_RESP_SIZE]; ImbRequestBuffer * req = (ImbRequestBuffer *) requestData; int i,j; /*form the response packet first */ req->req.rsSa = BMC_SA; if (IpmiVersion == IPMI_09_VERSION) req->req.cmd = WRITE_EMP_BUFFER; else req->req.cmd = SEND_MESSAGE; req->req.netFn = APP_NETFN; req->req.rsLun = 0; i = 0; /*checking for the IPMI version & then assigning the channel number for EMP //Actually the channel number is same in both the versions.This is just to //maintain the consistancy with the same method for LAN. //This is the 1st byte of the SEND MESSAGE command. */ if (IpmiVersion == IPMI_10_VERSION) req->req.data[i++] = EMP_CHANNEL; else if (IpmiVersion == IPMI_15_VERSION) req->req.data[i++] = channelNumber; /*The second byte of data for SEND MESSAGE starts with session handle */ req->req.data[i++] = sessionHandle; /*Then it is the response slave address for SEND MESSAGE. */ req->req.data[i++] = ptr->rqSa; /*Then the net function + lun for SEND MESSAGE command. */ req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3)); /*Here the checksum is calculated.The checksum calculation starts after the channel number. //so for the IPMI 1.5 version its a checksum of 3 bytes that is session handle,response slave //address & netfun+lun. */ if (IpmiVersion == IPMI_09_VERSION) req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) +1); else { if (IpmiVersion == IPMI_10_VERSION) req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) +1); else req->req.data[i++] = ((~(req->req.data[2]+ req->req.data[3])) +1); } /*This is the next byte of the message data for SEND MESSAGE command.It is the request //slave address. */ req->req.data[i++] = BMC_SA; /*though software is responding, we have to //provide BMCs slave address as responder //address. */ /*This is just the sequence number,which is the next byte of data for SEND MESSAGE */ req->req.data[i++] = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) ); /*The next byte is the command like get software ID(00).*/ req->req.data[i++] = ptr->cmd; /*after the cmd the data ,which is sent by DPC & is retrived using the get message earlier // is sent back to DPC. */ for ( j = 0 ; j < responseDataLen ; ++j,++i) req->req.data[i] = responseDataBuf[j]; req->req.data[i] = 0; /*The last byte of data for SEND MESSAGE command is the check sum ,which is calculated //from the next byte of the previous checksum that is the request slave address. */ if (IpmiVersion == IPMI_09_VERSION) j = 0; else { if (IpmiVersion == IPMI_10_VERSION) j = 1; else j = 2; } for ( ; j < ( i -3); ++j) req->req.data[i] += req->req.data[j+3]; req->req.data[i] = ~(req->req.data[i]) +1; ++i; req->req.dataLength = (BYTE)i; /*The flags & timeouts are used by the driver internally. */ req->flags = 0; req->timeOut = timeOut * 1000; /* convert to uSec units */ status = DeviceIoControl( hDevice, ioctl_sendmsg, requestData, sizeof(requestData), responseData, sizeof( responseData ), & respLength, NULL ); #ifndef NO_MACRO_ARGS DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); #endif if (fdebug) { printf("SendTimedEmp(%x,%x): status=%d cc=%x rlen=%lu i=%d\n", sessionHandle, channelNumber, status,responseData[0],respLength,i); _dump_buf("requestData",requestData,sizeof(requestData),0); } if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) ) { return ACCESN_ERROR; } return ACCESN_OK; } /*This is not a API exported by the driver in stricter sense. It is //added to support EMP functionality. Upper level software could have //implemented this function.(pai 5/4/99) */ /*/////////////////////////////////////////////////////////////////////////// // SendTimedLanMessageResponse ///////////////////////////////////////////////////////////////////////////// */ /*F* // Name: SendTimedLanMessageResponse // Purpose: This function sends a response message to the DPC Over Lan // Context: // Returns: OK else error status code // Parameters: // // Notes: none *F*/ ACCESN_STATUS SendTimedLanMessageResponse( ImbPacket *ptr, /* pointer to the original request from EMP */ char *responseDataBuf, int responseDataLen, int timeOut /* how long to wait, in mSec units */ ) { BOOL status; BYTE responseData[MAX_IMB_RESP_SIZE]; /* ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; */ DWORD respLength = sizeof( responseData ); BYTE requestData[MAX_IMB_RESP_SIZE]; ImbRequestBuffer * req = (ImbRequestBuffer *) requestData; int i,j; /*form the response packet first */ req->req.rsSa = BMC_SA; if (IpmiVersion == IPMI_09_VERSION) req->req.cmd = WRITE_EMP_BUFFER; else req->req.cmd = SEND_MESSAGE; req->req.netFn = APP_NETFN; /* After discussion with firmware team (Shailendra), the lun number needs to stay at 0 // even though the DPC over Lan firmware EPS states that the lun should be 1 for DPC // Over Lan. - Simont (5/17/00) */ req->req.rsLun = 0; i = 0; if (IpmiVersion != IPMI_09_VERSION) req->req.data[i++] = LAN_CHANNEL; req->req.data[i++] = ptr->rqSa; req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3)); if (IpmiVersion == IPMI_09_VERSION) req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) +1); else req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) +1); req->req.data[i++] = BMC_SA; /*though software is responding, we have to //provide BMCs slave address as responder //address. */ req->req.data[i++] = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) ); req->req.data[i++] = ptr->cmd; for ( j = 0 ; j < responseDataLen ; ++j,++i) req->req.data[i] = responseDataBuf[j]; req->req.data[i] = 0; if (IpmiVersion == IPMI_09_VERSION) j = 0; else j = 1; for ( ; j < ( i -3); ++j) req->req.data[i] += req->req.data[j+3]; req->req.data[i] = ~(req->req.data[i]) +1; ++i; req->req.dataLength = (BYTE)i; req->flags = 0; req->timeOut = timeOut * 1000; /* convert to uSec units */ status = DeviceIoControl( hDevice, ioctl_sendmsg, requestData, sizeof(requestData), responseData, sizeof( responseData ), & respLength, NULL ); if (fdebug) { printf("SendTimedLan(): status=%d cc=%x rlen=%lu i=%d\n", status, responseData[0],respLength,i); _dump_buf("requestData",requestData,sizeof(requestData),0); } #ifndef NO_MACRO_ARGS DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); #endif if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) ) { return ACCESN_ERROR; } return ACCESN_OK; } /*This is not a API exported by the driver in stricter sense. It is //added to support EMP functionality. Upper level software could have //implemented this function.(pai 5/4/99) */ /*/////////////////////////////////////////////////////////////////////////// // SendTimedLanMessageResponse_Ex ///////////////////////////////////////////////////////////////////////////// */ /*F* // Name: SendTimedLanMessageResponse_Ex // Purpose: This function sends a response message to the DPC Over Lan // Context: // Returns: OK else error status code // Parameters: // // Notes: none *F*/ ACCESN_STATUS SendTimedLanMessageResponse_Ex( ImbPacket *ptr, /* pointer to the original request from EMP */ char *responseDataBuf, int responseDataLen, int timeOut , /* how long to wait, in mSec units */ BYTE sessionHandle, /*This is introduced in IPMI1.5,this is required to be sent in //send message command as a parameter,which is then used by BMC //to identify the correct DPC session to send the mesage to. */ BYTE channelNumber /*There are 3 different channels on which DPC communication goes on //Emp - 1,Lan channel one - 6,Lan channel two(primary channel) - 7. */ ) { BOOL status; BYTE responseData[MAX_IMB_RESP_SIZE]; /* ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; */ DWORD respLength = sizeof( responseData ); BYTE requestData[MAX_IMB_RESP_SIZE]; ImbRequestBuffer * req = (ImbRequestBuffer *) requestData; int i,j; /*form the response packet first */ req->req.rsSa = BMC_SA; if (IpmiVersion == IPMI_09_VERSION) req->req.cmd = WRITE_EMP_BUFFER; else req->req.cmd = SEND_MESSAGE; req->req.netFn = APP_NETFN; /* After discussion with firmware team (Shailendra), the lun number needs to stay at 0 // even though the DPC over Lan firmware EPS states that the lun should be 1 for DPC // Over Lan. - Simont (5/17/00) */ req->req.rsLun = 0; i = 0; /*checking for the IPMI version & then assigning the channel number for Lan accordingly. //This is the 1st byte of the SEND MESSAGE command. */ if (IpmiVersion == IPMI_10_VERSION) req->req.data[i++] = LAN_CHANNEL; else if (IpmiVersion == IPMI_15_VERSION) req->req.data[i++] = channelNumber; /*The second byte of data for SEND MESSAGE starts with session handle */ req->req.data[i++] = sessionHandle; /*Then it is the response slave address for SEND MESSAGE. */ req->req.data[i++] = ptr->rqSa; /*Then the net function + lun for SEND MESSAGE command. */ req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3)); /*Here the checksum is calculated.The checksum calculation starts after the channel number. //so for the IPMI 1.5 version its a checksum of 3 bytes that is session handle,response slave //address & netfun+lun. */ if (IpmiVersion == IPMI_09_VERSION) req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) +1); else { if (IpmiVersion == IPMI_10_VERSION) req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) +1); else req->req.data[i++] = ((~(req->req.data[2]+ req->req.data[3])) +1); } /*This is the next byte of the message data for SEND MESSAGE command.It is the request //slave address. */ req->req.data[i++] = BMC_SA; /*though software is responding, we have to //provide BMC's slave address as responder //address. */ /*This is just the sequence number,which is the next byte of data for SEND MESSAGE */ req->req.data[i++] = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) ); /*The next byte is the command like get software ID(00). */ req->req.data[i++] = ptr->cmd; /*after the cmd the data ,which is sent by DPC & is retrived using the get message earlier // is sent back to DPC. */ for ( j = 0 ; j < responseDataLen ; ++j,++i) req->req.data[i] = responseDataBuf[j]; req->req.data[i] = 0; /*The last byte of data for SEND MESSAGE command is the check sum ,which is calculated //from the next byte of the previous checksum that is the request slave address. */ if (IpmiVersion == IPMI_09_VERSION) j = 0; else { if (IpmiVersion == IPMI_10_VERSION) j = 1; else j = 2; } for ( ; j < ( i -3); ++j) req->req.data[i] += req->req.data[j+3]; req->req.data[i] = ~(req->req.data[i]) +1; ++i; req->req.dataLength = (BYTE)i; /*The flags & timeouts are used by the driver internally */ req->flags = 0; req->timeOut = timeOut * 1000; /* convert to uSec units */ status = DeviceIoControl( hDevice, ioctl_sendmsg, requestData, sizeof(requestData), responseData, sizeof( responseData ), & respLength, NULL ); #ifndef NO_MACRO_ARGS DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); #endif if (fdebug) { printf("SendTimedLan(%x,%x): status=%d cc=%x rlen=%lu i=%d\n", sessionHandle, channelNumber, status,responseData[0],respLength,i); if (responseData[0] != 0) /*0xcc == invalid request data*/ { BYTE *pb; pb = (BYTE *)req->req.data; printf("SendMessage data: %02x %02x %02x %02x %02x %02x %02x %02x\n", pb[0], pb[1], pb[2], pb[3], pb[4], pb[5], pb[6], pb[7]); _dump_buf("requestData",requestData,sizeof(requestData),0); } } if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) ) { return ACCESN_ERROR; } return ACCESN_OK; } /*///////////////////////////////////////////////////////////////////////// //SendAsyncImbpRequest /////////////////////////////////////////////////////////////////////////// */ /*F* // Name: SendAsyncImbpRequest // Purpose: This function sends a request for Asynchronous IMB implemented function // Context: Used by Upper level agents (sis modules) to access Asynchronous IMB implemented functionality. // Returns: OK else error status code // Parameters: // reqPtr Pointer to Async IMB request // seqNo Sequence Munber // Notes: none *F*/ ACCESN_STATUS SendAsyncImbpRequest ( IMBPREQUESTDATA *reqPtr, /* request info and data */ BYTE * seqNo /* sequence number used in creating IMB msg */ ) { BOOL status; BYTE responseData[MAX_IMB_RESP_SIZE]; ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; DWORD respLength = sizeof( responseData ); BYTE requestData[MAX_IMB_RESP_SIZE]; ImbRequestBuffer * req = (ImbRequestBuffer *) requestData; req->req.rsSa = reqPtr->rsSa; req->req.cmd = reqPtr->cmdType; req->req.netFn = reqPtr->netFn; req->req.rsLun = reqPtr->rsLun; req->req.dataLength = (BYTE)reqPtr->dataLength; memcpy( req->req.data, reqPtr->data, reqPtr->dataLength ); req->flags = NO_RESPONSE_EXPECTED; req->timeOut = 0; /* no timeouts for async sends */ status = DeviceIoControl( hDevice, ioctl_sendmsg, requestData, sizeof( requestData ), & responseData, sizeof( responseData ), & respLength, NULL ); #ifndef NO_MACRO_ARGS DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); #endif if( status != TRUE ) { DWORD error; error = GetLastError(); return ACCESN_ERROR; } if( respLength != 2 ) { return ACCESN_ERROR; } /* // give the caller his sequence number */ *seqNo = resp->data[0]; return ACCESN_OK; } /*/////////////////////////////////////////////////////////////////////////// //GetAsyncImbpMessage ///////////////////////////////////////////////////////////////////////////// */ /*F* // Name: GetAsyncImbpMessage // Purpose: This function gets the next available async message with a message id // greater than SeqNo. The message looks like an IMB packet // and the length and Sequence number is returned // Context: Used by Upper level agents (sis modules) to access Asynchronous IMB implemented functionality. // Returns: OK else error status code // Parameters: // msgPtr Pointer to Async IMB request // msgLen Length // timeOut Time to wait // seqNo Sequence Munber // Notes: none *F*/ ACCESN_STATUS GetAsyncImbpMessage ( ImbPacket * msgPtr, /* request info and data */ DWORD *msgLen, /* IN - length of buffer, OUT - msg len */ DWORD timeOut, /* how long to wait for the message */ ImbAsyncSeq *seqNo, /* previously returned seq number */ /* (or ASYNC_SEQ_START) */ DWORD channelNumber ) { BOOL status; BYTE responseData[MAX_ASYNC_RESP_SIZE], lun, b; ImbAsyncResponse * resp = (ImbAsyncResponse *) responseData; DWORD respLength = sizeof( responseData ); ImbAsyncRequest req; BYTE *msgb; while(1) { if( (msgPtr == NULL) || (msgLen == NULL) || ( seqNo == NULL) ) return ACCESN_ERROR; msgb = (BYTE *)msgPtr; req.timeOut = timeOut * 1000; /* convert to uSec units */ req.lastSeq = *seqNo; status = DeviceIoControl( hDevice, IOCTL_IMB_GET_ASYNC_MSG, & req, sizeof( req ), & responseData, sizeof( responseData ), & respLength, NULL ); #ifndef NO_MACRO_ARGS DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); #endif if( status != TRUE ) { DWORD error = GetLastError(); /* // handle "msg not available" specially. it is // different from a random old error. */ switch( error ) { case IMB_MSG_NOT_AVAILABLE: return ACCESN_END_OF_DATA; default: return ACCESN_ERROR; } return ACCESN_ERROR; } if( respLength < MIN_ASYNC_RESP_SIZE ) { return ACCESN_ERROR; } respLength -= MIN_ASYNC_RESP_SIZE; if( *msgLen < respLength ) { return ACCESN_ERROR; } /*same code as in NT section */ if ( IpmiVersion == IPMI_09_VERSION) { switch( channelNumber) { case IPMB_CHANNEL: lun = IPMB_LUN; break; case EMP_CHANNEL: lun = EMP_LUN; break; default: lun = RESERVED_LUN; break; } b = (((ImbPacket *)(resp->data))->nfLn) & 0x3; if (channelNumber != ANY_CHANNEL) { if ( (lun == RESERVED_LUN) || (lun != b) ) { *seqNo = resp->thisSeq; continue; } } memcpy( msgPtr, resp->data, respLength ); *msgLen = respLength; /* Hack to return actual lun */ if (channelNumber == ANY_CHANNEL) msgb[respLength] = b; } else { /* it is a 1.0 or above version */ b = resp->data[0]; if ((channelNumber != ANY_CHANNEL) && (channelNumber != b)) { *seqNo = resp->thisSeq; continue; } memcpy(msgPtr, &(resp->data[1]), respLength-1); *msgLen = respLength-1; /* Hack to return actual channel */ if (channelNumber == ANY_CHANNEL) msgb[respLength-1] = b; } /* // give the caller his sequence number */ *seqNo = resp->thisSeq; return ACCESN_OK; } /*while (1) */ } /*/////////////////////////////////////////////////////////////////////////// //GetAsyncImbpMessage_Ex ///////////////////////////////////////////////////////////////////////////// */ /*F* // Name: GetAsyncImbpMessage_Ex // Purpose: This function gets the next available async message with a message id // greater than SeqNo. The message looks like an IMB packet // and the length and Sequence number is returned // Context: Used by Upper level agents (sis modules) to access Asynchronous IMB implemented functionality. // Returns: OK else error status code // Parameters: // msgPtr Pointer to Async IMB request // msgLen Length // timeOut Time to wait // seqNo Sequence Munber // Notes: none *F*/ ACCESN_STATUS GetAsyncImbpMessage_Ex ( ImbPacket * msgPtr, /* request info and data */ DWORD *msgLen, /* IN - length of buffer, OUT - msg len */ DWORD timeOut, /* how long to wait for the message */ ImbAsyncSeq *seqNo, /* previously returned seq number */ /* (or ASYNC_SEQ_START) */ DWORD channelNumber, BYTE * sessionHandle, BYTE * privilege ) { BOOL status; BYTE responseData[MAX_ASYNC_RESP_SIZE], lun, b; ImbAsyncResponse * resp = (ImbAsyncResponse *) responseData; DWORD respLength = sizeof( responseData ); ImbAsyncRequest req; BYTE *msgb; while(1) { if( (msgPtr == NULL) || (msgLen == NULL) || ( seqNo == NULL) ) return ACCESN_ERROR; msgb = (BYTE *)msgPtr; req.timeOut = timeOut * 1000; /* convert to uSec units */ req.lastSeq = *seqNo; status = DeviceIoControl( hDevice, IOCTL_IMB_GET_ASYNC_MSG, & req, sizeof( req ), & responseData, sizeof( responseData ), & respLength, NULL ); #ifndef NO_MACRO_ARGS DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); #endif if( status != TRUE ) { DWORD error = GetLastError(); /* // handle "msg not available" specially. it is // different from a random old error. */ switch( error ) { case IMB_MSG_NOT_AVAILABLE: return ACCESN_END_OF_DATA; default: return ACCESN_ERROR; } return ACCESN_ERROR; } if( respLength < MIN_ASYNC_RESP_SIZE ) { return ACCESN_ERROR; } respLength -= MIN_ASYNC_RESP_SIZE; if( *msgLen < respLength ) { return ACCESN_ERROR; } /*same code as in NT section */ if ( IpmiVersion == IPMI_09_VERSION) { switch( channelNumber) { case IPMB_CHANNEL: lun = IPMB_LUN; break; case EMP_CHANNEL: lun = EMP_LUN; break; default: lun = RESERVED_LUN; break; } b = ((((ImbPacket *)(resp->data))->nfLn) & 0x3); if (channelNumber != ANY_CHANNEL) { if ( (lun == RESERVED_LUN) || (lun != b) ) { *seqNo = resp->thisSeq; continue; } } memcpy( msgPtr, resp->data, respLength ); *msgLen = respLength; /* Hack to return actual lun */ if (channelNumber == ANY_CHANNEL) msgb[respLength] = b; } else { if((sessionHandle ==NULL) || (privilege ==NULL)) return ACCESN_ERROR; /*With the new IPMI version the get message command returns the //channel number along with the privileges.The 1st 4 bits of the //second byte of the response data for get message command represent //the channel number & the last 4 bits are the privileges. */ *privilege = (resp->data[0] & 0xf0)>> 4; #ifndef NO_MACRO_ARGS DEBUG("GetAsy: chan=%x chan_parm=%x\n",resp->data[0],channelNumber); #endif b = (resp->data[0] & 0x0f); if ((channelNumber != ANY_CHANNEL) && (channelNumber != b) ) { *seqNo = resp->thisSeq; continue; } /*The get message command according to IPMI 1.5 spec now even //returns the session handle.This is required to be captured //as it is required as request data for send message command. */ *sessionHandle = resp->data[1]; memcpy( msgPtr, &(resp->data[2]), respLength-1 ); *msgLen = respLength-1; /* Hack to return actual channel */ if (channelNumber == ANY_CHANNEL) msgb[respLength-1] = b; } /* // give the caller his sequence number */ *seqNo = resp->thisSeq; return ACCESN_OK; } /*while (1) */ } /*////////////////////////////////////////////////////////////////////////////// //IsAsyncMessageAvailable ///////////////////////////////////////////////////////////////////////////// */ /*F* // Name: IsMessageAvailable // Purpose: This function waits for an Async Message // // Context: Used by Upper level agents access Asynchronous IMB based // messages // Returns: OK else error status code // Parameters: // eventId // // Notes: This call will block the calling thread if no Async events are // are available in the queue. // *F*/ ACCESN_STATUS IsAsyncMessageAvailable (HandleType eventId ) { int dummy; int respLength = 0; BOOL status; /* confirm that app is not using a bad Id */ if ( AsyncEventHandle != eventId) { #ifdef LINUX printf("Invalid AsyncHandle %lx!=%lx\n",AsyncEventHandle,eventId); #endif return ACCESN_ERROR; } dummy = 0; status = DeviceIoControl(hDevice, IOCTL_IMB_CHECK_EVENT, &AsyncEventHandle, sizeof(HandleType), &dummy, sizeof(int), (LPDWORD) & respLength, NULL ); // if (fdebug) // printf("IsAsyncMessageAvail: status=%d rlen=%d dummy=%x\n", // status, respLength, dummy); #ifndef NO_MACRO_ARGS DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); #endif if( status != TRUE ) return ACCESN_ERROR; return ACCESN_OK; } /*I have retained this commented code because later we may want to use //DPC message specific Processing (pai 11/21) */ #ifdef NOT_COMPILED_BUT_LEFT_HERE_FOR_NOW /*////////////////////////////////////////////////////////////////////////////// //GetAsyncDpcMessage ///////////////////////////////////////////////////////////////////////////// */ /*F* // Name: GetAsyncDpcMessage // Purpose: This function gets the next available async message from // the DPC client. // // Context: Used by Upper level agents access Asynchronous IMB based // messages sent by the DPC client. // Returns: OK else error status code // Parameters: // msgPtr Pointer to Async IMB request // msgLen Length // timeOut Time to wait // seqNo Sequence Munber // Notes: This call will block the calling thread if no Async events are // are available in the queue. // *F*/ ACCESN_STATUS GetAsyncDpcMessage ( ImbPacket * msgPtr, /* request info and data */ DWORD * msgLen, /* IN - length of buffer, OUT - msg len */ DWORD timeOut, /* how long to wait for the message */ ImbAsyncSeq * seqNo, /* previously returned seq number (or ASYNC_SEQ_START) */ ) { BOOL status; BYTE responseData[MAX_ASYNC_RESP_SIZE]; ImbAsyncResponse * resp = (ImbAsyncResponse *) responseData; DWORD respLength = sizeof( responseData ); ImbAsyncRequest req; if( msgPtr == NULL || msgLen == NULL || seqNo == NULL ) return ACCESN_ERROR; req.lastSeq = *seqNo; hEvt = CreateEvent (NULL, TRUE, FALSE, NULL) ; if (!hEvt) { return ACCESN_ERROR; } status = DeviceIoControl( hDevice, IOCTL_IMB_GET_DPC_MSG, & req, sizeof( req ), & responseData, sizeof( responseData ), & respLength, &ovl ); if( status != TRUE ) { DWORD error = GetLastError(); /* // handle "msg not available" specially. it is different from // a random old error. // */ if (!status) { switch (error ) { case ERROR_IO_PENDING: WaitForSingleObject (hEvt, INFINITE) ; ResetEvent (hEvt) ; break; case IMB_MSG_NOT_AVAILABLE: CloseHandle(hEvt); return ACCESN_END_OF_DATA; default: CloseHandle(hEvt); return ACCESN_ERROR; } } if ( ( GetOverlappedResult(hDevice, &ovl, (LPDWORD)&respLength, TRUE ) == 0 ) || (respLength <= 0) ) { CloseHandle(hEvt); return ACCESN_ERROR; } } if( respLength < MIN_ASYNC_RESP_SIZE ) { CloseHandle(hEvt); return ACCESN_ERROR; } respLength -= MIN_ASYNC_RESP_SIZE; if( *msgLen < respLength ) { /* The following code should have been just return ACCESN_out_of_range */ CloseHandle(hEvt); return ACCESN_ERROR; } memcpy( msgPtr, resp->data, respLength ); *msgLen = respLength; /* // give the caller his sequence number */ *seqNo = resp->thisSeq; CloseHandle(hEvt); return ACCESN_OK; } #endif /*NOT_COMPILED_BUT_LEFT_HERE_FOR_NOW*/ /*///////////////////////////////////////////////////////////////////////////// //RegisterForImbAsyncMessageNotification ///////////////////////////////////////////////////////////////////////////// */ /*F* // Name: RegisterForImbAsyncMessageNotification // Purpose: This function Registers the calling application // for Asynchronous notification when a sms message // is available with the IMB driver. // // Context: Used by Upper level agents to know that an async // SMS message is available with the driver. // Returns: OK else error status code // Parameters: // handleId pointer to the registration handle // // Notes: The calling application should use the returned handle to // get the Async messages.. *F*/ ACCESN_STATUS RegisterForImbAsyncMessageNotification (HandleType *handleId) { BOOL status; DWORD respLength ; int dummy; /*allow only one app to register */ if( (handleId == NULL ) || (AsyncEventHandle) ) return ACCESN_ERROR; status = DeviceIoControl(hDevice, IOCTL_IMB_REGISTER_ASYNC_OBJ, &dummy, sizeof( int ), &AsyncEventHandle, sizeof(HandleType), (LPDWORD) & respLength, NULL ); #ifndef NO_MACRO_ARGS DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); #endif if( (respLength != sizeof(int)) || (status != TRUE )) { if (fdebug) { printf("RegisterForImbAsync error status=%d, len=%lu sizeint=%lu\n", status, respLength, sizeof(int)); if( respLength != sizeof(int)) printf("Async len err\n"); if( status != TRUE) printf("Async status err\n"); } return ACCESN_ERROR; } *handleId = AsyncEventHandle; #ifndef NO_MACRO_ARGS DEBUG("handleId = %x AsyncEventHandle %x\n", *handleId, AsyncEventHandle); #endif return ACCESN_OK; } /*///////////////////////////////////////////////////////////////////////////// //UnRegisterForImbAsyncMessageNotification ///////////////////////////////////////////////////////////////////////////// */ /*F* // Name: UnRegisterForImbAsyncMessageNotification // Purpose: This function un-registers the calling application // for Asynchronous notification when a sms message // is available with the IMB driver. // // Context: Used by Upper level agents to un-register // for async. notification of sms messages // Returns: OK else error status code // Parameters: // handleId pointer to the registration handle // iFlag value used to determine where this function was called from // _it is used currently on in NetWare environment_ // // Notes: *F*/ ACCESN_STATUS UnRegisterForImbAsyncMessageNotification (HandleType handleId, int iFlag) { BOOL status; DWORD respLength ; int dummy; iFlag = iFlag; /* to keep compiler happy We are not using this flag*/ if ( AsyncEventHandle != handleId) return ACCESN_ERROR; status = DeviceIoControl(hDevice, IOCTL_IMB_DEREGISTER_ASYNC_OBJ, &AsyncEventHandle, sizeof(HandleType), &dummy, (DWORD)sizeof(int ), (LPDWORD) & respLength, NULL ); #ifndef NO_MACRO_ARGS DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); #endif if( status != TRUE ) return ACCESN_ERROR; return ACCESN_OK; } /*/////////////////////////////////////////////////////////////////////////// // SetShutDownCode ///////////////////////////////////////////////////////////////////////////// */ /*F* // Name: SetShutDownCode // Purpose: To set the shutdown action code // Context: Called by the System Control Subsystem // Returns: none // Parameters: // code shutdown action code which can be either // SD_NO_ACTION, SD_RESET, SD_POWER_OFF as defined in imb_if.h *F*/ ACCESN_STATUS SetShutDownCode ( int delayTime, /* time to delay in 100ms units */ int code /* what to do when time expires */ ) { DWORD retLength; BOOL status; ShutdownCmdBuffer cmd; /* // If Imb driver is not present return AccessFailed */ if(hDevice == INVALID_HANDLE_VALUE) return ACCESN_ERROR; cmd.code = code; cmd.delayTime = delayTime; status = DeviceIoControl( hDevice, IOCTL_IMB_SHUTDOWN_CODE, & cmd, sizeof( cmd ), NULL, 0, & retLength, NULL ); #ifndef NO_MACRO_ARGS DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); #endif if(status == TRUE) return ACCESN_OK; else return ACCESN_ERROR; } #ifdef IMB_MEMORY /*///////////////////////////////////////////////////////////////////////// // MapPhysicalMemory /////////////////////////////////////////////////////////////////////////// */ /*F* // Name: MapPhysicalMemory // Purpose: This function maps specified range of physical memory in calling // pocesse's address space // Context: Used by Upper level agents (sis modules) to access // system physical memory // Returns: ACCESN_OK else error status code // Parameters: // // startAddress starting physical address of the memory to be mapped // addressLength length of the physical memory to be mapped // virtualAddress pointer to the mapped virtual address // Notes: none *F*/ /*/////////////////////////////////////////////////////////////////////////// // UnmapPhysicalMemory //////////////////////////////////////////////////////////////////////////// */ /*F* // Name: UnMapPhysicalMemory // Purpose: This function unmaps the previously mapped physical memory // Context: Used by Upper level agents (sis modules) // Returns: ACCESN_OK else error status code // Parameters: // // addressLength length of the physical memory to be mapped // virtualAddress pointer to the mapped virtual address // Notes: none *F*/ #ifdef WIN32 ACCESN_STATUS MapPhysicalMemory ( int startAddress, // physical address to map in int addressLength, // how much to map int *virtualAddress // where it got mapped to ) { DWORD retLength; BOOL status; PHYSICAL_MEMORY_INFO pmi; if ( startAddress == (int) NULL || addressLength <= 0 ) return ACCESN_OUT_OF_RANGE; pmi.InterfaceType = Internal; pmi.BusNumber = 0; pmi.BusAddress.HighPart = (LONG)0x0; pmi.BusAddress.LowPart = (LONG)startAddress; pmi.AddressSpace = (LONG) 0; pmi.Length = addressLength; status = DeviceIoControl ( hDevice, IOCTL_IMB_MAP_MEMORY, & pmi, sizeof(PHYSICAL_MEMORY_INFO), virtualAddress, sizeof(PVOID), & retLength, 0 ); if( status == TRUE ) { return ACCESN_OK; } else { return ACCESN_ERROR; } } ACCESN_STATUS UnmapPhysicalMemory ( int virtualAddress, // what memory to unmap int Length ) { DWORD retLength; BOOL status; status = DeviceIoControl ( hDevice, IOCTL_IMB_UNMAP_MEMORY, & virtualAddress, sizeof(PVOID), NULL, 0, & retLength, 0 ); if( status == TRUE ) { return ACCESN_OK; } else { return ACCESN_ERROR; } } #else /*Linux, SCO, UNIX, etc.*/ ACCESN_STATUS MapPhysicalMemory(int startAddress,int addressLength, int *virtualAddress ) { int fd, i; unsigned int length = addressLength; off_t startpAddress = (off_t)startAddress; unsigned int diff; caddr_t startvAddress; if ((startAddress == (int) NULL) || (addressLength <= 0)) return ACCESN_ERROR; if ( (fd = open("/dev/mem", O_RDONLY)) < 0) { char buf[128]; sprintf(buf,"%s %s: open(%s) failed", __FILE__,__FUNCTION__,"/dev/mem"); perror(buf); return ACCESN_ERROR ; } /* aliging the offset to a page boundary and adjusting the length */ diff = (int)startpAddress % PAGESIZE; startpAddress -= diff; length += diff; if ( (startvAddress = mmap( (caddr_t)0, length, PROT_READ, MAP_SHARED, fd, startpAddress ) ) == (caddr_t)-1) { char buf[128]; sprintf(buf,"%s %s: mmap failed", __FILE__,__FUNCTION__); perror(buf); close(fd); return ACCESN_ERROR; } #ifndef NO_MACRO_ARGS DEBUG("%s: mmap of 0x%x success\n",__FUNCTION__,startpAddress); #endif #ifdef LINUX_DEBUG_MAX /* dont want this memory dump for normal level of debugging. // So, I have put it under a stronger debug symbol. mahendra */ for(i=0; i < length; i++) { printf("0x%x ", (startvAddress[i])); if(isascii(startvAddress[i])) { printf("%c ", (startvAddress[i])); } } #endif /*LINUX_DEBUG_MAX */ *virtualAddress = (int)(startvAddress + diff); return ACCESN_OK; } ACCESN_STATUS UnmapPhysicalMemory( int virtualAddress, int Length ) { unsigned int diff = 0; /* page align the virtual address and adjust length accordingly */ diff = ((unsigned int) virtualAddress) % PAGESIZE; virtualAddress -= diff; Length += diff; #ifndef NO_MACRO_ARGS DEBUG("%s: calling munmap(0x%x,%d)\n",__FUNCTION__,virtualAddress,Length); #endif if(munmap((caddr_t)virtualAddress, Length) != 0) { char buf[128]; sprintf(buf,"%s %s: munmap failed", __FILE__,__FUNCTION__); perror(buf); return ACCESN_ERROR; } #ifndef NO_MACRO_ARGS DEBUG("%s: munmap(0x%x,%d) success\n",__FUNCTION__,virtualAddress,Length); #endif return ACCESN_OK; } #endif /*unix*/ #endif /*IMB_MEMORY*/ /*///////////////////////////////////////////////////////////////////////////// // GetIpmiVersion //////////////////////////////////////////////////////////////////////////// */ /*F* // Name: GetIpmiVersion // Purpose: This function returns current IPMI version // Context: // Returns: IPMI version // Parameters: // reqPtr // timeOut // respDataPtr // respLen // Notes: svuppula *F*/ BYTE GetIpmiVersion() { return ((BYTE)IpmiVersion); } #ifdef IMBDLL /* Inlude this routine if building WIN32 imbapi.dll */ BOOL WINAPI DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { switch(ulReason) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: break; case DLL_PROCESS_DETACH: case DLL_THREAD_DETACH: break; default: return FALSE; } return TRUE; } #endif #endif /*end of imbapi.c*/ ipmiutil-3.1.5/util/ihealth.c0000644000076400007640000012160313566765324016220 0ustar mgportalloggers/* * ihealth.c (was bmchealth.c) * * This tool checks the health of the BMC via IPMI. * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2006 Intel Corporation. * Copyright (c) 2009 Kontron America, Inc. * * 03/22/06 Andy Cress - created * 06/20/06 Andy Cress 0.6 - more vendor strings, add ping_node() stub for now * 10/20/06 Andy Cress 1.1 - added -g for guid * 01/10/07 Andy Cress 1.4 - added product strings * 02/25/07 Andy Cress 2.8 - added more Chassis Status decoding * 09/18/17 Andy Cress 3.07 - Set do_powerstate=0 for Sun, continue if failure */ /*M* Copyright (c) 2006, Intel Corporation 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 Corporation 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*/ #ifdef WIN32 #include #include #include #include "getopt.h" #elif defined(DOS) #include #include #include #include "getopt.h" #else #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include #include "ipmicmd.h" #include "oem_intel.h" #define SELFTEST_STATUS 0x04 #define GET_POWER_STATE 0x07 extern int get_BiosVersion(char *str); extern int get_SystemGuid(uchar *guid); extern int GetSDR(int id, int *next, uchar *recdata, int srecdata, int *rlen); extern int get_device_guid(uchar *pbuf, int *sz); /*subs.c*/ extern int oem_supermicro_get_health(char *pstr, int sz); /*oem_supermicro.c*/ extern int oem_supermicro_get_firmware_str(char *pstr, int sz); /*oem_supermicro.c*/ /* * Global variables */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil health"; #else static char * progver = "3.08"; static char * progname = "ihealth"; #endif static char fdebug = 0; static char fipmilan = 0; static char fcanonical = 0; static char do_hsc = 0; static char do_me = 0; static char do_frusdr = 0; static char do_guid = 0; static char do_powerstate = 1; static char do_lanstats = 0; static char do_session = 0; static char do_systeminfo = 0; static char set_restore = 0; static char set_name = 0; static char set_os = 0; static char set_os2 = 0; static uchar restore_policy = 0; static uchar bChan = 0x0e; static char fmBMC = 0; static char bdelim = '='; /*delimiter to separate name/value pairs*/ static char bcomma = ','; /*comma delimiter, may change if CSV*/ static char lan_ch_restrict = 0; static int kcs_loops = 0; static int vend_id = 0; static int prod_id = 0; static char *pname = NULL; static char *pos = NULL; static char *pos2 = NULL; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; int oem_get_health(char *pstr, int sz) { int rv; switch(vend_id) { case VENDOR_PEPPERCON: case VENDOR_SUPERMICRO: rv = oem_supermicro_get_health(pstr, sz); break; case VENDOR_SUPERMICROX: rv = oem_supermicro_get_firmware_str(pstr,sz); break; default: rv = LAN_ERR_NOTSUPPORT; break; } if (fdebug) printf("oem_get_health rv = %d\n",rv); return rv; } char *getdmiprod(void) { char *prod = ""; #ifdef LINUX static char dmiprod[32]; char cmd[160]; char *dmitmp = "/tmp/dmi.tmp"; FILE *fp; int rv, i; if (fipmilan) return(prod); sprintf(cmd,"dmidecode | grep -A6 \"^Base Board\" |grep 'Product Name' |cut -f2 -d':' |awk '{ print $1 }' >%s",dmitmp); rv = system(cmd); if (rv == 0) { fp = fopen(dmitmp,"r"); if (fp == NULL) rv = -1; else { if (fgets(dmiprod, sizeof(dmiprod), fp) == NULL) rv = -2; else { for (i=0; i> 8); idata[3] = (uchar)((hnd & 0x00FF0000) >> 16); idata[4] = (uchar)((hnd & 0xFF000000) >> 24); ilen = 5; } rlen = *len; *len = 0; rv = ipmi_cmdraw(CMD_GET_SESSION_INFO,NETFN_APP, g_sa, g_bus, g_lun, idata,ilen, rdata,&rlen,&cc, fdebug); if (fdebug) printf("get_lan_stats: rv = %d, cc = %02x\n",rv,cc); if (rv == 0) *len = rlen; if ((rv == 0) && (cc != 0)) rv = cc; return(rv); } static char *sesstype_str(uchar c) { uchar b; char *s; b = ((c & 0xf0) >> 4); switch(b) { case 0: s = "IPMIv1.5"; break; case 1: s = "IPMIv2/RMCP+"; break; default: s = "Other"; break; } return s; } static void show_session_info(uchar idx, uchar *sinfo,int len) { int i; char lan_type = 1; if (fdebug) { printf("Raw Session Info[%d]: ",idx); for (i = 0; i < len; i++) printf("%02x ",sinfo[i]); printf("\n"); } printf("Session Info[%d]:\n",idx); printf("\tSession Handle %c %d\n",bdelim,sinfo[0]); printf("\tSession Slot Count %c %d\n",bdelim,(sinfo[1] & 0x3f)); printf("\tActive Sessions %c %d\n",bdelim,(sinfo[2] & 0x3f)); if (len <= 3) return; printf("\tUser ID %c %d\n",bdelim,(sinfo[3] & 0x3f)); printf("\tPrivilege Level %c %d\n",bdelim,(sinfo[4] & 0x0f)); printf("\tSession Type %c %s\n",bdelim,sesstype_str(sinfo[5])); printf("\tChannel Number %c %d\n",bdelim,(sinfo[5] & 0x0f)); if (len <= 6) return; if (lan_type) { printf("\tConsole IP %c %d.%d.%d.%d\n",bdelim, sinfo[6],sinfo[7],sinfo[8],sinfo[9]); printf("\tConsole MAC %c %02x:%02x:%02x:%02x:%02x:%02x\n",bdelim, sinfo[10], sinfo[11], sinfo[12], sinfo[13], sinfo[14], sinfo[15]); printf("\tConsole Port %c %d\n",bdelim, sinfo[16]+ (sinfo[17] << 8)); } } int get_session_info_all(void) { int rv, len, nslots, i; uchar sinfo[24]; nslots = 1; for (i = 1; i <= nslots; i++) { len = sizeof(sinfo); rv = get_session_info(i,0,sinfo,&len); if (fdebug) printf("get_session_info(%d): rv = %d\n",i,rv); if (rv != 0) { if ((rv == 0xCB) || (rv == 0xCC)) { if (len >= 3) show_session_info(i,sinfo,len); if (i > 1) rv = 0; /*no such idx, end */ } break; } nslots = (sinfo[1] & 0x3F); show_session_info(i,sinfo,len); } return(rv); } static int get_selftest_status(uchar *rdata, int rlen) { uchar idata[4]; uchar ccode; int ret; ret = ipmi_cmdraw( SELFTEST_STATUS, NETFN_APP, g_sa, g_bus, g_lun, idata,0, rdata,&rlen,&ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; return(ret); } /*end get_selftest_status()*/ static int get_last_selftest(uchar *val, int vlen) { uchar idata[4]; uchar rdata[16]; int rlen; uchar ccode; int ret; if (val == NULL) return(ERR_BAD_PARAM); idata[0] = 0; /*0=first, 1=next*/ memset(rdata,0xFF,2); /*initial value = end-of-list*/ rlen = sizeof(rdata); ret = ipmi_cmdraw( 0x16, 0x30, g_sa, g_bus, g_lun, idata,1, rdata,&rlen,&ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; if (ret == 0) { if (rlen <= 0) ret = LAN_ERR_BADLENGTH; else { if (rlen > vlen) rlen = vlen; /*truncate if too long*/ memcpy(val,rdata,rlen); } } return(ret); } static int get_chassis_status(uchar *rdata, int *rsz) { uchar idata[4]; uchar ccode; int rlen; int ret; rlen = *rsz; ret = ipmi_cmdraw( CHASSIS_STATUS, NETFN_CHAS, g_sa, g_bus, g_lun, idata,0, rdata,&rlen,&ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; if (ret == 0) *rsz = rlen; return(ret); } /*end chassis_status()*/ static void show_chs_status(uchar *sbuf, int slen) { char chs_strbuf[80]; char *pstr; uchar state, b2, b3, b4; pstr = &chs_strbuf[0]; state = sbuf[0] & 0x7f; b2 = sbuf[1]; b3 = sbuf[2]; sprintf(pstr,"%s",(state & 0x01) ? "on" : "off"); printf("Chassis Status %c %02x %02x %02x %02x (%s, see below)\n", bdelim,state,sbuf[1],sbuf[2],sbuf[3],pstr); sprintf(pstr,"\tchassis_power %c ",bdelim); if (state & 0x01) strcat(pstr,"on"); else strcat(pstr,"off"); if (state & 0x02) strcat(pstr,", overload"); if (state & 0x04) strcat(pstr,", interlock"); if (state & 0x08) strcat(pstr,", fault"); if (state & 0x10) strcat(pstr,", control error"); printf("%s\n",pstr); sprintf(pstr,"\tpwr_restore_policy %c ",bdelim); if (state & 0x20) strcat(pstr,"last_state"); else if (state & 0x40) strcat(pstr,"turn_on"); else strcat(pstr,"stay_off"); printf("%s\n",pstr); if (b2 != 0) { sprintf(pstr,"\tlast_power_event %c ",bdelim); if (b2 & 0x10) strcat(pstr,"IPMI "); if (b2 & 0x08) strcat(pstr,"fault "); if (b2 & 0x04) strcat(pstr,"interlock "); if (b2 & 0x02) strcat(pstr,"overload "); if (b2 & 0x01) strcat(pstr,"ACfailed"); printf("%s\n",pstr); } printf("\tchassis_intrusion %c %s\n", bdelim, (b3 & 0x01) ? "active":"inactive"); printf("\tfront_panel_lockout %c %s\n", bdelim, (b3 & 0x02) ? "active":"inactive"); printf("\tdrive_fault %c %s\n", bdelim, (b3 & 0x04) ? "true":"false"); printf("\tcooling_fan_fault %c %s\n", bdelim, (b3 & 0x08) ? "true":"false"); if (slen > 3) { b4 = sbuf[3]; if (b4 & 0x80) { printf("\tFP sleep_button_disable %c allowed, button %s\n",bdelim, (b4 & 0x08) ? "disabled":"enabled"); } if (b4 & 0x40) { printf("\tFP diag_button_disable %c allowed, button %s\n",bdelim, (b4 & 0x04) ? "disabled":"enabled"); } if (b4 & 0x20) { printf("\tFP reset_button_disable %c allowed, button %s\n",bdelim, (b4 & 0x02) ? "disabled":"enabled"); } if (b4 & 0x10) { printf("\tFP power_button_disable %c allowed, button %s\n",bdelim, (b4 & 0x01) ? "disabled":"enabled"); } } return; } static int get_power_state(uchar *rdata, int rlen) { uchar idata[4]; uchar ccode; int ret; ret = ipmi_cmdraw( GET_POWER_STATE, NETFN_APP, g_sa, g_bus, g_lun, idata,0, rdata,&rlen,&ccode, fdebug); if (ret == 0 && ccode == 193) { /*0xB7, usu. SuperMicro, retry */ ret = ipmi_cmdraw( GET_POWER_STATE, NETFN_APP, g_sa, g_bus, g_lun, idata,0, rdata,&rlen,&ccode, fdebug); } if (ret == 0 && ccode != 0) ret = ccode; return(ret); } /*end get_power_state()*/ static char *pwr_string(uchar pstate) { char *pstr; switch(pstate) { case 0x00: pstr = "S0: working"; break; case 0x01: pstr = "S1: clock stopped, context ok"; break; case 0x02: pstr = "S2: clock stopped, context lost"; break; case 0x03: pstr = "S3: suspend-to-RAM"; break; case 0x04: pstr = "S4: suspend-to-Disk"; break; case 0x05: pstr = "S5: soft off"; break; case 0x06: pstr = "S4/S5: soft off, either S4 or S5"; break; case 0x07: pstr = "G3: mechanical off"; break; case 0x08: pstr = "S1-S3: sleeping"; break; case 0x09: pstr = "S1-S4: sleeping"; break; case 0x0A: pstr = "S5/o: soft off by override"; break; case 0x20: pstr = "legacy on"; break; case 0x21: pstr = "legacy soft-off"; break; case 0x2a: /* not initialized or device lost track of state */ default: pstr = "unknown"; break; } return(pstr); } #ifdef PING_OK extern int ping_bmc(char *node, char fdebug); static int ping_node(char *node) { int rv = 0; /* verify that the BMC LAN channel is configured & active */ /* send rmcp_ping to node's BMC */ rv = ping_bmc(node,fdebug); return(rv); } #endif #define MIN_SDR_SZ 8 static int get_frusdr_version(char *pver, int sver) { ushort recid; int recnext; int ret, sz, i, len; uchar sdr[MAX_BUFFER_SIZE]; char verstr[30]; char fIntel; int verlen; recid = 0; verstr[0] = 0; verlen = 0; while (recid != 0xffff) { memset(sdr,0,sizeof(sdr)); ret = GetSDR(recid,&recnext,sdr,sizeof(sdr),&sz); if (fdebug) printf("GetSDR[%04x]: ret = %x, next=%x\n",recid,ret,recnext); if (ret != 0) { if (ret > 0) { /* ret is a completion code error */ if (fdebug) printf("%04x GetSDR error 0x%02x %s, rlen=%d\n",recid,ret, decode_cc((ushort)0,(uchar)ret),sz); } else printf("%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 */ } else { /*got SDR */ len = sdr[4] + 5; if (sdr[3] == 0xC0) { /* OEM SDR */ /* check for Intel mfg id */ if ((sdr[5] == 0x57) && (sdr[6] == 0x01) && (sdr[7] == 0x00)) fIntel = 1; else fIntel = 0; if (sdr[8] == 0x53) { /*Intel OEM subtype, ASCII 'S' */ verlen = 0; for (i = 8; i < len; i++) { if (sdr[i] == 0) break; if (i >= sizeof(verstr)) break; verstr[verlen++] = sdr[i]; } verstr[verlen] = 0; /*stringify*/ /* continue on past SDR File, get SDR Package version */ // break; } } /*endif OEM SDR*/ } if (recnext == recid) recid = 0xffff; /*break;*/ else recid = (ushort)recnext; } if (verlen > sver) verlen = sver; if (fdebug) printf("get_frusdr_version: verstr=%s, verlen=%d\n",verstr,verlen); strncpy(pver,verstr,verlen); return(ret); } static int get_hsc_devid(uchar *rdata, int rlen) { uchar ccode; int ret; ret = ipmi_cmdraw( 0x01, /*(GET_DEVICEID & 0x00ff)*/ NETFN_APP, 0xC0,PUBLIC_BUS,BMC_LUN, NULL,0, rdata,&rlen,&ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; return(ret); } /*end get_hsc_devid*/ static int get_chan_auth(uchar chan, uchar *rdata, int rlen) { uchar idata[4]; uchar ccode; int ret; idata[0] = chan; /*0x0e = this channel*/ idata[1] = 0x02; /*priv level = user*/ ret = ipmi_cmdraw( 0x38, NETFN_APP, /*CMD_GET_CHAN_AUTH_CAP*/ g_sa, g_bus, g_lun, idata,2, rdata,&rlen,&ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; return(ret); } /*end get_chan_auth*/ void show_chan_auth(char *tag, uchar *rec, int srec) { char pstr[40]; pstr[0] = 0; if (rec[1] & 0x01) strcat(pstr,"None "); if (rec[1] & 0x02) strcat(pstr,"MD2 "); if (rec[1] & 0x04) strcat(pstr,"MD5 "); if (rec[1] & 0x10) strcat(pstr,"Straight_Passwd "); if (rec[1] & 0x20) strcat(pstr,"OEM "); printf("Chan %d AuthTypes %c %s\n",rec[0],bdelim,pstr); if (do_hsc) /*only show this if extra output*/ printf("Chan %d Status %c %02x, OEM ID %02x%02x%02x OEM Aux %02x\n", rec[0],bdelim,rec[2],rec[4],rec[5],rec[6],rec[7]); } #define BMC 1 #define HSC 2 #ifdef MOVED /* moved to subs.c*/ #define N_MFG 41 struct { int val; char *pstr; } mfgs[N_MFG] = { }; char * get_iana_str(int mfg); #endif char * get_mfg_str(uchar *rgmfg, int *pmfg) { char *mfgstr = ""; int mfg; mfg = rgmfg[0] + (rgmfg[1] << 8) + (rgmfg[2] << 16); if (pmfg != NULL) *pmfg = mfg; /*vend_id*/ mfgstr = get_iana_str(mfg); return(mfgstr); } /* int get_system_info(uchar parm, char *pbuf, int *szbuf); *see subs.c*/ /* int set_system_info(uchar parm, uchar *pbuf, int *szbuf); *see subs.c*/ void show_devid_all(int dtype, uchar *devrec, int sdevrec) { uchar ipmi_maj = 0; uchar ipmi_min = 0; char *tag; int mfg, prod; char *mfgstr = ""; char *prodstr = ""; char prodoem[40]; char extraver[32]; int i, j, k, l, rv; ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; prod = devrec[9] + (devrec[10] << 8); mfgstr = get_mfg_str(&devrec[6],&mfg); vend_id = mfg; prod_id = prod; extraver[0] = 0; if (dtype == HSC) tag = "HSC"; else { tag = "BMC"; /* The product ids below only apply to BMCs */ switch(mfg) { case VENDOR_NSC: /*=0x000322*/ fmBMC = 1; if (dtype == BMC) tag="mBMC"; if (prod == 0x4311) prodstr = "(TIGPT1U)"; /*Intel*/ break; case VENDOR_SUN: /*=0x00002a*/ if (prod == 0x4701) prodstr = "(X4140)"; do_powerstate = 0; break; case VENDOR_TYAN: /*=0x0019fd*/ switch(prod) { /* show product names for some */ case 0x0b41: prodstr = "(M3289)"; break; case 0x0f98: prodstr = "(M3291)"; break; case 0x137d: prodstr = "(S4989)"; break; case 0x13ee: prodstr = "(S5102)"; break; case 0x14fc: prodstr = "(S5372)"; break; default: prodstr = ""; break; } break; case VENDOR_FUJITSU: /*=0x002880*/ if (prod >= 0x200) prodstr = "(iRMC S2)"; else prodstr = ""; break; case VENDOR_CISCO: /*=0x00168b, 5771.*/ if (prod == 0x0005) prodstr = "(UCS C200)"; else prodstr = ""; if (fipmilan) lan_ch_restrict = 1; /*fw bug, gets 0xC1 on ipmilan*/ break; case 0x003C0A: /*=15370, Giga-Byte*/ prodstr = ""; lan_ch_restrict = 1; /*fw bug, gets 0xC1*/ break; case VENDOR_INTEL: /*=0x000157*/ if (do_hsc && (dtype == BMC)) /*if HSC option, also show extra*/ sprintf(extraver," (Boot %x.%x PIA %x.%x)", /*BMC extra*/ devrec[11],devrec[12],devrec[13],devrec[14]); switch(prod) { /* show product names for some */ case 0x000C: prodstr = "(TSRLT2)"; /*SCB2*/ bChan = 7; break; case 0x001B: prodstr = "(TIGPR2U)"; /*SWV2*/ bChan = 7; break; case 0x0022: prodstr = "(TIGI2U)"; break; /*SJR2*/ case 0x0026: prodstr = "(Bridgeport)"; break; case 0x0028: prodstr = "(S5000PAL)"; break; /*Alcolu*/ case 0x0029: prodstr = "(S5000PSL)"; break; /*StarLake*/ case 0x002B: prodstr = "(S5000VSA)"; break; case 0x002D: prodstr = "(MFSYS25)"; break; /*ClearBay*/ case 0x003E: prodstr = "(S5520UR)"; /*CG2100 or NSN2U*/ do_me = 1; kcs_loops = URNLOOPS; bChan = 1; break; case 0x0040: prodstr = "(QSSC-S4R)"; /*Stoutland*/ do_me = 1; kcs_loops = URNLOOPS; bChan = 1; break; case 0x0100: prodstr = "(Tiger4)"; break; case 0x0103: prodstr = "(McCarran)"; /*BladeCenter*/ do_powerstate = 0; break; case 0x0800: prodstr = "(ZT5504)"; /*ZiaTech*/ do_powerstate = 0; break; case 0x0808: prodstr = "(MPCBL0001)"; /*ATCA Blade*/ do_powerstate = 0; break; case 0x0841: prodstr = "(MPCMM0001)"; /*ATCA CMM*/ do_powerstate = 0; break; case 0x0811: prodstr = "(TIGW1U)"; break; /*S5000PHB*/ case 0x4311: prodstr = "(NSI2U)"; /*SE7520JR23*/ if (dtype == BMC) tag="mBMC"; fmBMC = 1; break; default: prodstr = ""; break; } if (is_romley(mfg,prod)) { intel_romley_desc(mfg,prod,&prodstr); snprintf(prodoem,sizeof(prodoem),"(%s)",prodstr); prodstr = prodoem; do_me = 1; kcs_loops = URNLOOPS; do_hsc = 1; /*the HSC is embedded, so not the same*/ sprintf(extraver,".%d (Boot %x.%x)", /*BMC extra*/ (devrec[13] + (devrec[14] << 8)),devrec[11],devrec[12]); } if (is_grantley(mfg,prod)) { intel_grantley_desc(mfg,prod,&prodstr); } break; case VENDOR_KONTRON: /*=0x003A98=15000.*/ i = devrec[11] + (devrec[12] << 8); j = devrec[13] + (devrec[14] << 8); k = 0; l = 0; { /* get Kontron firmware version with OEM cmd */ int rlen; uchar idata[4]; uchar rdata[16]; uchar cc; rlen = sizeof(rdata); idata[0] = 0; idata[1] = 0; idata[2] = 1; rv = ipmi_cmdraw(0x2f, 0x2c, g_sa, g_bus, g_lun, idata,3,rdata,&rlen,&cc,fdebug); if (rv == 0 && cc == 0) { k = rdata[1]; l = rdata[2]; } } sprintf(extraver,".%02d.%02d (FW %x.%x)",i,j,k,l); switch(prod) { /* show product names for some */ case 0x1590: prodstr = "(KTC5520)"; break; default: prodstr = ""; break; } break; case VENDOR_PEPPERCON: /*=0x0028c5 Peppercon/Raritan */ if (prod == 0x0004) prodstr = "(AOC-IPMI20)"; /*SuperMicro*/ else if (prod == 0x0007) prodstr = "(RMM2)"; /*Intel RMM2*/ break; case VENDOR_HP: /*=0x00000B*/ switch(prod) { /* show product names for some */ case 0x2000: prodstr = "(Proliant ML/DL)"; break; /*DL380*/ case 0x2020: prodstr = "(Proliant BL)"; break; default: if ((prod & 0xff00) == 0x8300) prodstr = "(Proliant SL)"; else prodstr = ""; break; } do_powerstate = 0; /*HP does not support get_power_state cmd*/ if (!fipmilan) lan_ch_restrict = 1; /*fw bug, gets 0xcc locally*/ break; case VENDOR_DELL: /*=0x0002A2*/ switch(prod) { /* show product names for some */ case 0x0100: prodstr = "(PE R610)"; break; default: prodstr = ""; break; } break; case VENDOR_MAGNUM: /* =5593. used by SuperMicro*/ switch(prod) { /* show product names for some */ case 6: prodstr = "(X8DTL)"; break; default: prodstr = ""; break; } break; case VENDOR_SUPERMICRO: /* =10876. used by SuperMicro*/ case VENDOR_SUPERMICROX: /* =47488. used by Winbond/SuperMicro*/ switch(prod) { /* decode some SuperMicro product ids */ case 4: prodstr = "(X7DBR)"; break; case 6: prodstr = "(X8DTL)"; break; case 1037: prodstr = "(X8SIE)"; break; case 1541: prodstr = "(X8SIL)"; break; case 1547: prodstr = "(X8SIA)"; break; /*0x060b*/ case 1549: prodstr = "(X8DTU)"; break; case 1551: prodstr = "(X8DTN)"; break; case 1562: prodstr = "(X8SIU-F)"; break; /*0x061a*/ case 1572: prodstr = "(X9SCM)"; break; /*or X9SCL*/ case 1576: prodstr = "(X9DRi)"; break; case 1585: prodstr = "(X9SCA)"; break; case 1603: prodstr = "(X9SPU)"; break; /*0x0643*/ case 1636: prodstr = "(X9DRH)"; break; /*0x0664*/ case 1643: prodstr = "(X9SRL)"; break; /*0x066b*/ case 1797: prodstr = "(X9DR7)"; break; /*0x0705*/ case 2097: prodstr = "(X10DRL)"; /*0x0831*/ do_powerstate = 0; break; case 2137: prodstr = "(X10DRH)"; break; /*0x0859*/ case 2203: prodstr = "(X11SSW-F)"; break; /*0x089b*/ case 2327: prodstr = "(X11DPi)"; break; /*0x0917*/ case 4520: prodstr = "(H8DGU)"; break; case 43025: prodstr = "(H8DGU-F)"; break; case 43707: prodstr = "(X8DTH)"; break; case 48145: prodstr = "(H8DG6)"; break; default: prodstr = ""; break; } if (!fipmilan) lan_ch_restrict = 1; /*fw bug, gets 0xd4 locally*/ break; case VENDOR_QUANTA: /*=7244.*/ switch(prod) { /* show product names for some */ case 21401: prodstr = "(S99Q)"; break; default: prodstr = ""; break; } break; case VENDOR_LENOVO: case VENDOR_LENOVO2: if (prod == 0x143) prodstr = "(x3650 M4)"; else prodstr = ""; do_powerstate = 0; break; case VENDOR_IBM: /*=0x0002*/ switch(prod) { /* show product names for some */ case 0x000e: prodstr = "(x3755)"; break; case 0x0011: prodstr = "(x3650)"; break; case 0x00dc: prodstr = "(x3650 M2)"; break; /*M2,M3*/ case 0x00fa: prodstr = "(x3850 X5)"; break; case 0x8848: prodstr = "(eServer 360S)"; break; default: prodstr = ""; break; } break; default: prodstr = ""; break; } /*end switch(prod)*/ if (prodstr[0] == '\0') prodstr = getdmiprod(); if (kcs_loops != 0) set_max_kcs_loops(kcs_loops); } /*end-else BMC*/ printf("%s manufacturer %c %06x (%s)%c product %c %04x %s\n", tag, bdelim,mfg,mfgstr,bcomma,bdelim,prod,prodstr); { /* BMC version */ printf("%s version %c %x.%02x%s%c IPMI v%d.%d\n", tag,bdelim, devrec[2],devrec[3],extraver,bcomma,ipmi_maj,ipmi_min); } /* could show product rev, if available (sdevrec > 14) */ return; } int GetPowerOnHours(unsigned int *val) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; uchar cc; int rc = -1; int i; unsigned int hrs; *val = 0; if (fmBMC) return(rc); 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; } *val = hrs; } return(rc); } char *decode_selftest(int stat) { char *s; uchar b; if (stat == 0x0055) s = "(OK)"; else { s = "(Error)"; if ((stat & 0x00ff) == 0x0057) { b = ((stat & 0xff00) >> 8); if (b & 0x80) s = "(No SEL Access)"; if (b & 0x40) s = "(No SDR Access)"; if (b & 0x20) s = "(No FRU Access)"; if (b & 0x10) s = "(IPMB Error)"; if (b & 0x08) s = "(SDR Empty)"; if (b & 0x02) s = "(BootCode Corrupt)"; if (b & 0x01) s = "(OpCode Corrupt)"; } } return(s); } #ifdef METACOMMAND int i_health(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int ret = 0; int c; uchar selfbuf[16]; uchar devrec[30]; char biosver[80]; uchar cc; int selfstatus; uchar pwr_state; char selfstr[36]; char *s; char *s1; int i, sresp; uint n; int rlen, len; uchar idata[4]; uchar rdata[16]; printf("%s ver %s\n", progname,progver); while ( (c = getopt( argc, argv,"cfghiln:o:p:q:sT:V:J:YEF:P:N:R:U:Z:x?")) != EOF ) switch(c) { case 'c': fcanonical = 1; bdelim = BDELIM; break; /* canonical output */ case 'f': do_frusdr = 1; break; /* check the FRUSDR too */ case 'g': do_guid = 1; break; /* get the System GUID also */ case 'h': do_hsc = 1; break; /* check the HSC too */ case 'i': do_systeminfo = 1; break; /* get system info too */ case 'l': do_lanstats = 1; break; /* get the LAN stats too */ case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'n': set_name = 1; /* set the system name*/ pname = optarg; break; case 'o': set_os = 1; /* set the Operating System*/ pos = optarg; break; case 'q': set_os2 = 1; /* set the Operating System*/ pos2 = optarg; break; case 'p': set_restore = 1; /* set the restore policy */ restore_policy = atob(optarg); if (restore_policy > 2) restore_policy = 1; break; case 's': do_session = 1; break; /* get session info too */ case 'x': fdebug = 1; break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: printf("Usage: %s [-cfghilnopsx -N node -U user -P/-R pswd -EFTVY]\n", progname); printf(" where -x show eXtra debug messages\n"); printf(" -c canonical output\n"); printf(" -f get the FRUSDR version also\n"); printf(" -g get the System GUID also\n"); printf(" -h check the HotSwap Controller also\n"); printf(" -i get System Info also: Name and OS\n"); printf(" -l get the IPMI LAN statistics also\n"); printf(" -n set System Name to this string \n"); printf(" -o set Operating System to this string\n"); printf(" -p1 set restore policy: 0=off, 1=last, 2=on\n"); printf(" -s get the IPMI Session info also\n"); print_lan_opt_usage(0); ret = ERR_USAGE; goto health_end; } fipmilan = is_remote(); if (fipmilan && set_restore) parse_lan_options('V',"4",0); /*if set, request admin priv*/ ret = ipmi_getdeviceid(devrec,16,fdebug); if (ret != 0) { goto health_end; } else { show_devid_all(BMC,devrec,16); } if (!fipmilan) { /*get local BIOS version*/ biosver[0] = 0; ret = get_BiosVersion(biosver); if (ret == 0) printf("BIOS Version %c %s\n",bdelim,biosver); } if (do_me) { /* ME version for Intel S5500 motherboards */ rlen = sizeof(rdata); ret = ipmi_cmdraw((GET_DEVICE_ID & 0xff), NETFN_APP,ME_SA,ME_BUS,0x00, idata,0,rdata,&rlen,&cc,fdebug); if (ret == 0 && cc != 0) ret = cc; if (ret == 0) { uchar m,n; m = (rdata[3] & 0xf0) >> 4; n = (rdata[3] & 0x0f); printf("ME Firmware Ver %c %02x.%02x.%02x.%02x%02x\n",bdelim, rdata[2],m,n,rdata[12],rdata[13]); /* If rdata[2] has 0x80 bit on, ME is in update/recovery mode. That can be cleared by removing input power. */ } else if (fdebug) printf("GetDeviceID(ME) error ret = %d\n",ret); } if (do_hsc) { if (fmBMC) printf("No HSC present\n"); else { /* Get HSC status */ if (is_romley(vend_id, prod_id)) { uchar maj, min; ret = get_hsbp_version_intel(&maj, &min); if (fdebug) printf("get_hsbp_version_intel ret = %d\n",ret); if (ret == 0) printf("HSC version %c %d.%02d\n", bdelim,maj,min); } else { ret = get_hsc_devid(&devrec[0],sizeof(devrec)); if (fdebug) printf("get_hsc_devid ret = %d\n",ret); if (ret == 0) /* only if HSC is detected */ show_devid_all(HSC,devrec,14); } } } i = get_driver_type(); printf("IPMI driver type %c %d (%s)\n",bdelim,i,show_driver_type(i)); if (do_powerstate) { /* Some BMCs dont support get_power_state*/ ret = get_power_state(selfbuf,4); if (ret != 0) { printf("ipmi_getpowerstate error, ret = %d\n",ret); pwr_state = 0; } else { pwr_state = selfbuf[0] & 0x7f; printf("Power State %c %02x (%s)\n", bdelim,pwr_state,pwr_string(pwr_state)); } } ret = get_selftest_status(&selfbuf[0],sizeof(selfbuf)); if (ret != 0) { printf("get_selftest_status error, ret = %x\n",ret); goto health_end; } else { selfstatus = selfbuf[0] + (selfbuf[1] << 8); s = decode_selftest(selfstatus); if (fmBMC) { sprintf(selfstr,"%s",s); } else { ret = get_last_selftest(&selfbuf[0],sizeof(selfbuf)); if (fdebug) printf("get_last_selftest ret = %x, %02x%02x\n", ret, selfbuf[1],selfbuf[0]); if (ret == 0 && (selfbuf[0] != 0xFF)) { sprintf(selfstr,"%s, last = %02x%02x",s,selfbuf[1],selfbuf[0]); } else sprintf(selfstr,"%s",s); ret = 0; /*ignore any errors with get_last_selftest*/ } printf("Selftest status %c %04x %s\n",bdelim,selfstatus,selfstr); } ret = oem_get_health(&selfstr[0],sizeof(selfstr)); if (ret == 0) { printf("%s\n",selfstr); } rlen = 4; ret = get_chassis_status(selfbuf,&rlen); if (ret != 0) { printf("Cannot do get_chassis_status, ret = %d\n",ret); goto health_end; } else { show_chs_status(selfbuf,rlen); } if (vend_id == VENDOR_INTEL) { int pwr_delay = 0; ret = get_power_restore_delay_intel(&pwr_delay); if (fdebug) printf("get_power_restore_delay_intel ret = %d\n",ret); if (ret == 0) { printf("PowerRestoreDelay %c %d seconds\n",bdelim,pwr_delay); } else ret = 0; } if (do_guid) { sresp = sizeof(devrec); ret = ipmi_cmd(GET_SYSTEM_GUID,NULL,0,devrec,&sresp,&cc,fdebug); if (ret != 0) { if (!is_remote()) { /* get UUID from SMBIOS */ cc = 0; sresp = 16; ret = get_SystemGuid(devrec); } else { cc = 0; sresp = sizeof(devrec); ret = get_device_guid(devrec,&sresp); } } if (fdebug) printf("system_guid: ret = %d, cc = %x\n",ret,cc); if (ret == 0 && cc == 0) { printf("System GUID %c ",bdelim); for (i=0; i<16; i++) { if ((i == 4) || (i == 6) || (i == 8) || (i == 10)) s = "-"; else s = ""; printf("%s%02x",s,devrec[i]); } printf("\n"); } } if (bChan != 7) /* do not get first lan chan if set above */ ret = get_lan_channel(1,&bChan); if (fmBMC == 0) { ret = GetPowerOnHours(&n); if (ret == 0) printf("Power On Hours %c %d hours (%d days)\n",bdelim,n,(n/24)); if (ret == 0xC1) ret = 0; /* not supporting poweron hours is ok. */ printf("BMC LAN Channels %c ",bdelim); for (i = 1; i<= 16; ) { c = get_lan_channel(i,&cc); if (c != 0) break; printf("%d ",cc); i = cc+1; } printf("\n"); if (lan_ch_restrict) ; /*skip if vendor fw bug*/ else { ret = get_chan_auth(bChan,&devrec[0],sizeof(devrec)); if (ret == 0) show_chan_auth("Channel Auth Cap",devrec,8); else printf("get_chan_auth error: ret = %x\n",ret); } } if (do_systeminfo) { char infostr[64]; len = sizeof(infostr); ret = get_system_info(1,infostr,&len); /*Firmware Version*/ len = sizeof(infostr); ret = get_system_info(2,infostr,&len); if (ret == 0) { printf("System Name %c %s\n",bdelim,infostr); len = sizeof(infostr); ret = get_system_info(3,infostr,&len); if (ret == 0) printf("Pri Operating System %c %s\n",bdelim,infostr); len = sizeof(infostr); ret = get_system_info(4,infostr,&len); if (ret == 0) printf("Sec Operating System %c %s\n",bdelim,infostr); } else { if (ret == 0xC1) /*only supported on later IPMI 2.0 firmware */ printf("GetSystemInfo not supported on this platform\n"); } } if (do_frusdr) { ret = get_frusdr_version((char *)&devrec[0],sizeof(devrec)); if (ret == 0) printf("FRU/SDR Version %c %s\n",bdelim,devrec); else printf("FRU/SDR Version %c error %d\n",bdelim,ret); } if (do_lanstats) { ret = get_lan_stats(bChan); } if (do_session) { i = get_session_info_all(); if (i != 0) printf("get_session_info error %d, %s\n",i,decode_rv(i)); } #ifdef PING_OK { char *node; /* Currently some problems with this: * works first time, but locks up BMC LAN on subsequent attempts. */ node = get_nodename(); ret = ping_node(node); printf("ping_node(%s): ret = %d\n",node,ret); } #endif if (set_name) { len = (int)strlen(pname); ret = set_system_info(2,pname,len); printf("Set System Name to '%s', ret = %d\n",pname,ret); if (ret == 0xC1) /*only supported on later IPMI 2.0 firmware */ printf("SetSystemInfo not supported on this platform\n"); } if (set_os) { len = (int)strlen(pos); ret = set_system_info(3,pos,len); printf("Set Pri Operating System to '%s', ret = %d\n",pos,ret); if (ret == 0xC1) /*only supported on later IPMI 2.0 firmware */ printf("SetSystemInfo not supported on this platform\n"); } if (set_os2) { len = (int)strlen(pos2); ret = set_system_info(4,pos2,len); printf("Set Sec Operating System to '%s', ret = %d\n",pos2,ret); if (ret == 0xC1) /*only supported on later IPMI 2.0 firmware */ printf("SetSystemInfo not supported on this platform\n"); } if (set_restore) { idata[0] = restore_policy; /* 1=last_state, 2=turn_on, 0=stay_off*/ rlen = sizeof(rdata); ret = ipmi_cmdraw(0x06 , NETFN_CHAS, g_sa, g_bus, g_lun, idata,1,rdata,&rlen,&cc,fdebug); if (ret == 0 && cc != 0) ret = cc; printf("set_restore_policy(%x): ret = %d\n",restore_policy,ret); } health_end: ipmi_close_(); // show_outcome(progname,ret); return (ret); } /* end main()*/ /* end bmchealth.c */ ipmiutil-3.1.5/util/subs.c0000644000076400007640000005430013566765324015555 0ustar mgportalloggers/* * subs.c * * Some common helper subroutines * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2010 Kontron America, Inc. * * 08/18/11 Andy Cress - created to consolidate subroutines */ /*M* Copyright (c) 2010 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 Kontron 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 #include #include #include #include #ifdef WIN32 #include // #if !defined(LONG_MAX) // # if __WORDSIZE == 64 // # define LONG_MAX 9223372036854775807L // # else // # define LONG_MAX 2147483647L // # endif // # define LONG_MIN (-LONG_MAX - 1L) // #endif #else /* Linux */ #include #include #include #endif #include "ipmicmd.h" extern char fdebug; /*ipmicmd.c*/ extern char fdbglog; /*ipmilanplus.c*/ extern int verbose; /*ipmilanplus.c*/ extern FILE *fpdbg; /*ipmicmd.c*/ extern FILE *fplog; /*ipmicmd.c */ extern char log_name[60]; /*log_name global, from ipmicmd.c*/ static int loglevel = LOG_WARN; #ifdef WIN32 #define SELMSG_ID 0x40000101 /* showselmsg.dll EventID 257. = 0x101 */ static HANDLE hLog = NULL; #endif /* decode_rv, decode_cc are in ipmicmd.c */ /* strlen_ wrapper for size_t/int warnings*/ int strlen_(const char *s) { return((int)strlen(s)); } /* Need our own copy of strdup(), named strdup_(), since Windows does * not have the same subroutine. */ char * strdup_(const char *instr) { char *newstr = NULL; if (instr != NULL) { newstr = malloc(strlen_(instr)+1); if (newstr != NULL) strcpy(newstr,instr); } return (newstr); } #ifdef WIN32 int strncasecmp(const char *s1, const char *s2, int n) { int i, val; char c1, c2; if (s1 == NULL || s2 == NULL) return (-1); val = 0; for (i = 0; i < n; i++) { c1 = s1[i] & 0x5f; c2 = s2[i] & 0x5f; if (c1 < c2) { val = -1; break; } if (c1 > c2) { val = 1; break; } } return(val); } #endif /* case insensitive string compare */ int str_icmp(char *s1, char *s2) { int n1, n2, val; if (s1 == NULL || s2 == NULL) return (-1); n1 = strlen_(s1); n2 = strlen_(s2); if (n1 != n2) return(-1); val = strncasecmp(s1,s2,n1); return(val); } void set_loglevel(int level) { loglevel = level; } void lprintf(int level, const char * format, ...) { va_list vptr; static char logtmp[LOG_MSG_LENGTH]; FILE *fp = stderr; if (!verbose && (level > loglevel)) return; if (level > LOG_WARN) fp = stdout; /*NOTICE,INFO*/ if (fdbglog && (fplog != NULL)) fp = fplog; #ifdef WIN32 va_start(vptr, format); vfprintf(fp, format, vptr); va_end(vptr); fprintf(fp,"\r\n"); #else va_start(vptr, format); vsnprintf(logtmp, LOG_MSG_LENGTH, format, vptr); va_end(vptr); fprintf(fp, "%s\r\n", logtmp); #endif return; } void lperror(int level, const char * format, ...) { va_list vptr; FILE *fp; if (level > loglevel) return; fp = stderr; if (fdbglog && verbose > 1) { if (fplog != NULL) fp = fplog; } va_start(vptr, format); vfprintf(fp, format, vptr); va_end(vptr); fprintf(fp,"\r\n"); return; } #ifdef LANHELPER uint32_t buf2long(uint8_t * buf); uint16_t buf2short(uint8_t * buf); void printbuf(const uint8_t * buf, int len, const char * desc); const char * buf2str(uint8_t * buf, int len); const char * oemval2str(uint16_t oem, uint16_t val, const struct oemvalstr *vs); const char * val2str(uint16_t val, const struct valstr *vs); uint16_t str2val(const char *str, const struct valstr *vs); #else ulong buf2long(uchar * buf) { return (ulong)(buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]); } ushort buf2short(uchar * buf) { return (ushort)(buf[1] << 8 | buf[0]); } void printbuf(const uchar * buf, int len, const char * desc) { int i; FILE *fp = stderr; if (len <= 0) return; if (verbose < 1) return; if (fdbglog && (fplog != NULL)) fp = fplog; fprintf(fp, "%s (%d bytes)\r\n", desc, len); for (i=0; i sizeof(str)) return NULL; memset(str, 0, sizeof(str)); for (i=0; i y)? x : y) == 0) return vs[i].val; } return vs[i].val; } #endif void dump_buf(char *tag, uchar *pbuf, int sz, char fshowascii) { uchar line[17]; uchar a; int i, j; char *stag; FILE *fpdbg1; if (fpdbg != NULL) fpdbg1 = fpdbg; else fpdbg1 = stdout; if (tag == NULL) stag = "dump_buf"; /*safety valve*/ else stag = tag; fprintf(fpdbg1,"%s (len=%d): ", stag,sz); line[0] = 0; line[16] = 0; j = 0; if (sz < 0) { fprintf(fpdbg1,"\n"); return; } /*safety valve*/ for (i = 0; i < sz; i++) { if (i % 16 == 0) { line[j] = 0; j = 0; fprintf(fpdbg1,"%s\n %04x: ",line,i); } if (fshowascii) { a = pbuf[i]; if (a < 0x20 || a > 0x7f) a = '.'; line[j++] = a; } fprintf(fpdbg1,"%02x ",pbuf[i]); } if (fshowascii) { if ((j > 0) && (j < 16)) { /* space over the remaining number of hex bytes */ for (i = 0; i < (16-j); i++) fprintf(fpdbg1," "); } else j = 16; line[j] = 0; } fprintf(fpdbg1,"%s\n",line); return; } void close_log(void) { if ((fplog != NULL) && (fplog != stderr) && (fplog != stdout)) { fclose(fplog); fplog = NULL; } } FILE *open_log(char *mname) { FILE *fp = NULL; char *pname; int len; /* log_name is global, for reuse */ if (log_name[0] == 0) { if (mname == NULL) { /*make a default name*/ pname = "ipmiutil"; #ifdef WIN32 sprintf(log_name,"%s.log",pname); #elif defined(DOS) sprintf(log_name,"%s.log",pname); #else /*LINUX, SOLARIS, BSD */ sprintf(log_name,"/var/log/%s.log",pname); #endif } else { /*use mname arg*/ len = strlen_(mname); if (len >= sizeof(log_name)) len = sizeof(log_name) - 1; strncpy(log_name, mname, len); } } close_log(); if (log_name[0] != 0) fp = fopen( log_name, "a+" ); if (fp == NULL) { fp = stdout; /*was stderr*/ fprintf(fp,"cannot open log: %s\n",log_name); } fplog = fp; return fp; } void flush_log(void) { if (fplog != NULL) fflush(fplog); } void print_log( char *pattn, ... ) { va_list arglist; if (fplog == NULL) fplog = open_log(NULL); /* if error, open_log sets fplog = stdout */ va_start( arglist, pattn ); vfprintf( fplog, pattn, arglist ); va_end( arglist ); } /* * logmsg * This does an open/close if no log is already open, but does not set fplog. */ void logmsg( char *pname, char *pattn, ... ) { va_list arglist; FILE *fp = NULL; int opened = 0; if (fplog == NULL) { /*no log alread open, open temp fp*/ fp = open_log(pname); if (fp == NULL) return; opened = 1; } else fp = fplog; va_start( arglist, pattn ); vfprintf( fp, pattn, arglist ); va_end( arglist ); if ((opened) && (fp != stderr)) /*opened temp fp, so close it*/ { fclose(fp); } } void dump_log(FILE *fp, char *tag, uchar *pbuf, int sz, char fshowascii) { FILE *fpsav; fpsav = fpdbg; if (fplog != NULL) fpdbg = fplog; if (fp != NULL) fpdbg = fp; dump_buf(tag, pbuf, sz, fshowascii); /*uses fpdbg*/ fflush(fpdbg); fpdbg = fpsav; } extern int lasterr; /*defined in ipmilan.c */ extern void show_LastError(char *tag, int err); /*ipmilan.c */ #ifdef WIN32 /* Windows stdlib.h: extern int * __cdecl _errno(void); */ int get_errno(void) { return(errno); } #else extern int errno; /* Linux= N_MFG) mfgstr = mfgs[0].pstr; return(mfgstr); } /* * str2uchar * Convert string into unsigned char and check for overflows * @str: (input) array of chars to parse from * @uchr_ptr: (output) pointer to address where uint8_t will be stored * returns 0 if successful, or -1,-2,-3 if error */ int str2uchar(char *str, uchar *uchr_ptr) { ulong lval = 0; char *end_ptr = NULL; if (str == NULL || uchr_ptr == NULL) return -1; /*NULL pointer arg*/ *uchr_ptr = 0; /*seed with default result*/ errno = 0; /* handle use of 08, 09 to avoid octal overflow */ if (strncmp(str,"08",2) == 0) lval = 8; else if (strncmp(str,"09",2) == 0) lval = 9; else { /*else do strtoul*/ lval = strtoul(str, &end_ptr, 0); if ((end_ptr == NULL) || *end_ptr != '\0' || errno != 0) return -2; /* invalid input given by user/overflow occurred */ if (lval > 0xFF || lval == LONG_MIN || lval == LONG_MAX) return -3; /* Argument is too big to fit unsigned char */ } *uchr_ptr = (uchar)lval; return 0; } /* atob is like atoi, but using str2uchar */ uchar atob(char *str_in) { uchar b = 0; int rv; rv = str2uchar(str_in,&b); /* if error, show error, but use default. */ switch (rv) { case -1: printf("atob error: input pointer is NULL\n"); break; case -2: printf("atob error: string-to-number conversion overflow\n"); break; case -3: printf("atob error: numeric argument is too big for one byte\n"); break; default: break; } return(b); } void atoip(uchar *array,char *instr) { int i,j,n; char *pi; char tmpstr[16]; /* converts ASCII input string into binary IP Address (array) */ if (array == NULL || instr == NULL) { if (fdebug) printf("atoip(%p,%p) NULL pointer error\n",array,instr); return; } j = 0; n = strlen_(instr); n++; /*include the null char*/ if (n > sizeof(tmpstr)) n = sizeof(tmpstr); memcpy(tmpstr,instr,n); pi = tmpstr; for (i = 0; i < n; i++) { if (tmpstr[i] == '.') { tmpstr[i] = 0; array[j++] = atob(pi); pi = &tmpstr[i+1]; } else if (tmpstr[i] == 0) { array[j++] = atob(pi); } } if (fdebug) printf("atoip: %d %d %d %d\n", array[0],array[1],array[2],array[3]); } /*end atoip()*/ /* * htoi * Almost all of the utilities use this subroutine * Input: a 2 character string of hex digits. * Output: a hex byte. */ uchar htoi(char *inhex) { // char rghex[16] = "0123456789ABCDEF"; uchar val; uchar c; if (inhex[1] == 0) { /* short string, one char */ c = inhex[0] & 0x5f; /* force cap */ if (c > '9') c += 9; /* c >= 'A' */ val = (c & 0x0f); } else { c = inhex[0] & 0x5f; /* force cap */ if (c > '9') c += 9; /* c >= 'A' */ val = (c & 0x0f) << 4; c = inhex[1] & 0x5f; /* force cap */ if (c > '9') c += 9; /* c >= 'A' */ val += (c & 0x0f); } return(val); } void os_usleep(int s, int u) { #ifdef WIN32 if (s == 0) { int i; if (u >= 1000) Sleep(u/1000); else for (i=0; i (uchar)2) return(0); /*encoding max is 2*/ if (vendor == 0) get_mfgid(&vend, NULL); else vend = vendor; if (vend == VENDOR_INTEL) rv = 0; if (vend == VENDOR_SUPERMICRO) rv = 0; return(rv); } int get_device_guid(uchar *pbuf, int *szbuf) { int rv = -1; //uchar idata[8]; uchar rdata[32]; int rlen, len; uchar cc; ushort cmdw; len = *szbuf; *szbuf = 0; cmdw = 0x08 | (NETFN_APP << 8); rv = ipmi_cmd_mc(cmdw, NULL,0,rdata,&rlen,&cc,fdebug); if (rv == 0 && cc != 0) rv = cc; if (rv == 0) { if (rlen > len) rlen = len; memcpy(pbuf,rdata,rlen); *szbuf = rlen; } return(rv); } int get_sysinfo(uchar parm, uchar set, uchar block, uchar *pbuf, int *szbuf) { uchar idata[8]; uchar rdata[32]; int rlen, j, len; int rv = -1; uchar cc; ushort cmdw; if (pbuf == NULL || szbuf == NULL) return(rv); len = 0; idata[0] = 0; idata[1] = parm; idata[2] = set; idata[3] = block; rlen = sizeof(rdata); cmdw = CMD_GET_SYSTEM_INFO | (NETFN_APP << 8); rv = ipmi_cmd_mc(cmdw, idata,4,rdata,&rlen,&cc,fdebug); if (rv == 0 && cc != 0) rv = cc; if (rv == 0) { j = 2; if (set == 0) { /*NEW_FMT: first set includes type, len */ if (sysinfo_has_len(rdata[2],0)) { /*but len not used if Intel*/ j = 4; len = rdata[3]; } } rdata[rlen] = 0; /*stringify for debug below*/ rlen -= j; if (fdebug) printf("get_sysinfo(%d,%d) j=%d len=%d %s\n", parm,set,j,rlen,&rdata[j]); if (rlen > *szbuf) rlen = *szbuf; memcpy(pbuf,&rdata[j],rlen); *szbuf = rlen; } return(rv); } int set_system_info(uchar parm, char *pbuf, int szbuf) { uchar idata[32]; uchar rdata[8]; int rlen, ilen, i, j, n; int rv = -1; uchar cc, set; ushort cmdw; if (pbuf == NULL) return(rv); if (szbuf > SYS_INFO_MAX) szbuf = SYS_INFO_MAX; n = 0; set = 0; while ((n < szbuf) || (n == 0)) { ilen = 16; j = 2; memset(idata,0,sizeof(idata)); idata[0] = parm; idata[1] = set; if (set == 0) { /*NEW_FMT: first set includes type, len */ if (sysinfo_has_len(0,0)) { /*but len not used if Intel*/ j = 4; idata[2] = 0; /*type = ASCII+Latin1*/ idata[3] = szbuf; /*overall length*/ } } i = ilen; if (i > (szbuf - n)) i = (szbuf - n); memcpy(&idata[j],&pbuf[n],i); rlen = sizeof(rdata); cmdw = CMD_SET_SYSTEM_INFO | (NETFN_APP << 8); rv = ipmi_cmd_mc(cmdw, idata,(ilen+j),rdata,&rlen,&cc,fdebug); if (rv == 0 && cc != 0) rv = cc; if (fdebug) printf("set_system_info(%d,%d) rv=%d j=%d ilen=%d %s\n", parm,set,rv,j,ilen,&pbuf[n]); if (rv != 0) break; else { n += ilen; set++; } } return(rv); } int get_system_info(uchar parm, char *pbuf, int *szbuf) { int rv = -1; int i, off, len, szchunk; off = 0; len = *szbuf; /* SYS_INFO_MAX = 64 (4 * 16) */ for (i = 0; i < 4; i++) { szchunk = 16; if ((off + szchunk) > *szbuf) break; rv = get_sysinfo(parm,i,0,&pbuf[off],&szchunk); if (rv != 0) break; off += szchunk; if (off >= len) break; } if (off < *szbuf) *szbuf = off; return(rv); } int ipmi_reserved_user(int vend, int userid) { int ret = 0; if (userid == 1) { switch(vend) { case VENDOR_INTEL: ret = 0; break; case VENDOR_KONTRON: ret = 1; break; case VENDOR_SUPERMICRO: ret = 1; break; case VENDOR_SUPERMICROX: ret = 1; break; default: ret = 0; break; } } return(ret); } #define NSEV 4 static char *sev_str[NSEV] = { /*0*/ "INF", /*1*/ "MIN", /*2*/ "MAJ", /*3*/ "CRT" }; uchar find_msg_sev(char *msg) { int i; char *p; uchar sev = SEV_INFO; if (msg == NULL) return(sev); for (i = 0; i < NSEV; i++) { p = strstr(msg,sev_str[i]); if (p != NULL) { sev = (uchar)i; break; } } return(sev); } int OpenSyslog(char *tag) { int ret = -1; if (tag == NULL) tag = "ipmiutil"; #ifdef WIN32 /* Requires showselmsg.dll and this Registry entry: HKLM/SYSTEM/CurrentControlSet/Services/EventLog/Application/showsel EventMessageFile REG_EXPAND_SZ "%SystemRoot%\system32\showselmsg.dll" TypesSupported REG_DWORD 0x000000007 */ hLog = RegisterEventSource(NULL, "showsel"); if (hLog == (void *)ERROR_INVALID_HANDLE) { hLog = NULL; } if (hLog == NULL) printf("RegisterEventSource error, %lx\n", GetLastError()); else ret = 0; /*success*/ #elif defined(DOS) ret = LAN_ERR_NOTSUPPORT; #else // Open syslog openlog( tag, LOG_CONS, LOG_KERN); ret = 0; /* success if here */ #endif return(ret); } void CloseSyslog(void) { #ifdef WIN32 DeregisterEventSource(hLog); #elif defined(DOS) ; #else // Close syslog closelog(); #endif } void WriteSyslog(char *msgbuf) { uchar sev; #ifdef WIN32 BOOL status; char *rgstrings[2] = {NULL, NULL}; WORD level; rgstrings[0] = msgbuf; /*decoded SEL entry*/ sev = find_msg_sev(msgbuf); switch(sev) { case SEV_MIN: level = EVENTLOG_WARNING_TYPE; break; case SEV_MAJ: level = EVENTLOG_ERROR_TYPE; break; case SEV_CRIT: level = EVENTLOG_ERROR_TYPE; break; case SEV_INFO: default: level = EVENTLOG_INFORMATION_TYPE; break; } if (hLog != NULL) { status = ReportEvent(hLog,EVENTLOG_INFORMATION_TYPE, 0, SELMSG_ID, NULL, 1,0, rgstrings,NULL); /* showsel eventid = 0x101. */ if (fdebug || (status == 0)) { /*error or debug*/ printf("ReportEvent status=%d, %lx\n", status,GetLastError()); } } #elif defined(DOS) ; #else int level; sev = find_msg_sev(msgbuf); switch(sev) { case SEV_MIN: level = LOG_WARN; break; case SEV_MAJ: level = LOG_ERR; break; case SEV_CRIT: level = LOG_CRIT; break; case SEV_INFO: default: level = LOG_INFO; break; } syslog(level,"%s",msgbuf); #endif } /*end WriteSyslog*/ int write_syslog(char *msg) { /* not used in showsel, but used by getevent, hwreset */ int rv; rv = OpenSyslog("ipmiutil"); if (rv == 0) { WriteSyslog(msg); CloseSyslog(); } return(rv); } /* end subs.c */ ipmiutil-3.1.5/util/ipmi_sample_evt.c0000644000076400007640000003317413566765324017764 0ustar mgportalloggers/* * ipmi_sample_evt.c * * A sample IPMI utility to get IPMI SEL events. * * 09/10/12 Andy Cress - created */ /*M* Copyright (c) 2012, 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 Kontron America, Inc. 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*/ #ifdef WIN32 #include #include #include #include "getopt.h" #else #include #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include #include "ipmicmd.h" extern int decode_sel_entry(uchar *evt, char *obuf, int sz); /*see ievents.c*/ extern void set_sel_opts(int sensdesc, int canon, void *sdrs, char dbg, char u); extern char *get_sensor_type_desc(uchar stype); /*see ievents.c*/ extern int get_sdr_cache(uchar **pret); /*see isensor.c*/ extern void free_sdr_cache(uchar *pret); /*see isensor.c*/ extern int write_syslog(char *msg); /*see isel.c*/ /* * Global variables */ static char * progname = "ipmi_sample_evt"; static char * progver = "1.0"; static char fdebug = 0; static char fset_mc = 0; static char fipmilan = 0; static char finit_ok = 0; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static char *mytag = NULL; static char *sdrfile = NULL; static ushort sel_recid = 0; static uint sel_time = 0; static int wait_interval = 3; /* 3 seconds between calls */ static uchar *sdrs = NULL; static int drvtype = 0; /* driver_type from ipmicmd.h: 3=MV_OpenIPMI */ FILE *fdout = NULL; #define LAST_REC 0xFFFF #ifdef WIN32 static char idxfile[80] = "c:\\ipmievt.idx"; static char outfile[80] = "c:\\ipmievt.log"; #else static char idxfile[80] = "/var/lib/ipmiutil/ipmievt.idx"; static char outfile[80] = "/var/log/ipmievt.log"; #endif /* These routines were copied from igetevent.c * msgout, getevent_sel, syncevent_sel, show_event, ievt_cleanup */ static void ievt_cleanup(void); static void msgout(char *pattn, ...) { va_list arglist; if (fdout == NULL) return; va_start( arglist, pattn ); vfprintf( fdout, pattn, arglist ); va_end( arglist ); fflush( fdout ); } #if defined(WIN32) | defined(DOS) /* no daemon code */ static void ievt_siginit(void) { return; } #else /* Linux daemon code */ #include static void ievt_sighnd(int sig) { ievt_cleanup(); exit(EXIT_SUCCESS); } static void ievt_siginit(void); static void ievt_siginit(void) { struct sigaction sact; /* handle signals for cleanup */ sact.sa_handler = ievt_sighnd; sact.sa_flags = 0; sigemptyset(&sact.sa_mask); sigaction(SIGINT, &sact, NULL); sigaction(SIGQUIT, &sact, NULL); sigaction(SIGTERM, &sact, NULL); } #endif static int get_sel_entry(ushort recid, ushort *nextid, uchar *rec) { uchar ibuf[6]; uchar rbuf[32]; int rlen; ushort xid, id = 0; uchar cc; int rv; ibuf[0] = 0; ibuf[1] = 0; ibuf[2] = (recid & 0x00ff); ibuf[3] = (recid & 0xff00) >> 8; ibuf[4] = 0; ibuf[5] = 0xFF; /*get entire record*/ rlen = sizeof(rbuf); rv = ipmi_cmd(GET_SEL_ENTRY, ibuf, 6, rbuf, &rlen, &cc, fdebug); if (rv == 0) { if (cc != 0) rv = cc; else { /*success*/ xid = rbuf[0] + (rbuf[1] << 8); /*next rec id*/ memcpy(rec,&rbuf[2],16); *nextid = xid; id = rbuf[2] + (rbuf[3] << 8); /*curr rec id*/ /* recid (requested) should match newid (received) */ if (fdebug) { if ((recid != id) && (recid != LAST_REC) && (recid != 0)) { /* the OpenIPMI driver does this sometimes */ msgout("get_sel MISMATCH: recid=%x newid=%x next=%x\n", recid,id,xid); dump_buf("get_sel cmd",ibuf,6,0); dump_buf("get_sel rsp",rbuf,rlen,0); } } } } if (fdebug) msgout("get_sel(%x) rv=%d cc=%x id=%x next=%x\n", recid,rv,cc,id,*nextid); return(rv); } static int getevent_sel(uchar *rdata, int *rlen, uchar *ccode) { uchar rec[24]; int rv = 0; ushort newid; ushort nextid; ushort recid; /* get current last record */ recid = sel_recid; rv = get_sel_entry(recid,&nextid,rec); if (rv == 0xCB && recid == 0) { /* SEL is empty */ *ccode = (uchar)rv; /* save the real ccode */ rv = 0x80; /* this is ok, just keep waiting */ } if (rv == 0) { if (fdebug) msgout("sel ok, id=%x next=%x\n",recid,nextid); if ((nextid == LAST_REC) || (recid == nextid)) { *ccode = 0x80; /*nothing new*/ } else { recid = nextid; /* else get new one */ rv = get_sel_entry(recid,&nextid,rec); if (rv == 0) { /* new event */ newid = rec[0] + (rec[1] << 8); if (drvtype == DRV_MV && recid != newid) { /* handle MV driver bug, try to get next one. */ if (fdebug) msgout("%s bug, record mismatch\n", show_driver_type(DRV_MV)); } if (fdebug) msgout("recid=%x newid=%x next=%x\n", recid,newid,nextid); memcpy(rdata,rec,16); *rlen = 16; *ccode = 0; sel_recid = recid; /*or newid*/ memcpy(&sel_time,&rec[2],4); } } } else { /* Error reading last recid saved */ if (fdebug) msgout("sel recid %x error, rv = %d\n",recid,rv); /* We want to set sel_recid = 0 here for some errors. */ if (rv == 0xCB || rv == 0xCD) { /* empty, or wrong SDR id */ sel_recid = 0; *ccode = (uchar)rv; rv = 0x80; /* wait again */ } } return(rv); } static int startevent_sel(ushort *precid, uint *ptime) { FILE *fd; uchar rec[24]; uint t = 0; ushort r = 0; ushort r2 = 0; int rv = -1; fd = fopen(idxfile,"r"); if (fdebug) msgout("start: idxfile=%s fd=%p\n",idxfile,fd); if (fd != NULL) { // Read the file, get savtime & savid rv = fscanf(fd,"%x %x",&t,&r); fclose(fd); if (r == LAST_REC) r = 0; rv = 0; /*read it, success*/ } else { /* treat as first time */ r = LAST_REC; rv = get_sel_entry(r,&r2,rec); if (rv == 0) { memcpy(&t,&rec[2],4); r = rec[0] + (rec[1] << 8); /*use current rec id*/ } else r = 0; rv = 1; /*first time*/ } if (fdebug) msgout("start: recid=%x time=%x\n",r,t); *ptime = t; *precid = r; return(rv); } static int syncevent_sel(ushort recid, uint itime) { FILE *fd; int rv; // Rewrite the saved time & record id if (fdebug) msgout("sync: recid=%x time=%x\n",recid,itime); fd = fopen(idxfile,"w"); if (fd == NULL) { msgout("syncevent: cannot open %s for writing\n",idxfile); rv = -1; } else { fprintf(fd,"%x %x\n",itime,recid); fclose(fd); rv = 0; } return(rv); } static void ievt_cleanup(void) { char obuf[48]; snprintf(obuf,sizeof(obuf),"%s exiting.\n",progname); msgout(obuf); write_syslog(obuf); if (finit_ok) { syncevent_sel(sel_recid,sel_time); free_sdr_cache(sdrs); } ipmi_close_(); /*inert if not opened*/ exit(EXIT_SUCCESS); } void show_event(uchar *evt,char *obuf, int sz) { int i; char sysbuf[250]; /* obuf should be 132 chars or more */ msgout("event data: "); for (i=0; i<16; i++) msgout("%02x ",evt[i]); msgout("\n"); decode_sel_entry(evt,obuf,sz); msgout(obuf); /*writes to outfile*/ /* write the message to syslog also. */ snprintf(sysbuf,sizeof(sysbuf),"%s: %s",progname,obuf); write_syslog(sysbuf); } #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) { int ret = 0; char c; uchar devrec[16]; uchar event[32]; /*usu 16 bytes */ char outbuf[160]; char *s1; int i, rlen; uchar ccode; uchar sensor_type; fdout = stderr; printf("%s ver %s\n", progname,progver); while ( (c = getopt( argc, argv,"m:p:s:t:xEF:N:P:R:T:U:V:YZ:?")) != EOF ) switch(c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } fset_mc = 1; ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 's': sdrfile = optarg; break; case 't': mytag = optarg; break; /* specific sensor tag */ case 'x': fdebug = 1; break; /* debug messages */ case 'p': /* port */ 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 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: printf("Usage: %s [-msx -NUPREFTVY]\n", progname); printf(" where -x show eXtra debug messages\n"); printf(" -m002000 specific MC (bus 00,sa 20,lun 00)\n"); printf(" -s File loads SDRs from File\n"); printf(" -t tag search for 'tag' in SDRs\n"); print_lan_opt_usage(1); exit(1); } /* Rather than parse_lan_options above, the set_lan_options function * could be used if the program already knows the nodename, etc. */ fipmilan = is_remote(); ret = ipmi_getdeviceid(devrec,16,fdebug); if (ret != 0) { printf("Cannot do ipmi_getdeviceid, ret = %d\n",ret); goto do_exit; } else { /*success*/ uchar ipmi_maj, ipmi_min; ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); } drvtype = get_driver_type(); /* could make it a daemon here, if desired */ fdout = fopen(outfile,"a"); if (fdout == NULL) { printf("%s: Cannot open %s\n", progname,outfile); fdout = stderr; } else { sprintf(outbuf,"%s ver %s started\n", progname,progver); msgout(outbuf); } sprintf(outbuf,"%s reading sensors ...\n",progname); write_syslog(outbuf); ret = get_sdr_cache(&sdrs); if (fdebug) msgout("get_sdr_cache ret = %d\n",ret); if (ret == 0) set_sel_opts(1,0, sdrs,fdebug,0); if (fipmilan) { char *node; node = get_nodename(); strcat(idxfile,"-"); strcat(idxfile,node); strcat(outfile,"-"); strcat(outfile,node); } ret = startevent_sel(&sel_recid,&sel_time); ievt_siginit(); finit_ok = 1; ret = 0; /*ignore any earlier errors, keep going*/ i = 0; while (ret == 0) { /*wait for bmc message events*/ if (fdebug) msgout("%s: %d Polling every %d sec for a new event after id %x\n", progname, i, wait_interval, sel_recid); rlen = sizeof(event); ret = getevent_sel(event,&rlen,&ccode); if (ret == 0) ret = ccode; if (fdebug) msgout("getevent_sel ret = %d\n",ret); if (ret == 0) { /* got an event successfully */ sensor_type = event[10]; msgout("got event id %04x, sensor_type = %02x\n", sel_recid,sensor_type); show_event(event,outbuf,sizeof(outbuf)); syncevent_sel(sel_recid,sel_time); } else if (ret == 0x80) { ret = 0; /*keep waiting*/ } else { msgout("get_event error: ret = 0x%x\n",ret); break; } i++; os_usleep(wait_interval,0); } /*end while loop*/ do_exit: ievt_cleanup(); show_outcome(progname,ret); exit (ret); } /* end main()*/ /* end ipmi_sample_evt.c */ ipmiutil-3.1.5/util/isolwin.c0000644000076400007640000002266013566765324016271 0ustar mgportalloggers/* * isolwin.c * IPMI Serial-Over-LAN console Windows terminal emulation * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2006 Intel Corporation. * Copyright (c) 2009 Kontron America, Inc. * * 08/20/07 Andy Cress - extracted from isolconsole.c/WIN32, * added os_usleep to input_thread * 09/24/07 Andy Cress - various termio fixes, e.g. scroll(), BUF_SZ */ /*M* Copyright (c) 2006-2007, Intel Corporation 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 Corporation 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 #include #include #include #include #include #include #define SockType SOCKET typedef struct { int type; int len; char *data; } SOL_RSP_PKT; extern void dbglog( char *pattn, ... ); /*from isolconsole.c*/ extern void os_usleep(int s, int u); /*from ipmilan.c*/ typedef unsigned char uchar; /* * Global variables */ extern int sol_done; extern char fUseWinCon; extern uchar fRaw; extern uchar fCRLF; /* =1 to use legacy CR+LF translation for BIOS */ extern uchar bTextMode; extern char fdebug; /*from isolconsole.c*/ extern int wait_time; /*from isolconsole.c*/ /*======== start Windows =============================*/ /* Windows os_read, os_select and supporting code */ #define INBUF_SZ 128 static DWORD rg_stdin[INBUF_SZ]; static int n_stdin = 0; #define NSPECIAL 33 static struct { uchar c; uchar code[4]; } special_keys[NSPECIAL] = { ' ', {0x20,0x20,0x01,0x01}, '!', {0x21,0x31,0x01,0x21}, '"', {0x22,0xde,0x01,0x21}, '#', {0x23,0x33,0x01,0x21}, '$', {0x24,0x34,0x01,0x21}, '%', {0x25,0x35,0x01,0x21}, '&', {0x26,0x37,0x01,0x21}, 0x27, {0x27,0xde,0x01,0x01}, /*'''*/ '(', {0x28,0x39,0x01,0x21}, ')', {0x29,0x30,0x01,0x21}, '*', {0x2a,0x38,0x01,0x21}, '+', {0x2b,0xbb,0x01,0x21}, ',', {0x2c,0xbc,0x01,0x01}, '-', {0x2d,0xbd,0x01,0x01}, '.', {0x2e,0xbe,0x01,0x01}, '/', {0x2f,0xbf,0x01,0x01}, ':', {0x3a,0xba,0x01,0x21}, ';', {0x3b,0xba,0x01,0x01}, '<', {0x3c,0xbc,0x01,0x21}, '=', {0x3d,0xbb,0x01,0x01}, '>', {0x3e,0xbe,0x01,0x21}, '?', {0x3f,0xbf,0x01,0x21}, '@', {0x40,0x32,0x01,0x21}, '[', {0x5b,0xdb,0x01,0x01}, 0x5c, {0x5c,0xdc,0x01,0x01}, /*'\'*/ ']', {0x5d,0xdd,0x01,0x01}, '^', {0x5e,0x36,0x01,0x21}, '_', {0x5f,0xbd,0x01,0x21}, '`', {0x60,0xc0,0x01,0x01}, '{', {0x7b,0xdb,0x01,0x21}, '|', {0x7c,0xdc,0x01,0x21}, '}', {0x7d,0xdd,0x01,0x21}, '~', {0x7e,0xc0,0x01,0x21} }; void Ascii2KeyCode(uchar c, uchar *buf) { int i; int j = 0; /* Convert ascii chars from script file into KeyCodes*/ for (i = 0; i < NSPECIAL; i++) if (c == special_keys[i].c) break; if (i < NSPECIAL) { /* special chars */ buf[j++] = c; buf[j++] = special_keys[i].code[1]; buf[j++] = special_keys[i].code[2]; buf[j++] = special_keys[i].code[3]; } else if (c < 0x0D) { /* control chars, like Ctl-c */ buf[j++] = c; buf[j++] = (c | 0x40); buf[j++] = 0x01; buf[j++] = 0x41; } else { /* alphanumeric chars */ buf[j++] = c; if (c > 0x60) buf[j++] = c - 0x20; /*drop 0x20 bit if upper case*/ else buf[j++] = c; buf[j++] = 0x01; buf[j++] = 0x01; } } DWORD WINAPI input_thread( LPVOID lpParam) { HANDLE hstdin; DWORD rv = 0; INPUT_RECORD inrecords[10]; DWORD nread; DWORD oldmode; hstdin = GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(hstdin, &oldmode); SetConsoleMode(hstdin, ENABLE_WINDOW_INPUT); while (!sol_done) { DWORD dwResult = WaitForSingleObject(hstdin, wait_time * 2); /*1000 msec*/ if (dwResult != WAIT_OBJECT_0) { if (dwResult != WAIT_TIMEOUT) dbglog("input_thread: Wait result = %x\n",dwResult); continue; } if (ReadConsoleInput(hstdin, inrecords, 10, &nread)) { DWORD index; for (index = 0; index < nread; index++) { /* Pack the char info into a DWORD */ INPUT_RECORD *precord = &inrecords[index]; DWORD dwChar; if (precord->EventType == KEY_EVENT) { if (precord->Event.KeyEvent.wVirtualKeyCode == VK_SHIFT || precord->Event.KeyEvent.wVirtualKeyCode == VK_CONTROL || precord->Event.KeyEvent.wVirtualKeyCode == VK_MENU || precord->Event.KeyEvent.wVirtualKeyCode == VK_CAPITAL) { continue; } dwChar = (((precord->Event.KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) != 0) << 31) | (((precord->Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0) << 30) | (((precord->Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) != 0) << 29) | (((precord->Event.KeyEvent.dwControlKeyState & NUMLOCK_ON) != 0) << 28) | (((precord->Event.KeyEvent.dwControlKeyState & SCROLLLOCK_ON) != 0) << 27) | (((precord->Event.KeyEvent.dwControlKeyState & CAPSLOCK_ON) != 0) << 26) | (((precord->Event.KeyEvent.dwControlKeyState & ENHANCED_KEY) != 0) << 25) | ((precord->Event.KeyEvent.bKeyDown != 0) << 24) | ((precord->Event.KeyEvent.wRepeatCount & 0xFF) << 16) | ((precord->Event.KeyEvent.wVirtualKeyCode & 0xFF) << 8) | (precord->Event.KeyEvent.uChar.AsciiChar & 0xFF); } else if (precord->EventType == WINDOW_BUFFER_SIZE_EVENT) { dwChar = ~0; } else { continue; } if (precord->Event.KeyEvent.bKeyDown == 0) { if (fdebug > 2) dbglog("input_thread: key up event (%08x)\n",dwChar); continue; } if (n_stdin < INBUF_SZ) { /* rg_stdin[INBUF_SZ] */ if (fdebug > 2) dbglog("input_thread: n=%d dwChar=%08x keystate=%x\n", n_stdin, dwChar, precord->Event.KeyEvent.dwControlKeyState); rg_stdin[n_stdin++] = dwChar; } else dbglog("input_thread: overflow n=%d size=%d\n", n_stdin,INBUF_SZ); } /*end-for nread*/ } /*endif ReadConsoleInput*/ } /*end-while not sol_done*/ SetConsoleMode(hstdin, oldmode); CloseHandle(hstdin); return(rv); } int os_read(int fd, uchar *buf, int sz) { int len = 0; if (fd == 0) { if (n_stdin > 0) { /* get pending chars from stdin */ int cnt = n_stdin * sizeof(rg_stdin[0]); if (fdebug > 2) dbglog("os_read: stdin n=%d %04x %04x \n", n_stdin,rg_stdin[0],rg_stdin[1]); memcpy(buf, rg_stdin, cnt); len = cnt; n_stdin = 0; memset((uchar *)&rg_stdin,0,cnt); } } else { // ReadFile(fd, buf, sz, &len, NULL); // len = _read(fd, buf, sz); len = recv(fd, buf, sz, 0); } return(len); } int os_select(int infd, SockType sfd, fd_set *read_fds, fd_set *error_fds) { int rv = 0; struct timeval tv; /* check the socket for new data via select */ /* Windows select only works on WSA sockets */ { FD_ZERO(read_fds); FD_SET(sfd, read_fds); FD_ZERO(error_fds); FD_SET(sfd, error_fds); tv.tv_sec = 0; tv.tv_usec = wait_time * 100; /* 50000 usec, 50 msec, 0.05 sec */ // rv = select(sfd + 1, read_fds, NULL, error_fds, &tv); rv = select((int)(sfd+1), read_fds, NULL, error_fds, &tv); if (rv < 0) { rv = -(WSAGetLastError()); if (fdebug) dbglog("select(%d) error %d\r\n",sfd,rv); } else if (FD_ISSET(sfd, error_fds)) { if (fdebug) dbglog("select(%d) error_fds rv=%d err=%d\r\n",sfd, rv, WSAGetLastError()); } if (rv > 0 && fdebug) dbglog("select(%d) got socket data %d\r\n",sfd,rv); } if (infd == 0) { /* check stdin */ if (n_stdin > 0) { FD_SET(infd, read_fds); if (rv < 0) rv = 1; else rv++; } } return rv; } /*======== end Windows ===============================*/ /*end solwin.c*/ ipmiutil-3.1.5/util/oem_sun.c0000644000076400007640000007132413566765324016253 0ustar mgportalloggers/* * oem_sun.c * Handle Sun OEM command functions * * Change history: * 09/02/2010 ARCress - included in source tree * *--------------------------------------------------------------------- */ /* * Copyright (c) 2005 Sun Microsystems, 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: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution 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. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #include #include #include #ifdef WIN32 #include #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int #include "getopt.h" #else #include #include #include #include #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #include #else #include #endif #endif #ifndef ULONG_MAX /*needed for WIN32*/ #define ULONG_MAX 4294967295UL #define UCHAR_MAX 255 #endif #include "ipmicmd.h" #include "isensor.h" #include "oem_sun.h" extern int verbose; /*ipmilanplus.c*/ extern void lprintf(int level, const char * format, ...); /*ipmilanplus.c*/ extern void set_loglevel(int level); static const struct valstr sunoem_led_type_vals[] = { { 0, "OK2RM" }, { 1, "SERVICE" }, { 2, "ACT" }, { 3, "LOCATE" }, { 0xFF, NULL } }; static const struct valstr sunoem_led_mode_vals[] = { { 0, "OFF" }, { 1, "ON" }, { 2, "STANDBY" }, { 3, "SLOW" }, { 4, "FAST" }, { 0xFF, NULL } }; static const struct valstr sunoem_led_mode_optvals[] = { { 0, "STEADY_OFF" }, { 1, "STEADY_ON" }, { 2, "STANDBY_BLINK" }, { 3, "SLOW_BLINK" }, { 4, "FAST_BLINK" }, { 0xFF, NULL } }; /* global variables */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil sunoem"; #else static char * progver = "3.08"; static char * progname = "isunoem"; #endif static char fdebug = 0; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static int is_sbcmd = 0; static int csv_output = 0; static uchar *sdrcache = NULL; static int vend_id = 0; static int prod_id = 0; static void ipmi_sunoem_usage(void) { lprintf(LOG_NOTICE, "usage: sunoem [option...]"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " fan speed <0-100>"); lprintf(LOG_NOTICE, " Set system fan speed (PWM duty cycle)"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " sshkey set "); lprintf(LOG_NOTICE, " Set ssh key for a userid into authorized_keys,"); lprintf(LOG_NOTICE, " view users with 'user list' command."); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " sshkey del "); lprintf(LOG_NOTICE, " Delete ssh key for userid from authorized_keys,"); lprintf(LOG_NOTICE, " view users with 'user list' command."); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " led get [ledtype]"); lprintf(LOG_NOTICE, " Read status of LED found in Generic Device Locator."); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " led set [ledtype]"); lprintf(LOG_NOTICE, " Set mode of LED found in Generic Device Locator."); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " sbled get [ledtype]"); lprintf(LOG_NOTICE, " Read status of LED found in Generic Device Locator"); lprintf(LOG_NOTICE, " for Sun Blade Modular Systems."); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " sbled set [ledtype]"); lprintf(LOG_NOTICE, " Set mode of LED found in Generic Device Locator"); lprintf(LOG_NOTICE, " for Sun Blade Modular Systems."); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " Use 'sdr list generic' command to get list of Generic"); lprintf(LOG_NOTICE, " Devices that are controllable LEDs."); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " Required SIS LED Mode:"); lprintf(LOG_NOTICE, " OFF Off"); lprintf(LOG_NOTICE, " ON Steady On"); lprintf(LOG_NOTICE, " STANDBY 100ms on 2900ms off blink rate"); lprintf(LOG_NOTICE, " SLOW 1HZ blink rate"); lprintf(LOG_NOTICE, " FAST 4HZ blink rate"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " Optional SIS LED Type:"); lprintf(LOG_NOTICE, " OK2RM OK to Remove"); lprintf(LOG_NOTICE, " SERVICE Service Required"); lprintf(LOG_NOTICE, " ACT Activity"); lprintf(LOG_NOTICE, " LOCATE Locate"); lprintf(LOG_NOTICE, ""); } /* * IPMI Request Data: 1 byte * * [byte 0] FanSpeed Fan speed as percentage */ static int ipmi_sunoem_fan_speed(void * intf, uint8_t speed) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; /* * sunoem fan speed */ if (speed > 100) { lprintf(LOG_NOTICE, "Invalid fan speed: %d", speed); return -1; } req.msg.netfn = IPMI_NETFN_SUNOEM; req.msg.cmd = IPMI_SUNOEM_SET_FAN_SPEED; req.msg.data = &speed; req.msg.data_len = 1; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { lprintf(LOG_ERR, "Sun OEM Set Fan Speed command failed"); return (rv); } else if (rv > 0) { lprintf(LOG_ERR, "Sun OEM Set Fan Speed command failed: %s", decode_cc(0,rv)); return (rv); } printf("Set Fan speed to %d%%\n", speed); return rv; } static void led_print(const char * name, uint8_t state) { if (csv_output) printf("%s,%s\n", name, val2str(state, sunoem_led_mode_vals)); else printf("%-16s | %s\n", name, val2str(state, sunoem_led_mode_vals)); } int sunoem_led_get(void * intf, uchar *sdr, uchar ledtype, uchar *prsp) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t rqdata[7]; int rqdata_len = 5; struct sdr_record_generic_locator * dev; if (sdr == NULL) return -1; dev = (struct sdr_record_generic_locator *)&sdr[5]; rqdata[0] = dev->dev_slave_addr; if (ledtype == 0xFF) rqdata[1] = dev->oem; else rqdata[1] = ledtype; rqdata[2] = dev->dev_access_addr; rqdata[3] = dev->oem; if (is_sbcmd) { rqdata[4] = dev->entity.id; rqdata[5] = dev->entity.instance; rqdata[6] = 0; rqdata_len = 7; } else { rqdata[4] = 0; } req.msg.netfn = IPMI_NETFN_SUNOEM; req.msg.cmd = IPMI_SUNOEM_LED_GET; req.msg.lun = dev->lun; req.msg.data = rqdata; req.msg.data_len = (uchar)rqdata_len; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { lprintf(LOG_ERR, "Sun OEM Get LED command failed"); return rv; } else if (rv > 0) { lprintf(LOG_ERR, "Sun OEM Get LED command failed: %s", decode_cc(0,rv)); return rv; } if (prsp != NULL) memcpy(prsp,rsp,rsp_len); if (rsp_len != 1) { lprintf(LOG_ERR, "Sun OEM Get LED command error len=%d", rsp_len); return -1; } return rv; } int sunoem_led_set(void * intf, uchar *sdr, uchar ledtype, uchar ledmode) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t rqdata[9]; int rqdata_len = 7; struct sdr_record_generic_locator * dev; if (sdr == NULL) return -1; dev = (struct sdr_record_generic_locator *)&sdr[5]; rqdata[0] = dev->dev_slave_addr; if (ledtype == 0xFF) rqdata[1] = dev->oem; else rqdata[1] = ledtype; rqdata[2] = dev->dev_access_addr; rqdata[3] = dev->oem; rqdata[4] = ledmode; if (is_sbcmd) { rqdata[5] = dev->entity.id; rqdata[6] = dev->entity.instance; rqdata[7] = 0; rqdata[8] = 0; rqdata_len = 9; } else { rqdata[5] = 0; rqdata[6] = 0; } req.msg.netfn = IPMI_NETFN_SUNOEM; req.msg.cmd = IPMI_SUNOEM_LED_SET; req.msg.lun = dev->lun; req.msg.data = rqdata; req.msg.data_len = (uchar)rqdata_len; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { lprintf(LOG_ERR, "Sun OEM Set LED command failed"); } else if (rv > 0) { lprintf(LOG_ERR, "Sun OEM Set LED command failed: %s", decode_cc(0,rv)); } return rv; } static void sunoem_led_get_byentity(void * intf, uchar entity_id, uchar entity_inst, uchar ledtype) { uchar rsp[IPMI_RSPBUF_SIZE]; int rv; uchar *elist; struct entity_id entity; struct sdr_record_generic_locator *dev; uchar sdr[IPMI_RSPBUF_SIZE]; ushort id; if (entity_id == 0) return; /* lookup sdrs with this entity */ memset(&entity, 0, sizeof(struct entity_id)); entity.id = entity_id; entity.instance = entity_inst; if (sdrcache == NULL) rv = get_sdr_cache(&elist); else elist = sdrcache; id = 0; /* for each generic sensor set its led state */ while(find_sdr_next(sdr,elist,id) == 0) { id = sdr[0] + (sdr[1] << 8); if (sdr[3] != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) continue; dev = (struct sdr_record_generic_locator *)&sdr[5]; if ((dev->entity.id == entity_id) && (dev->entity.instance == entity_inst)) { rv = sunoem_led_get(intf, sdr, ledtype, rsp); if (rv == 0) { led_print((const char *)dev->id_string, rsp[0]); } } } if (sdrcache == NULL) free_sdr_cache(elist); } static void sunoem_led_set_byentity(void * intf, uchar entity_id, uchar entity_inst, uchar ledtype, uchar ledmode) { int rv; uchar *elist; struct entity_id entity; struct sdr_record_generic_locator * dev; uchar sdr[IPMI_RSPBUF_SIZE]; ushort id; if (entity_id == 0) return; /* lookup sdrs with this entity */ memset(&entity, 0, sizeof(struct entity_id)); entity.id = entity_id; entity.instance = entity_inst; if (sdrcache == NULL) rv = get_sdr_cache(&elist); else elist = sdrcache; id = 0; /* for each generic sensor set its led state */ while(find_sdr_next(sdr,elist,id) == 0) { id = sdr[0] + (sdr[1] << 8); if (sdr[3] != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) continue; /* match entity_id and entity_inst */ dev = (struct sdr_record_generic_locator *)&sdr[5]; if ((dev->entity.id == entity_id) && (dev->entity.instance == entity_inst)) { rv = sunoem_led_set(intf, sdr, ledtype, ledmode); if (rv == 0) { led_print((const char *)dev->id_string, ledmode); } } } if (sdrcache == NULL) free_sdr_cache(elist); } /* * IPMI Request Data: 5 bytes * * [byte 0] devAddr Value from the "Device Slave Address" field in * LED's Generic Device Locator record in the SDR * [byte 1] led LED Type: OK2RM, ACT, LOCATE, SERVICE * [byte 2] ctrlrAddr Controller address; value from the "Device * Access Address" field, 0x20 if the LED is local * [byte 3] hwInfo The OEM field from the SDR record * [byte 4] force 1 = directly access the device * 0 = go thru its controller * Ignored if LED is local * * The format below is for Sun Blade Modular systems only * [byte 4] entityID The entityID field from the SDR record * [byte 5] entityIns The entityIns field from the SDR record * [byte 6] force 1 = directly access the device * 0 = go thru its controller * Ignored if LED is local */ static int ipmi_sunoem_led_get(void * intf, int argc, char ** argv) { uchar rsp[IPMI_RSPBUF_SIZE]; int rv; uchar *alist; struct sdr_record_entity_assoc *assoc; struct sdr_record_generic_locator * dev; uchar sdr[IPMI_RSPBUF_SIZE]; uchar sdr1[IPMI_RSPBUF_SIZE]; ushort id; uchar ledtype = 0xFF; int i; /* * sunoem led/sbled get [type] */ if (argc < 1 || strncmp(argv[0], "help", 4) == 0) { ipmi_sunoem_usage(); return 0; } if (argc > 1) { ledtype = (uchar)str2val(argv[1], sunoem_led_type_vals); if (ledtype == 0xFF) lprintf(LOG_ERR, "Unknown ledtype, will use data from the SDR oem field"); } if (strncasecmp(argv[0], "all", 3) == 0) { /* do all generic sensors */ lprintf(LOG_NOTICE, "Fetching SDRs ..."); rv = get_sdr_cache(&alist); if (fdebug) lprintf(LOG_NOTICE, "get_sdr_cache rv = %d",rv); id = 0; rv = ERR_NOT_FOUND; while(find_sdr_next(sdr,alist,id) == 0) { id = sdr[0] + (sdr[1] << 8); if (sdr[3] != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) continue; dev = (struct sdr_record_generic_locator *)&sdr[5]; if (dev->entity.logical) // (sdr[13] & 0x80 != 0) continue; rv = sunoem_led_get(intf, sdr, ledtype, rsp); if (rv == 0) { led_print((const char *)dev->id_string, rsp[0]); } } free_sdr_cache(alist); return rv; } /* look up generic device locator record in SDR */ id = (ushort)atoi(argv[0]); lprintf(LOG_NOTICE, "Fetching SDRs ..."); rv = get_sdr_cache(&alist); if (fdebug) lprintf(LOG_NOTICE, "get_sdr_cache rv = %d",rv); if (rv == 0) { sdrcache = alist; rv = find_sdr_next(sdr1,alist,id); } if (rv != 0) { lprintf(LOG_ERR, "No Sensor Data Record found for %s", argv[0]); free_sdr_cache(alist); return (rv); } if (sdr1[3] != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) { lprintf(LOG_ERR, "Invalid SDR type %d", sdr1[3]); free_sdr_cache(alist); return (-1); } dev = (struct sdr_record_generic_locator *)&sdr1[5]; if (!dev->entity.logical) { /* * handle physical entity */ rv = sunoem_led_get(intf, sdr1, ledtype, rsp); if (rv == 0) { led_print((const char *)dev->id_string, rsp[0]); } free_sdr_cache(alist); return rv; } /* * handle logical entity for LED grouping */ lprintf(LOG_INFO, "LED %s is logical device", argv[0]); /* get entity assoc records */ // rv = get_sdr_cache(&alist); id = 0; while(find_sdr_next(sdr,alist,id) == 0) { id = sdr[0] + (sdr[1] << 8); if (sdr[3] != SDR_RECORD_TYPE_ENTITY_ASSOC) continue; assoc = (struct sdr_record_entity_assoc *)&sdr[5]; if (assoc == NULL) continue; /* check that the entity id/instance matches our generic record */ if (assoc->entity.id != dev->entity.id || assoc->entity.instance != dev->entity.instance) continue; if (assoc->flags.isrange) { /* * handle ranged entity associations * * the test for non-zero entity id is handled in * sunoem_led_get_byentity() */ /* first range set - id 1 and 2 must be equal */ if (assoc->entity_id_1 == assoc->entity_id_2) for (i = assoc->entity_inst_1; i <= assoc->entity_inst_2; i++) sunoem_led_get_byentity(intf, assoc->entity_id_1, (uchar)i, ledtype); /* second range set - id 3 and 4 must be equal */ if (assoc->entity_id_3 == assoc->entity_id_4) for (i = assoc->entity_inst_3; i <= assoc->entity_inst_4; i++) sunoem_led_get_byentity(intf, assoc->entity_id_3, (uchar)i, ledtype); } else { /* * handle entity list */ sunoem_led_get_byentity(intf, assoc->entity_id_1, assoc->entity_inst_1, ledtype); sunoem_led_get_byentity(intf, assoc->entity_id_2, assoc->entity_inst_2, ledtype); sunoem_led_get_byentity(intf, assoc->entity_id_3, assoc->entity_inst_3, ledtype); sunoem_led_get_byentity(intf, assoc->entity_id_4, assoc->entity_inst_4, ledtype); } } free_sdr_cache(alist); sdrcache = NULL; return rv; } /* * IPMI Request Data: 7 bytes * * [byte 0] devAddr Value from the "Device Slave Address" field in * LED's Generic Device Locator record in the SDR * [byte 1] led LED Type: OK2RM, ACT, LOCATE, SERVICE * [byte 2] ctrlrAddr Controller address; value from the "Device * Access Address" field, 0x20 if the LED is local * [byte 3] hwInfo The OEM field from the SDR record * [byte 4] mode LED Mode: OFF, ON, STANDBY, SLOW, FAST * [byte 5] force TRUE - directly access the device * FALSE - go thru its controller * Ignored if LED is local * [byte 6] role Used by BMC for authorization purposes * * The format below is for Sun Blade Modular systems only * [byte 5] entityID The entityID field from the SDR record * [byte 6] entityIns The entityIns field from the SDR record * [byte 7] force TRUE - directly access the device * FALSE - go thru its controller * Ignored if LED is local * [byte 8] role Used by BMC for authorization purposes * * * IPMI Response Data: 1 byte * * [byte 0] mode LED Mode: OFF, ON, STANDBY, SLOW, FAST */ static int ipmi_sunoem_led_set(void * intf, int argc, char ** argv) { int rv; uchar *alist; struct sdr_record_entity_assoc *assoc; struct sdr_record_generic_locator * dev; uchar sdr[IPMI_RSPBUF_SIZE]; uchar sdr1[IPMI_RSPBUF_SIZE]; ushort id; uchar ledmode; uchar ledtype = 0xFF; int i; /* * sunoem led/sbled set [type] */ if (argc < 2 || strncmp(argv[0], "help", 4) == 0) { ipmi_sunoem_usage(); return 0; } i = str2val(argv[1], sunoem_led_mode_vals); if (i == 0xFF) { i = str2val(argv[1], sunoem_led_mode_optvals); if (i == 0xFF) { lprintf(LOG_NOTICE, "Invalid LED Mode: %s", argv[1]); return -1; } } ledmode = (uchar)i; if (argc > 3) { ledtype = (uchar)str2val(argv[2], sunoem_led_type_vals); if (ledtype == 0xFF) lprintf(LOG_ERR, "Unknown ledtype, will use data from the SDR oem field"); } if (strncasecmp(argv[0], "all", 3) == 0) { /* do all generic sensors */ lprintf(LOG_NOTICE, "Fetching SDRs ..."); rv = get_sdr_cache(&alist); if (fdebug) lprintf(LOG_NOTICE, "get_sdr_cache rv = %d",rv); id = 0; rv = ERR_NOT_FOUND; while(find_sdr_next(sdr,alist,id) == 0) { id = sdr[0] + (sdr[1] << 8); if (sdr[3] != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) continue; dev = (struct sdr_record_generic_locator *)&sdr[5]; if ((sdr[13] & 0x80) != 0) /*logical entity*/ continue; rv = sunoem_led_set(intf, sdr, ledtype, ledmode); if (rv == 0) { led_print((const char *)dev->id_string, ledmode); } } free_sdr_cache(alist); return rv; } /* look up generic device locator records in SDR */ id = (ushort)atoi(argv[0]); lprintf(LOG_NOTICE, "Fetching SDRs ..."); rv = get_sdr_cache(&alist); if (fdebug) lprintf(LOG_NOTICE, "get_sdr_cache rv = %d",rv); if (rv == 0) { sdrcache = alist; rv = find_sdr_next(sdr1,alist,id); } if (rv != 0) { lprintf(LOG_ERR, "No Sensor Data Record found for %s", argv[0]); free_sdr_cache(alist); return (rv); } if (sdr1[3] != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) { lprintf(LOG_ERR, "Invalid SDR type %d", sdr1[3]); free_sdr_cache(alist); return -1; } dev = (struct sdr_record_generic_locator *)&sdr1[5]; if (!dev->entity.logical) { /* * handle physical entity */ rv = sunoem_led_set(intf, sdr, ledtype, ledmode); if (rv == 0) { led_print(argv[0], ledmode); } free_sdr_cache(alist); return rv; } /* * handle logical entity for LED grouping */ lprintf(LOG_INFO, "LED %s is logical device", argv[0]); /* get entity assoc records */ id = 0; while(find_sdr_next(sdr,alist,id) == 0) { id = sdr[0] + (sdr[1] << 8); if (sdr[3] != SDR_RECORD_TYPE_ENTITY_ASSOC) continue; assoc = (struct sdr_record_entity_assoc *)&sdr[5]; if (assoc == NULL) continue; /* check that the entity id/instance matches our generic record */ if (assoc->entity.id != dev->entity.id || assoc->entity.instance != dev->entity.instance) continue; if (assoc->flags.isrange) { /* * handle ranged entity associations * * the test for non-zero entity id is handled in * sunoem_led_get_byentity() */ /* first range set - id 1 and 2 must be equal */ if (assoc->entity_id_1 == assoc->entity_id_2) for (i = assoc->entity_inst_1; i <= assoc->entity_inst_2; i++) sunoem_led_set_byentity(intf, assoc->entity_id_1, (uchar)i, ledtype, ledmode); /* second range set - id 3 and 4 must be equal */ if (assoc->entity_id_3 == assoc->entity_id_4) for (i = assoc->entity_inst_3; i <= assoc->entity_inst_4; i++) sunoem_led_set_byentity(intf, assoc->entity_id_3, (uchar)i, ledtype, ledmode); } else { /* * handle entity list */ sunoem_led_set_byentity(intf, assoc->entity_id_1, assoc->entity_inst_1, ledtype, ledmode); sunoem_led_set_byentity(intf, assoc->entity_id_2, assoc->entity_inst_2, ledtype, ledmode); sunoem_led_set_byentity(intf, assoc->entity_id_3, assoc->entity_inst_3, ledtype, ledmode); sunoem_led_set_byentity(intf, assoc->entity_id_4, assoc->entity_inst_4, ledtype, ledmode); } } free_sdr_cache(alist); sdrcache = NULL; return rv; } static int ipmi_sunoem_sshkey_del(void * intf, uint8_t uid) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; memset(&req, 0, sizeof(struct ipmi_rq)); req.msg.netfn = IPMI_NETFN_SUNOEM; req.msg.cmd = IPMI_SUNOEM_DEL_SSH_KEY; req.msg.data = &uid; req.msg.data_len = 1; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { lprintf(LOG_ERR, "Unable to delete ssh key for UID %d", uid); return rv; } else if (rv > 0) { lprintf(LOG_ERR, "Unable to delete ssh key for UID %d: %s", uid, decode_cc(0,rv)); return rv; } printf("Deleted SSH key for user id %d\n", uid); return rv; } #define SSHKEY_BLOCK_SIZE 64 static int ipmi_sunoem_sshkey_set(void * intf, uint8_t uid, char * ifile) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv = -1; struct ipmi_rq req; FILE * fp; size_t count; uint16_t i_size, r, f_size; uint8_t wbuf[SSHKEY_BLOCK_SIZE + 3]; if (ifile == NULL) { lprintf(LOG_ERR, "Invalid or missing input filename"); return -1; } fp = fopen(ifile, "r"); if (fp == NULL) { lprintf(LOG_ERR, "Unable to open file %s for reading", ifile); return -1; } printf("Setting SSH key for user id %d...", uid); memset(&req, 0, sizeof(struct ipmi_rq)); req.msg.netfn = IPMI_NETFN_SUNOEM; req.msg.cmd = IPMI_SUNOEM_SET_SSH_KEY; req.msg.data = wbuf; fseek(fp, 0, SEEK_END); f_size = (uint16_t)ftell(fp); fseek(fp, 0, SEEK_SET); for (r = 0; r < f_size; r += i_size) { i_size = f_size - r; if (i_size > SSHKEY_BLOCK_SIZE) i_size = SSHKEY_BLOCK_SIZE; memset(wbuf, 0, SSHKEY_BLOCK_SIZE); fseek(fp, r, SEEK_SET); count = fread(wbuf+3, 1, i_size, fp); if (count != i_size) { lprintf(LOG_ERR, "Unable to read %d bytes from file %s", i_size, ifile); fclose(fp); return -1; } printf("."); fflush(stdout); wbuf[0] = uid; if ((r + SSHKEY_BLOCK_SIZE) >= f_size) wbuf[1] = 0xff; else wbuf[1] = (uint8_t)(r / SSHKEY_BLOCK_SIZE); wbuf[2] = (uint8_t)i_size; req.msg.data_len = i_size + 3; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { lprintf(LOG_ERR, "Unable to set ssh key for UID %d", uid); break; } } printf("done\n"); fclose(fp); return rv; } int ipmi_sunoem_main(void * intf, int argc, char ** argv) { int rc = 0; if (argc == 0 || strncmp(argv[0], "help", 4) == 0) { ipmi_sunoem_usage(); return 0; } if (strncmp(argv[0], "fan", 3) == 0) { uint8_t pct; if (argc < 2) { ipmi_sunoem_usage(); return -1; } else if (strncmp(argv[1], "speed", 5) == 0) { if (argc < 3) { ipmi_sunoem_usage(); return -1; } pct = atob(argv[2]); rc = ipmi_sunoem_fan_speed(intf, pct); } else { ipmi_sunoem_usage(); return -1; } } if ((strncmp(argv[0], "led", 3) == 0) || (strncmp(argv[0], "sbled", 5) == 0)) { if (argc < 2) { ipmi_sunoem_usage(); return -1; } if (strncmp(argv[0], "sbled", 5) == 0) { is_sbcmd = 1; } if (strncmp(argv[1], "get", 3) == 0) { if (argc < 3) { char * arg[] = { "all" }; rc = ipmi_sunoem_led_get(intf, 1, arg); } else { rc = ipmi_sunoem_led_get(intf, argc-2, &(argv[2])); } } else if (strncmp(argv[1], "set", 3) == 0) { if (argc < 4) { ipmi_sunoem_usage(); return -1; } rc = ipmi_sunoem_led_set(intf, argc-2, &(argv[2])); } else { ipmi_sunoem_usage(); return -1; } } if (strncmp(argv[0], "sshkey", 6) == 0) { uint8_t uid = 0; unsigned long l; if (argc < 2) { ipmi_sunoem_usage(); return -1; } else if (strncmp(argv[1], "del", 3) == 0) { if (argc < 3) { ipmi_sunoem_usage(); return -1; } l = strtoul(argv[2], NULL, 0); if ((l == ULONG_MAX) || (l > UCHAR_MAX)) { printf("param %s is out of bounds\n",argv[2]); return -17; /*ERR_BAD_PARAM*/ } uid = (uint8_t)l; rc = ipmi_sunoem_sshkey_del(intf, uid); } else if (strncmp(argv[1], "set", 3) == 0) { if (argc < 4) { ipmi_sunoem_usage(); return -1; } l = strtoul(argv[2], NULL, 0); if ((l == ULONG_MAX) || (l > UCHAR_MAX)) { printf("param %s is out of bounds\n",argv[2]); return -17; /*ERR_BAD_PARAM*/ } uid = (uint8_t)l; rc = ipmi_sunoem_sshkey_set(intf, uid, argv[3]); } } return rc; } int decode_sensor_sun(uchar *sdr,uchar *reading,char *pstring, int slen) { int rv = -1; uchar stype; char *pstr = NULL; if (sdr == NULL || reading == NULL) return(rv); if (pstring == NULL || slen == 0) return(rv); /* sdr[3] is the SDR type: 02=Compact, 01=Full) */ /* Usually compact sensors here, but type 0xC0 is a full sensor */ stype = sdr[12]; switch(stype) { case 0x15: /* Module/Board State sensor (e.g. BL0/STATE) */ if ((reading[1] + reading[2]) == 0) pstr = "NotAvailable"; else if (reading[2] & 0x01) pstr = "OK"; /*deasserted/OK*/ else pstr = "Asserted"; /*Asserted, error*/ rv = 0; break; case 0xC0: /* Blade Error sensor (e.g. BL0/ERR, a Full SDR) */ if ((reading[1] + reading[2]) == 0) pstr = "NotAvailable"; else if (reading[2] & 0x01) pstr = "OK"; /*deasserted/OK*/ else pstr = "Asserted"; /*Asserted, error*/ rv = 0; break; default: break; } if (rv == 0) strncpy(pstring, pstr, slen); return(rv); } #ifdef METACOMMAND int i_sunoem(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { void *intf = NULL; int rc = 0; int c, i; char *s1; uchar devrec[16]; printf("%s ver %s\n", progname,progver); set_loglevel(LOG_NOTICE); while ( (c = getopt( argc, argv,"m:T:V:J:EYF:P:N:R:U:Z:x?")) != EOF ) switch (c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'x': fdebug = 1; verbose = 1; set_debug(); break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; case '?': ipmi_sunoem_usage(); return 0; break; } for (i = 0; i < optind; i++) { argv++; argc--; } rc = ipmi_getdeviceid( devrec, sizeof(devrec),fdebug); if (rc == 0) { char ipmi_maj, ipmi_min; ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16); prod_id = devrec[9] + (devrec[10] << 8); show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); rc = ipmi_sunoem_main(intf, argc, argv); } ipmi_close_(); // show_outcome(progname,rc); return rc; } ipmiutil-3.1.5/util/iseltime.c0000644000076400007640000002123413566765324016414 0ustar mgportalloggers/* * iseltime.c * * Author: Andy Cress arcress at users.sourceforge.net * * 05/11/09 Andy Cress v1.0 - created * 07/23/10 Andy Cress v1.1 - always show System time also * 08/20/10 Andy Cress v1.2 - show/set RTC time also if Linux * 03/16/17 Andy Cress 3.03 - show/set UTC offset also */ /*M* Copyright (c) 2013, Andy Cress All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ #ifdef WIN32 #include #include #include "getopt.h" #elif defined(EFI) // EFI: defined (EFI32) || defined (EFI64) || defined(EFIX64) #ifndef NULL #define NULL 0 #endif #include #include #include #include #elif defined(DOS) #include #include #include #include #include "getopt.h" #else /* Linux, Solaris, BSD */ #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include #include #include "ipmicmd.h" #define GET_SELTIME 0x48 #define SET_SELTIME 0x49 #define GET_SELUTC 0x5C #define SET_SELUTC 0x5D /* * Global variables */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil seltime"; #else static char * progver = "3.08"; static char * progname = "iseltime"; #endif static char fdebug = 0; static char fset = 0; static uchar ipmi_maj = 0; static uchar ipmi_min = 0; static int get_sel_utc(uchar *rdata, int rlen) { uchar idata[4]; uchar ccode; int ret; ret = ipmi_cmdraw(GET_SELUTC, NETFN_STOR, BMC_SA, PUBLIC_BUS, BMC_LUN, idata, 0, rdata, &rlen, &ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; return(ret); } /*end get_sel_utc()*/ static int set_sel_utc(short offset) { uchar idata[4]; uchar rdata[16]; int rlen = 8; int ret; uchar ccode; idata[0] = (uchar)(offset & 0x00ff); idata[1] = (uchar)((offset >> 8) & 0x00ff); ret = ipmi_cmdraw(SET_SELUTC, NETFN_STOR, BMC_SA, PUBLIC_BUS, BMC_LUN, idata, 2, rdata, &rlen, &ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; return(ret); } /*end set_sel_utc()*/ static int get_sel_time(uchar *rdata, int rlen) { uchar idata[4]; uchar ccode; int ret; ret = ipmi_cmdraw(GET_SELTIME, NETFN_STOR, BMC_SA, PUBLIC_BUS, BMC_LUN, idata, 0, rdata, &rlen, &ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; return(ret); } /*end get_sel_time()*/ static int set_sel_time(time_t newtime) { uchar idata[4]; uchar rdata[16]; int rlen = 8; int ret; uchar ccode; idata[0] = (uchar)(newtime & 0x00ff); idata[1] = (uchar)((newtime >> 8) & 0x00ff); idata[2] = (uchar)((newtime >> 16) & 0x00ff); idata[3] = (uchar)((newtime >> 24) & 0x00ff); ret = ipmi_cmdraw(SET_SELTIME, NETFN_STOR, BMC_SA, PUBLIC_BUS, BMC_LUN, idata, 4, rdata, &rlen, &ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; return(ret); } /*end set_sel_time()*/ time_t utc2local(time_t t) { struct tm * tm_tmp; int gt_year,gt_yday,gt_hour,lt_year,lt_yday,lt_hour; int delta_hour; time_t lt; //modify UTC time to local time expressed in number of seconds from 1/1/70 0:0:0 1970 GMT // check for dst? tm_tmp=gmtime(&t); gt_year=tm_tmp->tm_year; gt_yday=tm_tmp->tm_yday; gt_hour=tm_tmp->tm_hour; tm_tmp=localtime(&t); lt_year=tm_tmp->tm_year; lt_yday=tm_tmp->tm_yday; lt_hour=tm_tmp->tm_hour; delta_hour=lt_hour - gt_hour; if ( (lt_year > gt_year) || ((lt_year == gt_year) && (lt_yday > gt_yday)) ) delta_hour += 24; if ( (lt_year < gt_year) || ((lt_year == gt_year) && (lt_yday < gt_yday)) ) delta_hour -= 24; if (fdebug) printf("utc2local: delta_hour = %d\n",delta_hour); lt = t + (delta_hour * 60 * 60); return(lt); } #define TIMESTR_SZ 30 void show_time(time_t etime, int doutc) { char buf[TIMESTR_SZ]; int bufsz = TIMESTR_SZ; time_t t; strcpy(buf,"00/00/00 00:00:00"); if (doutc) t = utc2local(etime); else t = etime; strftime(buf,bufsz, "%x %H:%M:%S", gmtime(&t)); /*or "%x %T"*/ printf("%s\n",buf); return; } #ifdef METACOMMAND int i_iseltime(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int rv = 0; uchar devrec[20]; uchar timebuf[4]; time_t ltime1, ltime2, ltime3; short offset; int c; #if defined (EFI) InitializeLib(_LIBC_EFIImageHandle, _LIBC_EFISystemTable); #else printf("%s ver %s\n", progname,progver); #endif while ( (c = getopt( argc, argv,"sT:V:J:EYF:P:N:R:U:x?")) != EOF ) switch(c) { case 's': fset = 1; break; /* read only */ case 'x': fdebug = 1; break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ parse_lan_options(c,optarg,fdebug); break; default: printf("Usage: %s [-sx -NUPRETVF]\n", progname); printf(" where -s Set SEL time (usually once a day)\n"); printf(" -x show eXtra debug messages\n"); print_lan_opt_usage(0); exit(1); } rv = ipmi_getdeviceid(devrec,16,fdebug); if (rv != 0) { show_outcome(progname,rv); ipmi_close_(); exit(rv); } else { ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; #ifndef EFI printf("-- BMC version %x.%x, IPMI version %d.%d \n", devrec[2], devrec[3], ipmi_maj, ipmi_min); #endif } offset = 0; rv = get_sel_utc((uchar *)&offset,2); if (fdebug) printf("get_sel_utc: ret=%x offset=%d\n",rv,offset); if (rv == 0) { /* TODO: get system UTC offset */ rv = set_sel_utc(offset); printf("set_sel_utc(%d): ret=%x\n",offset,rv); } rv = get_sel_time(&timebuf[0],4); if (rv != 0) { printf("get_sel_time error: ret = %x\n",rv); ipmi_close_(); exit(1); } time(<ime2); printf("Current System time: "); show_time(ltime2,1); ltime1 = timebuf[0] + (timebuf[1] << 8) + (timebuf[2] << 16) + (timebuf[3] << 24); printf("Current SEL time: "); show_time(ltime1,0); // if (fdebug) ltime3 = utc2local(ltime1); if (fset == 1) { /* get current time */ time(<ime2); rv = set_sel_time(ltime2); printf("Setting SEL time to System Time: ret = %x\n",rv); if (rv != 0) printf("set_sel_time error: ret = %x\n",rv); else { /*successful*/ rv = get_sel_time(timebuf,8); if (rv != 0) printf("get_sel_time error: ret = %x\n",rv); else { ltime3 = timebuf[0] + (timebuf[1] << 8) + (timebuf[2] << 16) + (timebuf[3] << 24); printf("New SEL time: "); show_time(ltime3,0); } } } #ifdef LINUX if (is_remote() == 0) { c = system("echo \"Current RTC time: `hwclock`\""); if (fset == 1) { c = system("hwclock --systohc"); printf("Copying System Time to RTC: ret = %d\n",c); } } #endif ipmi_close_(); show_outcome(progname,rv); exit (rv); } /* end main()*/ /* end iseltime.c */ ipmiutil-3.1.5/util/ipmilan.h0000644000076400007640000000760613566765324016246 0ustar mgportalloggers/*********************************************** * ipmilan.h * * Definitions and data structures for the * IPMI LAN interface * ***********************************************/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 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 Corporation 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. *----------------------------------------------------------------------*/ #ifndef IPMILAN_H_ #define IPMILAN_H_ #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 #endif #define SOL_HDR_LEN 30 /*SOL 1.5 HDR: 4(rmcp) + 9 + 1 + 5(sol) */ #define RQ_HDR_LEN 30 #define RQ_LEN_MAX 200 /*see IPMI_REQBUF_SIZE, was 25 */ #define RS_LEN_MAX 200 /*see IPMI_RSPBUF_SIZE */ /* Note that the send buffer is [RQ_LEN_MAX+RQ_HDR_LEN+7] = 62 */ /* Note that the receive buffer is [RS_LEN_MAX+RQ_HDR_LEN+7] = 237 */ #define SEND_BUF_SZ (RQ_LEN_MAX+RQ_HDR_LEN+7+8+8) /*RQ_LEN+53= 78*/ #define RECV_BUF_SZ (RS_LEN_MAX+RQ_HDR_LEN+7+8+8) /*RS_LEN+53=253*/ /* #define IPMI_LAN_SEQ_NUM_MAX 0x3F * only for gnulan */ #define RMCP_PRI_RMCP_PORT 0x26F #define PAYLOAD_TYPE_SOL 0x01 /* IPMI commands used for LAN sessions */ #define CMD_GET_CHAN_AUTH_CAP 0x38 #define CMD_GET_SESSION_CHALLENGE 0x39 #define CMD_ACTIVATE_SESSION 0x3A #define CMD_SET_SESSION_PRIV 0x3B #define CMD_CLOSE_SESSION 0x3C #define CMD_GET_MESSAGE 0x33 #define CMD_SEND_MESSAGE 0x34 /* see ipmicmd.h for LAN_ERR definitions */ int get_LastError( void ); void show_LastError(char *tag, int err); void ipmi_lan_set_timeout(int ipmito, int tries, int pingto); int ipmi_open_lan(char *node, int port, char *user, char *pswd, int fdebugcmd); int ipmi_close_lan(char *node); int ipmi_flush_lan(char *node); int ipmi_cmd_lan(char *node, ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); int ipmi_cmdraw_lan(char *node, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); int ipmicmd_lan(char *node, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); int ipmi_cmd_ipmb(uchar cmd, uchar netfn, uchar sa, uchar bus, uchar lun, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); #endif // IPMILAN_H_ ipmiutil-3.1.5/util/isol.c0000644000076400007640000012652213566765324015555 0ustar mgportalloggers/* * isol.c (was isolconsole.c) * IPMI Serial-Over-LAN console application * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2007 Intel Corporation * Copyright (c) 2009 Kontron America, Inc. * * 10/12/06 Andy Cress - created, just a framework for now * 02/08/07 Andy Cress - now working for IPMI LAN 2.0 SOL in Linux, * still stdio problems in Windows * 02/23/07 Andy Cress - fixed Windows stdin, still Windows output issues, * need more in xlate_vt100_win(). * 04/06/07 Andy Cress - more vt100-to-windows translation, * added -r for raw termio * 04/19/07 Andy Cress - more vt100-to-windows translation, * 05/08/07 Andy Cress - more logic for 1.5 SOL. Session opens but * 1.5 SOL data packets are not yet working. * 05/24/07 Andy Cress - Fix Enter key confusion in BIOS Setup (use CR+LF) * 06/15/07 Andy Cress - More fixes to Windows translation (fUseWinCon) * 08/20/07 Andy Cress - moved Windows translation to isolwin.c * See ChangeLog for further changes * * NOTE: There are a few other options for Serial-Over-LAN console * applications: * ipmitool.sf.net has v2 sol console capability for Linux (BSD) * Intel dpccli, a CLI console for Linux and Windows (proprietary) * Intel ISM console for Windows (proprietary) * Intel System Management Software (LANDesk) console, proprietary * The Intel applications support both IPMI 1.5 and 2.0 SOL * protocols. */ /*M* Copyright (c) 2007 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 Kontron 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*/ #if defined(DOS) #include #include #include #include #include "getopt.h" int i_sol(int argc, char **argv) { printf("IPMI SOL console is not supported under DOS.\n"); return(1); } #else /* All other OSs: Linux, Windows, Solaris, BSD */ #ifdef WIN32 #include #include #include #include #include #include "getopt.h" #else #include #include #include #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include #include #include "ipmicmd.h" #include "ipmilanplus.h" #define ACTIVATE_PAYLOAD 0x48 #define DEACTIVATE_PAYLOAD 0x49 #define PAYLOAD_TYPE_SOL 0x01 #define SOL_SERIAL_ALERT_MASK_DEFERRED 0x04 #define SOL_BMC_ASSERTS_CTS_MASK_TRUE 0x00 #define SOL_BMC_ASSERTS_CTS_MASK_FALSE 0x02 #define IPMI_PAYLOAD_TYPE_SOL 0x01 #define AUTHTYPE_RMCP_PLUS 0x06 #define RV_END -2 #define CH_CR '\r' /*0x0D =='\r'*/ #define CH_LF '\n' /*0x0A =='\n' LineFeed(Down) */ #define CH_ESC '\033' /*0x1B == ASCII Escape */ #define CH_CTL '\316' /*0xCE == VT100 Control */ #define CH_DEL '\177' /*0x7F == Delete key */ #define CH_BS '\010' /*0x08 == Backspace */ #define CH_TAB '\011' /*0x09 == Tab */ #define CH_UP '\013' /*0x0B == Up Arrow */ /* Input data buffer size: screen size (80*24) = 1920 */ /* IPMI_BUF_SIZE = 1024, less RMCP+IPMI hdr */ /* IDATA_SZ=2048 was too big, used =300 thru v2.1.0 */ #define IDATA_SZ 512 #define IPKT_SZ 512 #define MAX_INTEL_DATA 203 /*sol_send >= 204 bytes gives error w Intel BMC*/ #define MAX_DELL_DATA 46 /*sol_send >= 46 bytes gives error w Dell BMC*/ #define MAX_KONTRON_DATA 74 /*sol_send >= 75 bytes gives error w Kontron BMC*/ #define MAX_OTHER_DATA 45 /*use a small sol_send limit of 45 by default */ typedef struct { int type; int len; char *data; } SOL_RSP_PKT; extern void tty_setraw(int mode); /*from ipmicmd.c*/ extern void tty_setnormal(int mode); /*from ipmicmd.c*/ /* extern int tty_getattr(int *lflag,int *oflag,int *iflag); *from ipmicmd.c*/ extern SockType lan_get_fd(void); /*from ipmilan.c*/ extern int lan_send_sol( uchar *payload, int len, SOL_RSP_PKT *rsp); extern int lan_recv_sol( SOL_RSP_PKT *rsp ); extern int lan_keepalive(int type); extern void lan_get_sol_data(uchar fEnc, uchar iseed, uint32 *seed); extern void lan_set_sol_data(uchar fEnc, uchar auth, uchar iseed, int insize, int outsize); /* lan2 routines, from ipmilanplus.c, even if not HAVE_LANPLUS: */ extern int lan2_get_fd(void); /*from ipmilanplus.c*/ extern int lan2_send_sol( uchar *payload, int len, SOL_RSP_PKT *rsp); extern int lan2_recv_sol( SOL_RSP_PKT *rsp ); extern void lan2_set_sol_data(int in, int out, int port, void*hnd, char esc); extern int lan2_keepalive(int type, SOL_RSP_PKT *rsp); extern void lan2_recv_handler( void *rs ); extern long lan2_get_latency( void ); /*from ipmilanplus.c*/ extern void lanplus_set_recvdelay( int delay ); /*lib/lanplus/lanplus.c*/ extern int lan2_send_break( SOL_RSP_PKT *rsp ); extern char fdbglog; /*see ipmilanplus.c*/ extern char log_name[]; /*see ipmicmd.c*/ extern int is_lan2intel(int vend, int prod); /*see oem_intel.c*/ void dbglog( char *pattn, ... ); /*local prototype*/ /* * Global variables */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil sol"; #else static char * progver = "3.08"; static char * progname = "isol"; #endif static char fdebug = 0; static char fpicmg = 0; static char factivate = 0; static char fdeactivate = 0; static char fScript = 0; static char fTrace = 0; static char fprivset = 0; static char bDriver = 0; static uchar bSolVer = 0; static uchar bKeepAlive = 1; /*1=GetDeviceID, 2=empty SOL data*/ static char sol_esc_len = 2; /* SOL escape seq ("~.") */ static char sol_esc_ch = '~'; static char sol_esc_pending = 0; static char sol_esc_fn[4] = {'.','b','d', '?'}; /* SOL escape functions */ static char file_scr[80] = {""}; static char file_trc[80] = {""}; static char dbglog_name[40] = "isoldbg.log"; static FILE *fp_scr = NULL; static FILE *fp_trc = NULL; static uchar ipmi_maj = 0; static uchar ipmi_min = 0; static int vend_id = 0; /* Manufacturer IANA vendor id */ static int prod_id = 0; static uchar fSolEncryption = 1; static uchar fSolAuthentication = 1; static int sol_timeout = 30; /* default: send keepalive every 30 seconds */ static time_t keepalive_start; static int max_bmc_data = MAX_OTHER_DATA; static int fgotrecv = 0; static int fsentok = 0; static uchar payload_instance = 1; char fUseWinCon = 1; uchar fCRLF = 0; /* 0=use CR, 1=use legacy CR+LF, 2=use LF (like raw) */ uchar fRaw = 0; uchar bTextMode = 0; int sol_done = 0; int wait_time = 500; /*number of msec to wait*/ int retry_time = 5; /*number of msec between retries*/ static int sol_ver = 2; /*use IPMI 2.0 SOL by default*/ static int sol_retries = 1; /*send retries for sol_input_handler*/ static int sol_recvdelay = 0; /*if != 0, num us to delay before recv*/ static uchar sol15_iseed = 0x01; /*initial seed count, usu 0 or 1 */ static uint32 sol15_wseed = 0; /*32-bit seed value*/ static long lan2_latency = 0; /*lan2 latency in msec */ static long lan2_slow = 100; /*slow if latency > 100 msec */ extern FILE *fplog; /*see ipmicmd.c*/ #ifdef WIN32 /* these routines are in isolwin.c */ extern DWORD WINAPI input_thread( LPVOID lpParam); extern void console_open(char fdebugcmd); extern void console_close(void); extern void console_out(uchar *pdata, int len); extern int console_in(DWORD keydata, uchar *pdata, int len); extern int os_select(int infd, SockType sfd, fd_set *read_fds, fd_set *error_fds); extern int os_read(int fd, uchar *buf, int sz); extern void Ascii2KeyCode(uchar c, uchar *buf); #else /*======== start Linux ===============================*/ int os_read(int fd, uchar *buf, int sz) { int len = 0; len = read(fd, buf, sz); return(len); } int os_select(int infd, SockType sfd, fd_set *read_fds, fd_set *error_fds) { int rv = 0; struct timeval tv; /* Linux handles both stdin & socket via select() */ FD_ZERO(read_fds); FD_SET(infd, read_fds); FD_SET(sfd, read_fds); FD_ZERO(error_fds); FD_SET(sfd, error_fds); tv.tv_sec = 0; tv.tv_usec = wait_time * 1000; /* 500000 usec, 500 msec, 0.5 sec*/ rv = select((int)(sfd + 1), read_fds, NULL, error_fds, &tv); return rv; } void CheckTextMode(uchar *buffer, int sbuf) { int c, i, j, imatch; uchar pattern[5] = {CH_ESC,'[','0','0','m'}; /*was [0m */ int spattern = 5; /* if CH_ESC,"[0m", TextMode change */ j = 0; imatch = 0; for (j = 0; j < sbuf; j++) { if ((sbuf - j) < spattern && imatch == 0) break; c = buffer[j]; if (c == pattern[imatch]) { imatch++; } else if (pattern[imatch] == '?') { /*wildcard char*/ imatch++; } else if (pattern[imatch] == '0' && (c>='0' && c <='9')) { /*numeric*/ imatch++; } else { if (imatch > 0) { if (j > 0) j--; /* try again with the first match char */ imatch = 0; } } if (imatch == spattern) { /*match found*/ char mystr[5]; i = (j+1) - imatch; /*buffer[i] is the match */ // bTextMode = buffer[i+2] & 0x0f; /* usu 0 or 1 */ mystr[0] = buffer[i+2]; mystr[1] = buffer[i+3]; mystr[2] = 0; bTextMode = atob(mystr); dbglog("TextMode changed to %d\n",bTextMode); } else if (imatch > spattern) break; } return; } /*======== end Linux =================================*/ #endif void printm( char *pattn, ... ) { /* all sol error/info messages go to log or stderr by default */ va_list arglist; FILE *fp; if (fdbglog && fplog != NULL) fp = fplog; else fp = stderr; va_start(arglist, pattn); vfprintf(fp, pattn, arglist); va_end(arglist); fprintf(fp,"\r\n"); } void dbglog( char *pattn, ... ) { va_list arglist; int fadd = 0; int l; #ifdef WIN32 FILE *fp; // char _pattn[80]; if (fdebug == 0 && fdbglog == 0) return; if (fdbglog && fplog != NULL) fp = fplog; else fp = stderr; l = (int)strlen(pattn); if ((l >= 1) && (pattn[l-1] == '\n')) { /*check EOL chars*/ if (pattn[l-2] == '\r') fadd = 0; else fadd = 0; /* '\n' only */ // else _pattn[l-1] = 0; /*truncate, add \r\n below, dangerous*/ } else fadd = 1; /*no line-end, so add it below*/ va_start(arglist, pattn); vfprintf(fp, pattn, arglist); va_end(arglist); if (fadd) fprintf(fp,"\r\n"); #else char logtmp[LOG_MSG_LENGTH]; if (fdebug == 0 && fdbglog == 0) return; l = strlen(pattn); if ((l >= 1) && (pattn[l-1] == '\n')) fadd = 0; else fadd = 1; va_start( arglist, pattn ); vsnprintf(logtmp, LOG_MSG_LENGTH, pattn, arglist); va_end( arglist ); if (fadd) strcat(logtmp,"\n"); if (fdbglog) print_log(logtmp); else if (fdebug) fprintf( stderr, "%s", logtmp); #endif } void dbg_dump(char *tag, uchar *pdata, int len, int fascii) { FILE *fp = NULL; if (fdebug == 0 && fdbglog == 0) return; if (fdbglog && (fplog != NULL)) fp = fplog; dump_log(fp,tag,pdata,len,(char)fascii); /*uses fplog or fpdbg */ } #ifdef OLD static void set_latency( struct timeval *t1, struct timeval *t2, long *latency) { long nsec; nsec = t2->tv_sec - t1->tv_sec; if ((ulong)(nsec) > 1) nsec = 1; *latency = nsec*1000 + (t2->tv_usec - t1->tv_usec)/1000; } #endif static int sol_send(uchar *buf, int len, SOL_RSP_PKT *rsp) { int rv = 0; if (bSolVer == 1) { rv = lan_send_sol(buf, len, rsp); } else { rv = lan2_send_sol(buf, len, rsp); if (rv == 0x01) rv = 0; /* else bit-mapped error, 0x02 = need retry*/ } return(rv); } static int sol_recv( SOL_RSP_PKT *rsp) { int rv = 0; if (bSolVer == 1) { rv = lan_recv_sol( rsp ); } else rv = lan2_recv_sol( rsp ); return(rv); } static SockType sol_get_fd(void) { SockType fd = 0; if (bSolVer == 1) { fd = lan_get_fd(); } else fd = lan2_get_fd(); return(fd); } /* * sol_output_handler * This routine is called both in isol.c and ipmilanplus.c/lan2_recv_handler * whenever SOL data is received from the BMC for output to the console. */ void sol_output_handler(SOL_RSP_PKT *rsp) { if (rsp == NULL) return; if (rsp->type == PAYLOAD_TYPE_SOL) { #ifdef WIN32 fgotrecv = 1; if (fdbglog) dbg_dump("sol_output(console_out)",rsp->data,rsp->len,1); console_out(rsp->data,rsp->len); #else uchar *pdata; int len; int i; uchar c; // int mode; fgotrecv = 1; pdata = rsp->data; len = rsp->len; if (fdbglog) { // dbglog("sol_output: len = %d\n",len); dbg_dump("sol_output",pdata,len,1); /*like printlog*/ } CheckTextMode(pdata,len); for (i = 0; i < len; i++) { c = pdata[i]; /* do special character handling here? * CH_CR, 0xb0-0xb3, 0xdb */ putc(c, stdout); } fflush(stdout); #endif if (fTrace) { fwrite(rsp->data,1,rsp->len,fp_trc); fflush(fp_trc); } } else { dbglog("sol_output: rsp.type=%x, rsp.len=%d\n", rsp->type, rsp->len); } } static int sol_keepalive(int type) { int rv = 0; time_t end; time(&end); if (sol_timeout == 0) return(rv); if ((end - keepalive_start) > sol_timeout) { dbglog("sol_keepalive: timeout, lan%d\n",bSolVer); /*++++*/ if (bSolVer == 1) { rv = lan_keepalive(type); } else { SOL_RSP_PKT rs; rv = lan2_keepalive(type, &rs); if (rv >= 0 && rs.len != 0) { /*handle any rsp data*/ if (rs.type == IPMI_PAYLOAD_TYPE_SOL) { dbglog("keepalive: output_handler(%d)\n",rs.len); sol_output_handler(&rs); } } } time(&keepalive_start); /*time in seconds*/ dbglog("sol_keepalive sent, rv = %d\n",rv); flush_log(); } return(rv); } static void sol_keepalive_reset(void) { /* not idle, so reset the keepalive timer */ time(&keepalive_start); /*time in seconds*/ } static int send_break( void ) { SOL_RSP_PKT rs; int rv; if (sol_ver == 1) return LAN_ERR_NOTSUPPORT; rv = lan2_send_break(&rs); dbglog("lan2_send_break rv=%d rs.len=%d\n", rv,rs.len); return(rv); } static int send_ctlaltdel( void ) { uchar buf[8]; int rv, rlen; // #define TESTALT 1 #ifdef TESTALT SOL_RSP_PKT rs; /* This doesn't work. Fix it later. */ /* Problem is that keycodes must be translated for serial console */ /* CtrlL = 0x0706, AltL = 0x0703, Del = 0x007f, MetaDel = 0x087f * Del = keycode 0x53 * 1b 53 33 7e = alt+del * 1b 4f 48 = ctl-alt-home * 1b 4f 46 = ctl-alt-end * 1b 53 33 3b 38 7e = ctl+alt+shift+del * 1b 53 33 3b 33 7e = ctl+alt+ins * 1b 53 33 3b 35 7e = ctl+alt+ins * 1b 53 35 3b 37 7e = ctl+alt+pgup * 1b 53 36 3b 37 7e = ctl+alt+pgdn * Need to find a sequence at serial console that does a reboot * when the command prompt is not up. */ buf[0] = 0x1b; buf[1] = 0x53; buf[2] = 0x33; buf[3] = 0x3b; buf[4] = 0x36; buf[5] = 0x7e; rv = sol_send(buf, 6, &rs); rlen = rs.len; #else uchar rbuf[16]; uchar cc; rlen = sizeof(rbuf); buf[0] = 5; /*soft reset via ACPI */ rv = ipmi_cmdraw(CHASSIS_CTL,NETFN_CHAS,BMC_SA, PUBLIC_BUS, BMC_LUN, buf,1,rbuf,&rlen,&cc,fdebug); if (rv == 0 && cc != 0) rv = cc; #endif dbglog("send_ctlaltdel rv=%d rlen=%d\n", rv,rlen); return(rv); } static void show_esc_help( void ) { printf("%c?\r\n",sol_esc_ch); printf("Supported SOL escape sequences:\r\n"); printf("\t%c. - terminate connection\r\n",sol_esc_ch); printf("\t%cB - send break\r\n",sol_esc_ch); printf("\t%cD - send ctl-alt-delete (chassis soft reset)\r\n",sol_esc_ch); printf("\t%c? - show this help message\r\n",sol_esc_ch); printf("\t%c%c - send the escape character by typing it twice\r\n", sol_esc_ch, sol_esc_ch); } int sol_input_handler( uchar *input, int ilen) { int rv = 0; uchar payload[IPKT_SZ]; SOL_RSP_PKT rs; int i, length, t; static uchar lastc = 0; char rvend = 0; char fdoinput = 1; uchar c; #ifdef WIN32 uchar c1, c2, c3; unsigned long dwKeyCode; #endif memset(&payload, 0, sizeof(payload)); length = 0; rs.len = 0; if ((fdebug > 2) && (ilen > 4)) dbg_dump("sol_input dump:",input,ilen,1); // i = 0; for (i = 0; i < ilen; i++) { if (fdebug > 2) dbglog("sol_input keys[%d]: %02x %02x %02x %02x, ilen=%d\n", i, input[i], input[i+1], input[i+2], input[i+3], ilen); /* look for console escape sequences (~) */ if (sol_esc_pending) { sol_esc_pending = 0; /* next char in 2-char esc seq */ #ifdef WIN32 if ( ((input[i+3] & 0x01) == 0) || /* h.o byte, if not keydown */ (i < 0)) { /* skip h.o. bytes in dwChar for windows */ fdoinput = 0; /*skip this input*/ sol_esc_pending = 1; /*if here, esc was pending*/ if (fdebug > 2) dbglog("sol_input: skip, %02x!=X1 for i=%d\n",input[i+3],i); } else #endif switch(input[i]) { case '.': dbglog("sol_input RV_END (%02x %02x)\n",sol_esc_ch,input[i]); rvend = 1; fdoinput = 0; break; case 'b': case 'B': rv = send_break(); fdoinput = 0; break; case 'd': case 'D': rv = send_ctlaltdel(); fdoinput = 0; break; case '?': show_esc_help(); fdoinput = 0; break; default: /* includes entering "~~" to output '~' */ dbglog("sol_input sol_esc no match (%02x %02x/%c%c)\n", sol_esc_ch,input[i], sol_esc_ch,input[i]); fdoinput = 1; break; } } else if (input[i] == sol_esc_ch) { /* start of new sol_esc seq */ if (fdebug > 2) dbglog("sol_input esc_pending (%02x %02x)\n",input[i],input[i+1]); if ((sol_esc_len == 1) || ((ilen > (i+1)) && (input[i+1] == '.')) ) { /*then exit now*/ dbglog("sol_input RV_END (%02x %02x)\n",input[i],input[i+1]); rvend = 1; } fdoinput = 0; sol_esc_pending = 1; } else fdoinput = 1; /*send as normal input*/ if (fdoinput) { c = input[i]; #ifdef WIN32 c1 = input[i+1]; c2 = input[i+2]; c3 = input[i+3]; dwKeyCode = (c << 24) | (c1 << 16) | (c2 << 8) | c3; dbglog("sol_input[%d]: KeyCode=0x%08X, '%c'\n", i, dwKeyCode, (0x20 <= c && c <= 0x7E ? c : '.') ); /* check Windows input to see if it should be sent */ t = console_in(dwKeyCode, &payload[length], sizeof(payload) - length); if (t > 0) length += t; lastc = c; #else /* * Linux end-of-line handling with fCRLF: * (0) CR, (1) CR+LF, (2) LF * Note that the CR+LF logic works for BIOS, but causes * extra returns after Linux commands. Using -l sets CR+LF. * Using bTextMode detects if bg color, as in BIOS Setup * or other apps that need CR+LF. * * If stty has '-onlcr', then LF (fCRLF=2) is fine, but * if stty has 'onlcr', LF causes two output lines, * so CR is the default (fCRLF=0), which works for * either 'onlcr' or '-onlcr'. * Using -r (fRaw) has the same effect as LF (fCRLF=2). */ if (c == CH_LF && !fRaw) { // input=enter/LF and not raw (-r) if ((fCRLF == 1) || (bTextMode > 40)) { /*-l option or bg color*/ /*CR+LF: insert CR here, LF below*/ payload[length++] = CH_CR; } else if (fCRLF == 2) ; /*LF: same as raw, use CH_LF*/ else c = CH_CR; /* CR: switch LF to CR */ } /* copy other data to payload */ payload[length++] = c; lastc = c; if (c == CH_CR || c == CH_LF) dbglog("sol_input[%d] payload: %02x %02x, bTextMode=%d\n", i,payload[0],payload[1],bTextMode); #endif if (length >= max_bmc_data) { /*overflow, truncate*/ dbglog("sol_send: ilen(%d) >= BMC max data(%d), truncated\n", ilen,max_bmc_data); break; } else if (length >= sizeof(payload)) { /*overflow, truncate*/ dbglog("sol_send: ilen(%d) >= buffer size(%d), truncated\n", ilen,sizeof(payload)); break; } } /*endif fdoinput*/ #ifdef WIN32 i += 3; /*increment to next dwKeyCode (3+1)*/ #endif } /*end-for input[ilen] */ if (length > 0) { /* Send the SOL payload */ for (t = 0; t < sol_retries; t++) { if (t > 0) os_usleep(0,(retry_time * 1000)); /*wait between retries 5000 us*/ rv = sol_send(payload, length, &rs); dbglog("sol_send(%d,%d) rv=%d rs.len=%d\n", t,length,rv,rs.len); if (rv >= 0) { /* rv ok */ if (rs.len != 0) { /* have some rsp data, so handle it */ if (rs.type == IPMI_PAYLOAD_TYPE_SOL) { dbglog("output: handler(%d)\n",rs.len); sol_output_handler(&rs); } else { dbglog("WARNING: after sol_send, rs.type=%d, not SOL\n",rs.type); } } /*endif have rsp data*/ rv = 0; /*recvd something, so dont retry */ } if (rv == 0) break; /* else retry again if rv < 0 or rv == 0x02 */ } /*end for loop*/ if (rv < 0) rv = LAN_ERR_DROPPED; } if (rvend) rv = RV_END; return(rv); } static int send_activate_15sol(void) { int rv = 0; uchar actcmd; uchar netfn; uchar ibuf[64]; uchar rbuf[64]; int rlen; uchar ilen, cc; lan_get_sol_data(fSolEncryption,sol15_iseed,&sol15_wseed); actcmd = (uchar)(ACTIVATE_SOL1 & 0x00ff); netfn = NETFN_SOL; if (fSolEncryption) ibuf[0] = 0x11; /* use encryption, activate SOL */ else ibuf[0] = 0x01; /*no encryptionn, no serial alerts, activate SOL */ memcpy(&ibuf[1],&sol15_wseed,4); /*32-bit seed*/ ilen = 5; rlen = sizeof(rbuf); rv = ipmi_cmdraw(actcmd,netfn,BMC_SA, PUBLIC_BUS, BMC_LUN, ibuf,ilen,rbuf,&rlen,&cc,fdebug); if (rv == 0 && cc != 0) rv = cc; /* switch(cc) { case 0x80: SOL already active on another session * case 0x81: SOL disabled * case 0x82: SOL activation limit reached } */ if (rv == 0) { /*success*/ dbg_dump("sol 15 act_resp",rbuf,rlen,0); /* sol 15 act_resp (len=4): 0000: 00 01 64 64 */ /* 00=auth, 01=seed_cnt, 64=in_payload_sz, 64=out_payload_sz */ lan_set_sol_data(fSolEncryption,rbuf[0],rbuf[1], rbuf[2], rbuf[3]); } return(rv); } static int send_deactivate_15sol(void) { int rv = -1; uchar actcmd; uchar netfn; uchar ibuf[64]; uchar rbuf[64]; int rlen; uchar ilen, cc; /* SOL for IPMI 1.5 does not have an explicit deactivate, so * use an activate with data0 = 00. */ actcmd = (uchar)(ACTIVATE_SOL1 & 0x00ff); netfn = NETFN_SOL; if (fSolEncryption) ibuf[0] = 0x10; /* deactivate, use encryption */ else ibuf[0] = 0x00; /*deactivate*/ memcpy(&ibuf[1],&sol15_wseed,4); /*32-bit seed*/ ilen = 5; rlen = sizeof(rbuf); rv = ipmi_cmdraw(actcmd,netfn,BMC_SA, PUBLIC_BUS, BMC_LUN, ibuf,ilen,rbuf,&rlen,&cc,fdebug); if (rv == 0 && cc != 0) rv = cc; dbg_dump("sol 15 deact_resp",rbuf,rlen,0); /* 80 00 32 ff */ return(rv); } int send_activate_sol(uchar verSOL) { int rv = 0; int in_payload_size, out_payload_size, udp_port; uchar actcmd; uchar netfn; uchar ibuf[64]; uchar rbuf[64]; int rlen; uchar ilen, cc; sol_ver = verSOL; /* activate SOL = 0x01, get SOL status = 0x05 */ if (verSOL == 1) { rv = send_activate_15sol(); return(rv); } else { /* use IPMI 2.0 method */ actcmd = ACTIVATE_PAYLOAD; netfn = NETFN_APP; ibuf[0] = PAYLOAD_TYPE_SOL; ibuf[1] = payload_instance; /* payload instance */ ibuf[2] = SOL_SERIAL_ALERT_MASK_DEFERRED; if (fSolEncryption) ibuf[2] |= 0x80; if (fSolAuthentication) ibuf[2] |= 0x40; if (vend_id == VENDOR_INTEL) ibuf[2] |= SOL_BMC_ASSERTS_CTS_MASK_TRUE; else ibuf[2] |= SOL_BMC_ASSERTS_CTS_MASK_FALSE; ibuf[3] = 0; ibuf[4] = 0; ibuf[5] = 0; ilen = 6; } rlen = sizeof(rbuf); rv = ipmi_cmdraw(actcmd,netfn,BMC_SA, PUBLIC_BUS, BMC_LUN, ibuf,ilen,rbuf,&rlen,&cc,fdebug); dbg_dump("sol act_cmd",ibuf,ilen,0); dbglog("send_activate v2(%x,%x) rv = %d cc = %x\n",actcmd,netfn,rv,cc); if (rv >= 0) { rv = cc; switch(cc) { case 0x00: if (rlen != 12) { printm("Unexpected SOL response data received, len=%d\n",rlen); rv = -1; } break; case 0x80: printm("SOL payload already active on another session\n"); break; case 0x81: printm("SOL payload disabled\n"); break; case 0x82: printm("SOL payload activation limit reached\n"); break; case 0x83: printm("Cannot activate SOL payload with encryption\n"); break; case 0x84: printm("Cannot activate SOL payload without encryption\n"); break; default: printm("Cannot activate SOL, ccode = 0x%02x\n",cc); break; } } if (rv == 0) { /* success, use the response data */ /* only here if response data is from IPMI 2.0 method */ dbg_dump("sol act_resp",rbuf,rlen,0); in_payload_size = rbuf[4] + (rbuf[5] << 8); out_payload_size = rbuf[6] + (rbuf[7] << 8); udp_port = rbuf[8] + (rbuf[9] << 8); dbglog("activate ok, in=%d out=%d port=%d\n", in_payload_size, out_payload_size, udp_port); if (bSolVer == 2) lan2_set_sol_data(in_payload_size, out_payload_size, udp_port, (void *)lan2_recv_handler, sol_esc_ch); } return(rv); } int send_deactivate_sol(uchar verSOL) { int rv = 0; uchar deactcmd; uchar netfn; uchar ibuf[64]; uchar rbuf[64]; int rlen; uchar ilen, cc; if (verSOL == 1) { return(send_deactivate_15sol()); } else { /* use IPMI 2.0 method */ deactcmd = DEACTIVATE_PAYLOAD; netfn = NETFN_APP; ibuf[0] = PAYLOAD_TYPE_SOL; /* payload type */ ibuf[1] = payload_instance; /* payload instance */ ibuf[2] = 0; ibuf[3] = 0; ibuf[4] = 0; ibuf[5] = 0; ilen = 6; } rlen = sizeof(rbuf); rv = ipmi_cmdraw(deactcmd,netfn,BMC_SA, PUBLIC_BUS, BMC_LUN, ibuf,ilen,rbuf,&rlen,&cc,fdebug); dbglog("sol deactivate rv = %d, cc = %x\n",rv,cc); if (rv == 0 && cc != 0) rv = cc; return(rv); } int sol_data_loop( void ) { int istdin; int rv = 0; uchar ibuf[IDATA_SZ]; uchar cbuf[IDATA_SZ]; int szibuf, szcbuf; SockType fd; int len; fd_set read_fds; fd_set error_fds; static uchar lastc = 0; int c; #ifdef WIN32 int c1; time_t ltime1 = 0; time_t ltime2 = 0; HANDLE thnd; istdin = 0; #else long ltime1 = 0; long ltime2 = 0; istdin = fileno(stdin); #endif /* * OK, now loop and listen to * stdin for user input * interface fd for incoming SOL data */ /* sizeof(ibuf/cbuf)=IDATA_SZ(512), max_bmc_data=203 for sol data */ szibuf = max_bmc_data; szcbuf = max_bmc_data; fd = sol_get_fd(); if (fScript) { /* open file_scr */ fp_scr = fopen(file_scr,"r"); if (fp_scr == NULL) { printm("Cannot open %s, ignoring\n",file_scr); fScript = 0; } } if (fTrace) { /* open file_trc for writing */ fp_trc = fopen(file_trc,"a"); if (fp_trc == NULL) { printm("Cannot open %s, ignoring\n",file_trc); fTrace = 0; } } dbglog("stdin = %d, intf->fd = %d\n",istdin,fd); if (sol_esc_len == 1) printf("[SOL session is running, use '%c' to end session.]\n",sol_esc_ch); else printf("[SOL session is running, use '%c.' to end, '%c?' for help.]\n", sol_esc_ch, sol_esc_ch); tty_setraw(2); sol_keepalive_reset(); #ifdef WIN32 thnd = CreateThread(NULL, 0, &input_thread, NULL, 0, NULL); if (thnd == NULL) { printm("CreateThread error, aborting\n"); rv = -1; sol_done = 1; } console_open(fdebug); #else if (bSolVer == 1) { /* jump start the session v1.5 data */ ibuf[0] = 0x1b; /*escape*/ ibuf[1] = '{'; rv = sol_input_handler(ibuf,2); } #endif if (fdbglog) time((time_t *)<ime1); while (sol_done == 0) { if (bKeepAlive > 0) { /* send KeepAlive if needed */ rv = sol_keepalive(bKeepAlive); /* if keepalive error, try to keep going anyway */ } if (fdebug > 2) dbglog("os_select(%d,%d) called\n",istdin,fd); rv = os_select(istdin,fd, &read_fds, &error_fds); if (rv < 0) { dbglog("os_select(%d,%d) error %d\n",istdin,fd,rv); perror("select"); sol_done = 1; } else if (rv > 0) { if (fdbglog) { time((time_t *)<ime2); dbglog("select rv = %d sockfd=%x stdin=%x time=%ld\n", rv, FD_ISSET(fd, &read_fds),FD_ISSET(istdin, &read_fds), (ltime2 - ltime1)); } if (FD_ISSET(fd, &read_fds)) { SOL_RSP_PKT rs; rs.len = 0; /* receive output from BMC SOL */ rv = sol_recv(&rs); #ifdef WIN32 /* Windows sometimes gets rv = -1 here */ if (rv == -1) rv = -(WSAGetLastError()); #endif dbglog("output: recv rv = %d, len = %d\n",rv,rs.len); if (rv < 0) { dbglog("Error %d reading SOL socket\n",rv); printm("Error %d reading SOL socket\n",rv); sol_done = 1; } else { /*sol_output_handler sets fgotrecv*/ sol_output_handler(&rs); sol_keepalive_reset(); /* go back to select until there is no more socket data */ continue; } } /*endif fd*/ if (FD_ISSET(fd, &error_fds)) { dbglog("Error selecting SOL socket\n",rv); } /*endif fd*/ if (FD_ISSET(istdin, &read_fds)) { /* input from stdin (user) if not WIN32 */ memset(ibuf,0,szibuf); len = os_read(istdin, ibuf, szibuf); dbglog("stdin: read len=%d, %02x %02x %02x %02x\n", len,ibuf[0],ibuf[1],ibuf[2],ibuf[3]); if (len <= 0) { dbglog("Error %d reading stdin\n",len); printm("Error %d reading stdin\n",len); sol_done = 1; } else { rv = sol_input_handler(ibuf,len); dbglog("sol_input: handler rv = %d\n",rv); if (rv < 0) { sol_done = 1; if (rv == RV_END) { dbglog("sol_data RV_END\n"); printf("\n%s exit via user input \n",progname); } /* else drop through to show_outcomes */ } else sol_keepalive_reset(); } } /*endif stdin*/ } /*endif select rv > 0 */ else if (fScript) { /*rv == 0*/ /* if we sent a script line, but no receive yet, keep waiting*/ if (fsentok && (fgotrecv == 0)) { dbglog("sol_data script sentok, but no recv\n"); // continue; } fsentok = 0; /* read input stream from script file */ memset(cbuf,0,szcbuf); /* read one line at a time */ rv = 0; for (len = 0; len < szcbuf; ) { c = fgetc(fp_scr); if (c == EOF) { rv = -2; break; } #ifdef WIN32 if ((c == '\n') && (lastc != '\r')) c1 = '\r'; /*Enter*/ else c1 = c; Ascii2KeyCode((uchar)c1,&cbuf[len]); len += 4; #else cbuf[len++] = c; #endif if (c == '\n') break; lastc = (uchar)c; } dbglog("script: read len=%d, %02x %02x %02x\n", len,cbuf[0],cbuf[1],cbuf[2]); if (rv != 0 || len == 0) { dbglog("Stop reading file %s, rv=%d\n",file_scr,rv); fclose(fp_scr); fScript = 0; } else { /* TODO: add processing for some wait/sleep/prompt commands */ rv = sol_input_handler(cbuf,len); dbglog("input: handler rv = %d\n",rv); if (rv < 0) { sol_done = 1; if (rv == RV_END) { dbglog("sol_data RV_END\n"); printf("\n%s exit via user input \n",progname); } else printf("Error %d processing input\n",rv); } else { fsentok = 1; /*sent a script line successfully*/ fgotrecv = 0; /*need to wait for recv*/ } } } /*endif fScript*/ } /*end while*/ if (rv == RV_END) rv = 0; #ifdef WIN32 os_usleep(0,5000); /*wait 5 ms for thread to close itself*/ CloseHandle(thnd); console_close(); #endif tty_setnormal(2); if (fScript) fclose(fp_scr); /* close file_scr */ if (fTrace) fclose(fp_trc); /* close file_trc */ return(rv); } static void show_usage(void) { printf("Usage: %s [-acdeiolnrsvxz -NUPREFTVY]\n", progname); printf(" where -a activate SOL console session\n"); printf(" -d deactivate SOL console session\n"); printf(" -c'^' set escape Char to '^', default='~'\n"); printf(" -e Encryption off for SOL session\n"); printf(" -i file Input script file\n"); printf(" -o file Output trace file\n"); printf(" -l Legacy mode for BIOS/DOS CR+LF\n"); printf(" -n 1 Payload instance Number, default=1\n"); printf(" -r Raw termio, no VT-ANSI translation\n"); printf(" -s NNN Slow link delay, default=100usec\n"); #ifdef NOT_DOCUMENTED printf(" -t N SOL send timeout reTries, default=1\n"); printf(" -u N Wait time in msec for tuning, default=500\n"); #endif #ifdef WIN32 printf(" -w do not use Windows Console buffer, use stdio\n"); #endif printf(" -v debug log filename (default=isoldbg.log)\n"); printf(" -x show eXtra debug messages in debug log\n"); printf(" -z show even more debug messages\n"); print_lan_opt_usage(1); } #ifdef METACOMMAND int i_sol(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int ret = 0; int i; uchar devrec[16]; uchar bmcver[2]; int c; printf("%s ver %s\n", progname,progver); parse_lan_options('V',"2",0); /*default to user priv*/ while ( (c = getopt( argc, argv,"ac:dei:k:ln:o:p:rs:t:u:wv:xzEF:J:N:P:R:T:U:V:YZ:?")) != EOF ) switch(c) { case 'a': factivate = 1; break; /*activate*/ case 'd': fdeactivate = 1; break; /*deactivate*/ case 'c': /* escape char */ if (strncmp(optarg,"0x",2) == 0) sol_esc_ch = htoi(&optarg[2]); /*hex char value*/ else if (optarg[0] >= '0' && optarg[0] <= '9') sol_esc_ch = atob(optarg); /*decimal char value*/ else sol_esc_ch = optarg[0]; /*single ascii char*/ sol_esc_len = 1; /*set single-char esc sequence */ break; case 'e': fSolEncryption = 0; break; /*encryption off*/ case 'k': i = atoi(optarg); /*sol keepalive timeout, default = 30*/ if (i < 0) printf("Invalid keepalive timeout %d, ignoring.\n",i); else sol_timeout = i; if (i == 0) bKeepAlive = 0; if (i == 32) bKeepAlive = 2; /*++++ for debug*/ break; case 'l': fCRLF = 1; break; /*do legacy CR+LF translation*/ case 'i': strncpy(file_scr,optarg,sizeof(file_scr)); fScript = 1; break; /*script input file*/ case 'n': i = atoi(optarg); /* payload_instance */ if ((i <= 0) || (i > 255)) printf("Invalid payload instance %d, ignoring.\n",i); else payload_instance = i; break; case 'o': strncpy(file_trc,optarg,sizeof(file_trc)); fTrace = 1; break; /*trace output file*/ case 'r': fRaw = 1; fCRLF = 0; fUseWinCon = 0; break; /*raw termio, xlate off*/ case 's': sol_recvdelay = atoi(optarg); break; /*slow recv delay*/ case 't': sol_retries = atoi(optarg); break; /*timeout/retries*/ case 'u': wait_time = atoi(optarg); break; /*wait_time for tuning*/ case 'v': strncpy(dbglog_name,optarg,sizeof(dbglog_name)); fdbglog = 1; break; /*name of debug log file*/ case 'w': fUseWinCon = 0; break; /*do not use Console routines*/ case 'x': if (fdebug == 0) fdebug = 2; /*only normal via dbglog */ else fdebug++; /* -xx = full, -xxx = max */ break; case 'z': fdebug = 3; break; /*full debug messages */ case 'V': /* priv level */ fprivset = 1; case 'p': /* port */ 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: show_usage(); ret = ERR_USAGE; goto do_exit; } if (is_remote() == 0) { /* no node specified */ printf("Serial-Over-Lan Console requires a -N nodename\n"); ret = ERR_BAD_PARAM; goto do_exit; } if (fdeactivate && !fprivset) parse_lan_options('V',"4",0); /*deactivate requires admin priv */ /* fdebug: 1=debug/no packets, 2=debug log only, 3=full debug, 4=max debug*/ if (fdebug > 1) fdbglog = 1; if (factivate == 0 && fdeactivate == 0) { show_usage(); printf("Error: Need either -a or -d for sol\n"); ret = ERR_BAD_PARAM; goto do_exit; } #ifdef WIN32 else if (factivate) { if (fdebug) printf("%s activate, connecting ...\n", progname); } #endif if (fdbglog) { // strcpy(log_name,dbglog_name); open_log(dbglog_name); dbglog("%s ver %s\r\n", progname,progver); } i = get_driver_type(); /*see if user explictly set type*/ if (i == DRV_UNKNOWN) bDriver = DRV_UNKNOWN; /*no driver type specified*/ else bDriver = (uchar)i; ret = ipmi_getdeviceid(devrec,16,fdebug); if (ret != 0) { goto do_exit; } else { ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16); prod_id = devrec[9] + (devrec[10] << 8); show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); bmcver[0] = devrec[2]; bmcver[1] = devrec[3]; switch(vend_id) { case VENDOR_DELL: /*Dell == 0x0002A2*/ max_bmc_data = MAX_DELL_DATA; /*shorter max data*/ break; case VENDOR_SUPERMICROX: case VENDOR_SUPERMICRO: if (!fprivset) parse_lan_options('V',"4",0); /*requires admin priv*/ case VENDOR_LMC: case VENDOR_PEPPERCON: /* 0x0028C5 Peppercon/Raritan*/ sol_timeout = 10; /* shorter 10 sec SOL keepalive timeout */ max_bmc_data = MAX_OTHER_DATA; break; case VENDOR_INTEL: max_bmc_data = MAX_INTEL_DATA; break; case VENDOR_KONTRON: max_bmc_data = MAX_KONTRON_DATA; // bKeepAlive = 1; break; default: max_bmc_data = MAX_OTHER_DATA; break; } } ret = ipmi_getpicmg(devrec,16,fdebug); if (ret == 0) fpicmg = 1; dbglog("driver=%d fdebug=%d vend_id=%x bmcver=%x.%x ipmi %d.%d\n", bDriver,fdebug,vend_id,bmcver[0],bmcver[1],ipmi_maj,ipmi_min); /* check for SOL support */ if (ipmi_maj >= 2) { if ((bDriver == DRV_LAN) && (vend_id == VENDOR_INTEL)) { /* user specified to use IPMI LAN 1.5 SOL on Intel */ bSolVer = 1; /*IPMI 1.5 SOL*/ } else { bSolVer = 2; /*IPMI 2.0 SOL*/ if (get_driver_type() == DRV_LAN) { /*now using IPMI LAN 1.5*/ char *ptyp; ipmi_close_(); /*close current IPMI LAN 1.5*/ if (is_lan2intel(vend_id,prod_id)) ptyp = "lan2i"; else ptyp = "lan2"; i = set_driver_type(ptyp); /*switch to IPMI LAN 2.0*/ } } } else if (ipmi_maj == 1) { if (ipmi_min >= 5) bSolVer = 1; /* IPMI 1.5 */ else bSolVer = 0; /* IPMI 1.0 */ } else bSolVer = 0; if (bSolVer == 0) { printf("Serial Over Lan not supported for this IPMI version\n"); ret = LAN_ERR_NOTSUPPORT; goto do_exit; } #ifndef HAVE_LANPLUS if (bSolVer == 2) { printf("2.0 LanPlus module not available, trying 1.5 SOL instead\n"); bSolVer = 1; } #endif /* May also want to verify that SOL is implemented here */ /* * Spawn a console raw terminal thread now, which will wait for the * "Activating cmd (0x02)" on success */ if (fdeactivate) { /* Request admin privilege by default, since deactivate requires it. */ ret = send_deactivate_sol(bSolVer); dbglog("send_deactivate_sol rv = %d\n",ret); } else if (factivate) { ret = send_activate_sol(bSolVer); dbglog("send_activate_sol(%d) rv = %d\n",bSolVer,ret); if (bSolVer == 2) { lan2_latency = lan2_get_latency(); retry_time = lan2_latency; dbglog("lan2_latency = %ld msec (slow > %ld msec)\n", lan2_latency,lan2_slow); if ((sol_recvdelay == 0) && (lan2_latency > lan2_slow)) sol_recvdelay = 500; /* it is slow, set recvdelay */ if (sol_recvdelay != 0) { dbglog("set_recvdelay to %dus\n",sol_recvdelay); lanplus_set_recvdelay(sol_recvdelay); } } /*endif bSolVer==2*/ if (ret == 0) { ret = sol_data_loop(); } /*endif activate ok*/ } /*endif do activate */ do_exit: if (ret != LAN_ERR_DROPPED) { /*if link dropped, no need to close*/ ipmi_close_(); os_usleep(0,(wait_time * 1000)); /*wait 0.5 sec for BMC teardown*/ } if (fdebug) show_outcome(progname,ret); if (fdbglog) close_log(); return(ret); } /* end main()*/ #endif /* end isol.c */ ipmiutil-3.1.5/util/itsol.h0000644000076400007640000000500413566765324015735 0ustar mgportalloggers/* * Copyright (c) 2005 Tyan Computer Corp. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution 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. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #ifndef IPMI_TSOL_H #define IPMI_TSOL_H // #include #define IPMI_TSOL_CMD_SENDKEY 0x03 #define IPMI_TSOL_CMD_START 0x06 #define IPMI_TSOL_CMD_STOP 0x02 #define IPMI_NETFN_TSOL 0x30 #define IPMI_TSOL_DEF_PORT 6230 #define IPMI_BUF_SIZE 1024 /* for ipmi_rs in defs.h */ #define MIN(x,y) (((x) < (y)) ? (x) : (y)) #ifdef HAVE_IPV6 #define SOCKADDR_T struct sockaddr_storage #else #define SOCKADDR_T struct sockaddr_in #endif int get_LastError( void ); /* ipmilan.c */ void show_LastError(char *tag, int err); void lprintf(int level, const char * format, ...); /*subs.c*/ int lan_keepalive(int type); /*ipmilan.c*/ void set_loglevel(int level); void lperror(int level, const char * format, ...); int ipmi_open(char fdebugcmd); int open_sockfd(char *node, SockType *sfd, SOCKADDR_T *daddr, int *daddr_len, int foutput); int ipmi_tsol_main(void *, int, char **); #endif /* IPMI_TSOL_H */ ipmiutil-3.1.5/util/oem_fujitsu.h0000644000076400007640000001561213566765324017142 0ustar mgportalloggers/* * oem_fujitsu.h * * Authors: Andy Cress arcress at users.sourceforge.net, and * Dan Lukes dan at obluda.cz * * 08/27/10 Andy Cress - added with source input from Dan Lukes */ /*M* The BSD 2.0 License 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 Kontron, 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*/ #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int #define IPMI_OEM_MAX_BYTES 100 #define IPMI_IANA_ENTERPRISE_ID_FUJITSU 10368 #define IPMI_NET_FN_OEM_GROUP_RQ 0x2E #define IPMI_CMD_OEM_FUJITSU_SYSTEM 0xF5 #define IPMI_OEM_FUJITSU_COMMAND_SPECIFIER_GET_SEL_ENTRY_LONG_TEXT 0x43 #define IPMI_FUJITSU_PRODUCT_ID_MIN 0x0200 #define IPMI_FUJITSU_PRODUCT_ID_MAX 0x03FF // iRMC-S1 based systems #define IPMI_FUJITSU_PRODUCT_ID_TX200S3 0x0200 #define IPMI_FUJITSU_PRODUCT_ID_TX300S3 0x0201 #define IPMI_FUJITSU_PRODUCT_ID_RX200S3 0x0202 #define IPMI_FUJITSU_PRODUCT_ID_RX300S3 0x0203 #define IPMI_FUJITSU_PRODUCT_ID_UNUSEDS3 0x0204 #define IPMI_FUJITSU_PRODUCT_ID_RX100S4 0x0205 #define IPMI_FUJITSU_PRODUCT_ID_TX150S5 0x0206 #define IPMI_FUJITSU_PRODUCT_ID_TX120S1 0x0207 #define IPMI_FUJITSU_PRODUCT_ID_BX630S2 0x0208 #define IPMI_FUJITSU_PRODUCT_ID_RX330S1 0x0209 #define IPMI_FUJITSU_PRODUCT_ID_E230RN1 0x0210 #define IPMI_FUJITSU_PRODUCT_ID_E230RSL 0x0211 #define IPMI_FUJITSU_PRODUCT_ID_RX330S1_SHA 0x0212 #define IPMI_FUJITSU_PRODUCT_ID_BX630S2_SHA 0x0213 #define FUJITSU_PRODUCT_IS_iRMC_S1(_product_id_) \ ((_product_id_) == IPMI_FUJITSU_PRODUCT_ID_TX200S3 \ || (_product_id_) == IPMI_FUJITSU_PRODUCT_ID_TX300S3 \ || (_product_id_) == IPMI_FUJITSU_PRODUCT_ID_RX200S3 \ || (_product_id_) == IPMI_FUJITSU_PRODUCT_ID_RX300S3 \ || (_product_id_) == IPMI_FUJITSU_PRODUCT_ID_UNUSEDS3 \ || (_product_id_) == IPMI_FUJITSU_PRODUCT_ID_RX100S4 \ || (_product_id_) == IPMI_FUJITSU_PRODUCT_ID_TX150S5 \ || (_product_id_) == IPMI_FUJITSU_PRODUCT_ID_TX120S1 \ || (_product_id_) == IPMI_FUJITSU_PRODUCT_ID_BX630S2 \ || (_product_id_) == IPMI_FUJITSU_PRODUCT_ID_RX330S1 \ || (_product_id_) == IPMI_FUJITSU_PRODUCT_ID_E230RN1 \ || (_product_id_) == IPMI_FUJITSU_PRODUCT_ID_E230RSL \ || (_product_id_) == IPMI_FUJITSU_PRODUCT_ID_RX330S1_SHA \ || (_product_id_) == IPMI_FUJITSU_PRODUCT_ID_BX630S2_SHA) // iRMC-S2 based systems #define IPMI_FUJITSU_PRODUCT_ID_RX600S4 0x0218 #define IPMI_FUJITSU_PRODUCT_ID_TX200S4 0x0220 #define IPMI_FUJITSU_PRODUCT_ID_TX300S4 0x0221 #define IPMI_FUJITSU_PRODUCT_ID_RX200S4 0x0222 #define IPMI_FUJITSU_PRODUCT_ID_RX300S4 0x0223 #define IPMI_FUJITSU_PRODUCT_ID_UNUSEDS4 0x0224 #define IPMI_FUJITSU_PRODUCT_ID_RX100S5 0x0225 #define IPMI_FUJITSU_PRODUCT_ID_TX150S6 0x0226 #define IPMI_FUJITSU_PRODUCT_ID_TX120S2 0x0227 #define IPMI_FUJITSU_PRODUCT_ID_TX150S6_64K 0x0233 #define IPMI_FUJITSU_PRODUCT_ID_TX200S4_64K 0x0234 #define IPMI_FUJITSU_PRODUCT_ID_TX300S4_64K 0x0235 #define IPMI_FUJITSU_PRODUCT_ID_TX200S5 0x0240 #define IPMI_FUJITSU_PRODUCT_ID_TX300S5 0x0241 #define IPMI_FUJITSU_PRODUCT_ID_RX200S5 0x0242 #define IPMI_FUJITSU_PRODUCT_ID_RX300S5 0x0243 #define IPMI_FUJITSU_PRODUCT_ID_BX620S5 0x0244 #define IPMI_FUJITSU_PRODUCT_ID_RX100S6 0x0245 #define IPMI_FUJITSU_PRODUCT_ID_TX150S7 0x0246 #define IPMI_FUJITSU_PRODUCT_ID_BX960S1 0x0254 #define IPMI_FUJITSU_PRODUCT_ID_BX924S1 0x0255 #define IPMI_FUJITSU_PRODUCT_ID_BX920S1 0x0256 #define IPMI_FUJITSU_PRODUCT_ID_BX922S1 0x0257 #define IPMI_FUJITSU_PRODUCT_ID_RX600S5 0x0258 #define IPMI_FUJITSU_PRODUCT_ID_TX200S6 0x0260 #define IPMI_FUJITSU_PRODUCT_ID_TX300S6 0x0261 #define IPMI_FUJITSU_PRODUCT_ID_RX200S6 0x0262 #define IPMI_FUJITSU_PRODUCT_ID_RX300S6 0x0263 /******************************************* + * Fujitsu Siemens Computers * + * Fujitsu Technology Solutions * + * iRMC S1 / iRMC S2 * + *******************************************/ #define IPMI_SENSOR_TYPE_OEM_FUJITSU_I2C_BUS 0xC0 #define IPMI_SENSOR_TYPE_OEM_FUJITSU_SYSTEM_POWER_CONSUMPTION 0xDD //Events only #define IPMI_SENSOR_TYPE_OEM_FUJITSU_MEMORY_STATUS 0xDE #define IPMI_SENSOR_TYPE_OEM_FUJITSU_MEMORY_CONFIG 0xDF #define IPMI_SENSOR_TYPE_OEM_FUJITSU_MEMORY 0xE1 // Events only #define IPMI_SENSOR_TYPE_OEM_FUJITSU_HW_ERROR 0xE3 // Events only #define IPMI_SENSOR_TYPE_OEM_FUJITSU_SYS_ERROR 0xE4 // Events only #define IPMI_SENSOR_TYPE_OEM_FUJITSU_FAN_STATUS 0xE6 #define IPMI_SENSOR_TYPE_OEM_FUJITSU_PSU_STATUS 0xE8 #define IPMI_SENSOR_TYPE_OEM_FUJITSU_PSU_REDUNDANCY 0xE9 #define IPMI_SENSOR_TYPE_OEM_FUJITSU_COMMUNICATION 0xEA // Reserved #define IPMI_SENSOR_TYPE_OEM_FUJITSU_FLASH 0xEC // Events only #define IPMI_SENSOR_TYPE_OEM_FUJITSU_EVENT 0xEE // Reserved #define IPMI_SENSOR_TYPE_OEM_FUJITSU_CONFIG_BACKUP 0xEF ipmiutil-3.1.5/util/ilan.c0000644000076400007640000054460713566765324015542 0ustar mgportalloggers/*--------------------------------------------------------------------------- * Filename: ilan.c (was pefconfig.c) * * Author: arcress at users.sourceforge.net * Copyright (c) 2009 Kontron America, Inc. * * Abstract: * This tool sets up the custom Platform Event Filter for the panicSEL * record (0x20, OS Critical Stop) to send a PEF SNMP alert for Linux * panics. It also configures the BMC LAN parameters, which are needed * to support PEF alerts. * * ----------- Change History ----------------------------------------------- * 10/16/01 Andy Cress - created * 10/24/01 Andy Cress - mods for SetPefEntry(0c) * 11/02/01 Andy Cress - added option to disable a given PefEntry * 11/15/01 Andy Cress - added function to GetLanEntry * 11/19/01 Andy Cress - added function to SetLanEntry * 01/18/02 Andy Cress - added GetCfgData function * 01/31/02 Andy Cress - converted to use ipmi_cmd_ia * 02/06/02 Andy Cress - removed GetCfgData * 02/06/02 Andy Cress - added ipmi_cmd_va * 02/08/02 Andy Cress - added GetChanAcc * 02/14/02 Andy Cress - added Get_IPMac_Addr() * 02/21/02 Andy Cress - added Alert IP/MAC logic to Get_IPMac_Addr() * 03/21/02 Andy Cress - do SetChanAcc(0x80) with every SetChanAcc(0x40) * 04/15/02 Andy Cress v1.2 - fix bug with user-specified Alert IP: * (ccode=c7 on SetLanEntry(16 & 18), also * added Get_Mac() for user-specified Alert IP. * 04/16/02 Andy Cress v1.3 added SetUser() to set password if specified, * also changed unset mac[0] to be 0xFF, not 0. * 05/09/02 Andy Cress v1.4 fixed bug 504 gwymac[0]=00 (mymac overwrote it), * also fixed alert scan to pick last trapsink * 05/31/02 Andy Cress v1.5 for gwy mac, changed arping -c 1 to -c 2, * also get com2sec community from snmpd.conf, * set dest type for no ack, no retry, * special handling to set preset PEF entries * 07/02/02 Andy Cress v1.6 added more Usage text * 07/08/02 Andy Cress v1.7 SetUserAccess length change * 08/02/02 Andy Cress v1.8 moved common ipmi_cmd() code to ipmicmd.c * 08/27/02 Andy Cress v1.9 fixed 0xc7 on SETUSER_ACCESS with pefconfig -P "", * show message if alert dest not found * 09/10/02 Andy Cress v1.10 make channel nums into defines (16) * 09/17/02 Andy Cress v1.11 decode Dest Addr IP (19) in decimal, * fix enable user padding in SetUser, * display new community string when setting * 12/09/02 Andy Cress v1.12 fix error w -C & snmpd.conf conflict * 01/29/03 Andy Cress v1.13 added MV OpenIPMI support * 02/05/03 Andy Cress v1.14 show pef entry descriptions, * added EnablePef routine * show correct Alert dest mac if -A only * 04/04/03 Andy Cress v1.15 add eth interface option (-i) * 05/13/03 Andy Cress v1.16 fix EnablePef if startup delay not supported * 06/19/03 Andy Cress v1.17 added errno.h (email from Travers Carter) * 07/25/03 Andy Cress v1.18 add SerialOverLan configuration * mod to SetUser, added GetBmcEthDevice, * use 'arping -I' if eth1. * 08/18/03 Andy Cress v1.19 Don't abort if IPMI 1.0, just skip PEF, * SetLanEntry(10 & 11) for bmc grat arp, * SetLanEntry(2) to 0x17 for auth priv * 09/10/03 Andy Cress v1.20 Don't enable a PEF entry if it is empty, * added -L lan_ch parameter, * scan for lan_ch in GetBmcEthDevice * 09/22/03 Andy Cress v1.21 Add DHCP option (-D), from Jerry Yu. * 12/05/03 Andy Cress v1.22 Fix auth type enables for ServerConfig * 12/16/03 Andy Cress v1.23 Allow flexible auth types via authmask * 03/19/04 Andy Cress v1.24 Change default pefnum for mBMC to 10 * 04/15/04 Andy Cress v1.25 Init each response for channel info, avoids * 0xcc error with /dev/ipmi0 due to wrong lan_ch * 05/05/04 Andy Cress v1.26 call ipmi_close before exit. Note that * Get_IPMac_Addr and GetBmcEthDevice * routines need more work for WIN32. * 05/24/04 Andy Cress v1.27 added CHAN_ACC params for ia64 * 06/28/04 Andy Cress v1.28 added parsing to get community from trapsink * 07/23/04 Andy Cress v1.29 use lan_ch variable to set Alert Policy Table * 08/23/04 Andy Cress v1.30 fixed decoding of PE Table entries, * added -e option (same as no params) * 08/25/04 Andy Cress v1.31 added some WIN32 logic to Get_Mac, Get_IPMac_Addr * 11/01/04 Andy Cress v1.32 add -N / -R for remote nodes * added -U for remote username * 11/18/04 Andy Cress v1.33 added -u to configure a lan username (user 2) * 11/23/04 Andy Cress v1.34 added pef_defaults if first 11 empty * 01/11/05 Andy Cress v1.35 allow scan for BMC LAN if fIPMI10 * 01/20/05 Andy Cress v1.36 fix to allow IPMI 2.0 * 02/16/05 Andy Cress v1.37 added IPMI 2.0 VLAN parameters, * if DHCP, can set DHCP Server via -I param * 03/02/05 Andy Cress v1.38 show Serial-Over-Lan params, * fix -L with lan_ch_parm. mods to GetBmcEthDevice * 03/18/05 Andy Cress v1.39 fix GetBmcEthDevice for invalid MAC compares * 06/03/05 Andy Cress v1.40 For my MAC in BMC, check user-specified, then * check existing BMC MAC, then check OS MAC. * 06/10/05 Andy Cress v1.41 Display multiple Alert Destinations, * handle fSOL20 commands * 07/07/05 Andy Cress v1.42 Fix GetBmcEthDevice for TIGI2U to skip GCM ch 3 * 07/08/05 Andy Cress v1.43 Mods to handle Intel NSI2U miniBMC, * 08/01/05 Andy Cress v1.44 added -t option to test if BMC LAN configured * 08/10/05 Andy Cress v1.45 truncate extra string chars, * decode more PEF params * 09/07/05 Andy Cress v1.46 enable mBMC PEF entries 26 thru 30 * 04/06/06 Andy Cress v1.47 show "gcm" as ifname if -L 3. * 06/20/06 Andy Cress v1.48 fix strcmp(gcm), show all 4 alert policies, * add PefDesc() for misc vendor pefdesc, add -a. * 08/08/06 Andy Cress v1.49 add Alcolu to fsharedMAC * 09/29/06 Andy Cress v1.52 use bmcmymac if valid, use bmcmyip if ok, * added -q for user number, * enhanced Get_IPMac_Addr for Windows * 10/12/06 Andy Cress v1.53 FindEthNum updates, always use gwy iface for mac * 11/02/06 Andy Cress v1.55 add user names, EnablePef mods for non-Intel. * 05/02/07 Brian Johnson v1.65 add fpefenable flag to not do SetPefEntry * if no Alert Destination. Previously did * SetPefEntry but not EnablePef in this case. * 05/04/07 Andy Cress v1.65 Use 0x02 for DHCP source instead of 0x03, * fix 1714748 missing "X:" in getopt line * 05/23/07 Jakub Gorgolewski * v1.66 Use iphlpapi for Windows detection * 10/31/07 Andy Cress v2.3 Fixed PEF entry for Power Redundancy Lost * 11/15/07 Andy Cress v2.4 Move custom PEF to #14, add to usage, * Allow broadcast MAC for -X * 12/17/07 Andy Cress v2.5 Add fSetPEFOks & secondary Gateway */ /*M* *--------------------------------------------------------------------------- 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 Kontron 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*/ #ifdef WIN32 #include #include #include #include #include #include #include "getopt.h" #elif defined(DOS) #include #include #include #include #include "getopt.h" #else /* Linux or similar */ #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #include #include #include #include #include #endif #ifdef LINUX #include #endif #ifdef SOLARIS #include #define SIOCGIFHWADDR SIOCGENADDR #define ifr_netmask ifr_ifru.ifru_addr // #define ifr_hwaddr.sa_data ifr_ifru.ifru_enaddr #elif defined(BSD) #include #define SIOCGIFHWADDR SIOCGIFMAC #define ifr_netmask ifr_ifru.ifru_addr // #define ifr_hwaddr.sa_data ifr_ifru.ifru_addr #elif defined(MACOS) #include #define ifr_netmask ifr_ifru.ifru_addr #endif #include "ipmicmd.h" #include "oem_intel.h" #include "oem_supermicro.h" #define SELprintf printf #define RTF_UP 0x0001 /* route usable */ #define SOL_ENABLE_FLAG 0x01 #define SOL_DISABLE_FLAG 0x00 #define SOL_PRIVILEGE_LEVEL_USER 0x02 #define SOL_PRIVILEGE_LEVEL_OPERATOR 0x03 #define SOL_PRIVILEGE_LEVEL_ADMIN 0x04 #define SOL_PREFERRED_BAUD_RATE 0x0a /*115.2k */ /* For IPMI 1.5, use Intel SOL commands & subfunctions */ #define SOL_ENABLE_PARAM 0x01 #define SOL_AUTHENTICATION_PARAM 0x02 #define SOL_ACC_INTERVAL_PARAM 0x03 #define SOL_RETRY_PARAM 0x04 #define SOL_BAUD_RATE_PARAM 0x05 /*non-volatile */ #define SOL_VOL_BAUD_RATE_PARAM 0x06 /*volatile */ /* For IPMI 2.0, use IPMI SOL commands & subfunctions */ #define SOL_ENABLE_PARAM2 0x08 #define SOL_AUTHENTICATION_PARAM2 0x09 #define SOL_BAUD_RATE_PARAM2 0x11 /* IPMI 2.0 SOL PAYLOAD commands */ #define SET_PAYLOAD_ACCESS 0x4C #define GET_PAYLOAD_ACCESS 0x4D #define GET_PAYLOAD_SUPPORT 0x4E /* Channel Access values */ #define CHAN_ACC_DISABLE 0x20 /* PEF off, disabled */ #define CHAN_ACC_PEFON 0x02 /* PEF on, always avail */ #define CHAN_ACC_PEFOFF 0x22 /* PEF off, always avail */ /* special channel access values for ia64 */ #define CHAN_ACC_PEFON64 0x0A /* PEF on, always avail, UserLevelAuth=off */ #define CHAN_ACC_PEFOFF64 0x2A /* PEF off, always avail, UserLevelAuth=off */ #define OS_LINUX 1 #define OS_WINDOWS 2 #define OS_SOLARIS 3 #define OS_BSD 4 #define OS_HPUX 5 /* TSRLT2 Channels: 0=IPMB, 1=Serial/EMP, 6=LAN2, 7=LAN1 */ /* S5000 Channels: 0=IPMB, 1=LAN1, 2=LAN2, 3=RMM2, 4=Serial, 6=pci, 7=sys */ /* For TIGPT1U/mBMC: 1=LAN channel, no serial */ #define LAN_CH 1 #define SER_CH 4 #define MAXCHAN 12 /*was 16, reduced for gnu ipmi_lan */ #define NUM_DEVICES_TO_CHECK 32 /*for GetBmcEthDevice() */ #define MAC_LEN 6 /*length of MAC Address */ #define PSW_LEN 16 /* see also PSW_MAX =20 in ipmicmd.h */ /* Note: The optional IPMI 2.0 20-byte passwords are not supported here, * due to back-compatibility issues. */ /* IP address source values */ #define SRC_STATIC 0x01 #define SRC_DHCP 0x02 /* BMC running DHCP */ #define SRC_BIOS 0x03 /* BIOS, sometimes DHCP */ #define SRC_OTHER 0x04 /* PEF event severities */ #define PEF_SEV_UNSPEC 0x00 #define PEF_SEV_MON 0x01 #define PEF_SEV_INFO 0x02 #define PEF_SEV_OK 0x04 #define PEF_SEV_WARN 0x08 #define PEF_SEV_CRIT 0x10 #define PEF_SEV_NORECOV 0x20 #define FLAG_INIT 99 /*initial value of char flag, beyond scope */ #define PARM_INIT 0xff typedef struct { /* See IPMI Table 15-2 */ uchar rec_id; uchar fconfig; uchar action; uchar policy; uchar severity; uchar genid1; uchar genid2; uchar sensor_type; uchar sensor_no; uchar event_trigger; uchar data1; uchar mask1; uchar res[9]; } PEF_RECORD; typedef struct { /* See IPMI Table 19-3 */ uchar data[36]; } LAN_RECORD; /*LanRecord */ #ifdef METACOMMAND extern int get_lan_stats (uchar chan); /*see bmchealth.c */ extern char *get_sensor_type_desc (uchar stype); /*from ievents.c */ #endif #define MYIP 0x01 #define GWYIP 0x02 #define DESTIP 0x04 #define MAXPEF 41 /* max pefnum offset = 40 (41 entries) */ /* * Global variables */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil lan"; #else static char * progver = "3.08"; static char * progname = "ilan"; #endif static char fdebug = 0; static char fipmilan = 0; static char fIPMI10 = 0; /* =1 if IPMI v1.0 or less */ static char fIPMI20 = 0; /* =1 if IPMI v2.0 or greater */ static char fSOL20 = 1; /* =1 if use Serial-Over-Lan 2.0 w IPMI 2.0 */ static char fsharedMAC = 0; /* =1 if special shared-MAC BMC LAN port */ static char fAdjustPefNum = 0; /* =1 adjust pefnum to first empty index */ static char fUserPefNum = 0; /* =1 if user specified a valid pefnum value */ static char freadonly = 1; /* =1 to only read LAN & PEF parameters */ static char fcanonical = 0; /* =1 to show only canonical output */ static char flansecure = 0; /* =1 set lan security: no null, cipher0 off */ static char bdelim = BCOLON; /* delimiter ':' or '|' if canonical output */ static char ftestonly = 0; static char fprivset = 0; static char flanstats = 0; /* =1 to show the IPMI LAN statistics */ static char foptmsg = 0; /* =1 to show the option warning msg */ static char fshowchan = 0; /* =1 to show the IPMI channels */ static char nopts = 0; /* number of pefconfig options specified */ static int nerrs = 0; /* number of errors during processing */ static int ngood = 0; /* number of good results */ static int lasterr = 0; /* value of the last error */ static char fCustomPEF = 0; /* =1 if -j to input a custom PEF record */ static char fSetPEFOks = 0; /* =1 if -k to set PEF OK rules */ static char fdisable = 0; static char fenable = 0; /* =1 to config BMC LAN and PEF */ static char fpefenable = 0; /* =1 enable PEF if Alert Dest is specified */ static char fdisableSOL = 0; static char fgetser = 0; static char fsetifn = 0; /* =1 if user specified ifname[] with -i */ static char fethfound = 0; /* =1 if FindEthNum successful */ static char fset_ip = 0; /* !=0 if options used to specify an IP addr */ static char fpassword = 0; /* =1 user-specified a password, so set it. */ static uchar fmBMC = 0; /* =1 mini-BMC, =0 Sahalee BMC */ static uchar fiBMC = 0; /* =1 Intel iBMC */ static uchar fRomley = 0; /* =1 Intel Romley BMC */ static uchar fGrantley = 0; static uchar fipv6 = 0; /* =1 if BMC supports IPv6 */ static uchar bmcpefctl = 0; /* existing BMC PEF Control, !0 = enabled */ static char alertnum = 1; /* alert dest num (usu 1 thru 4) */ static char alertmax = 9; /* alert dest num max (usu 4, error if >9) */ static char pefnum = 12; /* 11 pre-defined entries, adding 12th */ static char pefadd = 0; /* num PEF rules added (usu 2, could be 5 */ static char pefmax = MAXPEF; /* 20 for Sahalee, 30 for miniBMC */ static char *myuser = NULL; /* username to set, specified by -u */ static uchar usernum = 0; /* set non-zero to specify user number */ static uchar rgmyip[4] = { 0, 0, 0, 0 }; static uchar rggwyip[4] = { 0, 0, 0, 0 }; static uchar rggwy2ip[4] = { 0, 0, 0, 0 }; static uchar rgdestip[4] = { 0, 0, 0, 0 }; static uchar rgsubnet[4] = { 0, 0, 0, 0 }; static uchar bmcsubnet[4] = { 255, 255, 255, 0 }; /* default subnet */ static uchar ossubnet[4] = { 0, 0, 0, 0 }; static uchar osmyip[4] = { 0, 0, 0, 0 }; static uchar bmcmyip[4] = { 0, 0, 0, 0 }; static uchar bmcdestip[4] = { 0, 0, 0, 0 }; static uchar bmcdestmac[6] = { 0xff, 0, 0, 0, 0, 0 }; static uchar bmcgwyip[4] = { 0, 0, 0, 0 }; static uchar bmcgwymac[6] = { 0xff, 0, 0, 0, 0, 0 }; static uchar bmcmymac[6] = { 0xff, 0, 0, 0, 0, 0 }; static uchar rgmymac[6] = { 0xff, 0, 0, 0, 0, 0 }; static uchar osmymac[6] = { 0xff, 0, 0, 0, 0, 0 }; static uchar rggwymac[6] = { 0xff, 0, 0, 0, 0, 0 }; static uchar rggwy2mac[6] = { 0xff, 0, 0, 0, 0, 0 }; static uchar rgdestmac[6] = { 0xff, 0, 0, 0, 0, 0 }; static uchar rgdhcpmac[6] = { 0xff, 0, 0, 0, 0, 0 }; static int nciphers = 16; static int ncipher0 = 0; static uchar rgciphers[16] = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static char rghostname[32] = { '\0' }; static uchar custPEF[20]; /* max used = 18 bytes */ static char rgcommunity[19] = "public"; /* default community */ static char fsetcommunity = 0; /* =1 if user-specified community */ static char passwordData[PSW_MAX + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static uchar authmask = 0; /* usu 0x17, mBMC = 0x15 */ static uchar bAuth = 0x16; /*exclude auth=None for security */ static uchar arp_interval = 0x04; /* in 500 ms increments, 0-based */ static uchar arp_ctl = 0x01; /* 01=grat arp, 02=arp resp, 03=both */ static uchar fsetarp = 0; /* 1=user-specified arp_ctl */ #ifdef WIN32 static uchar ostype = OS_WINDOWS; /*windows */ static char ifname[64] = "Local Area Connection "; /* interface name */ static char ifpattn[25] = "Local Area Connection "; #elif SOLARIS /* for i86pc use "e1000g0", but for sun4u(sparc) this might be "eri0" */ static uchar ostype = OS_SOLARIS; #ifdef __SPARC__ static char ifname[16] = "eri0"; /* SPARC interface name */ static char ifname0[16] = "eri0"; static char ifpattn[14] = "eri"; #else static char ifname[16] = "e1000g0"; /* Solaris x86 interface name */ static char ifname0[16] = "e1000g0"; static char ifpattn[14] = "e1000g"; #endif #elif defined(BSD) static uchar ostype = OS_BSD; static char ifname[16] = "em0"; /* interface name */ static char ifname0[16] = "em0"; static char ifpattn[14] = "em"; #elif defined(HPUX) static uchar ostype = OS_HPUX; static char ifname[16] = "lan0"; /* interface name */ static char ifname0[16] = "lan0"; static char ifpattn[14] = "lan"; #else static uchar ostype = OS_LINUX; static char ifname[16] = "eth0"; /* interface name */ static char ifname0[16] = "eth0"; static char ifpattn[14] = "eth"; #endif static char *pspace1 = "\t"; /*used for fcanonical output */ static char *pspace2 = "\t\t"; static char *pspace3 = "\t\t\t"; static char *pspace4 = "\t\t\t\t"; static int vend_id; static int prod_id; static int lan_dhcp = 0; /*=1 if using DHCP for bmc lan channel*/ static uchar ser_ch = SER_CH; static uchar gcm_ch = PARM_INIT; static uchar failover_enable = PARM_INIT; static uchar vlan_enable = PARM_INIT; static uchar vlan_prio = 0; /*default = 0 */ static ushort vlan_id = 0; /*max 12 bits used */ static uchar lan_access = 0x04; /* -v usu 4=Admin, 3=Operator, 2=User */ static uchar lan_user = 0x02; /* -u if specified, default to user 2 */ static uchar lan_ch_parm = PARM_INIT; /* -L to set, unused if PARM_INIT */ static uchar lan_ch = LAN_CH; /* default=LAN_CH=1 */ static uchar max_users = 5; /* set in GetUser(1); */ static uchar enabled_users = 0; /* set in GetUser(1); */ static uchar show_users = 5; /* default, adjusted based on DeviceID */ static uchar fnewbaud = 0; /* =1 if user specified baud */ static uchar sol_baud = SOL_PREFERRED_BAUD_RATE; /*115.2k default */ static uchar sol_accum[2] = { 0x04, 0x32 }; static uchar sol_retry[2] = { 0x06, 0x14 }; static uchar sol_bvalid = 0; /* =1 if SOL baud is valid */ static uchar chan_pefon = CHAN_ACC_PEFON; static uchar chan_pefoff = CHAN_ACC_PEFOFF; static uchar SessInfo[18]; /* Session Info data */ // static uchar bparm7[3] = {0x00, 0x00, 0x00}; /*ipv4 header before*/ static uchar iparm7[3] = { 0x1E, 0x00, 0x00 }; /*intel ipv4 TTL,Flags,Service */ static uchar oparm7[3] = { 0x40, 0x40, 0x10 }; /*other ipv4 TTL,Flags,Service */ static uchar *parm7 = &oparm7[0]; #define MAX_PEFPARAMS 14 /* max pef params = 14 */ uchar peflen[MAX_PEFPARAMS] = { 0, 1, 1, 1, 1, 1, 21, 2, 1, 4, 17, 1, 3, 18 }; /*for ShowPef */ uchar pef_array[MAXPEF][21]; /* array of all PEF entries read, */ /* sizeof(PEF_RECORD) = 21 */ uchar pef_defaults[11][21] = { /* array of first 11 default PEF entries */ {0x01, 0x80, 1, 1, PEF_SEV_CRIT, 0xff, 0xff, 0x01, 0xff, 0x01, 0x95, 0x0a, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /*Temp */ {0x02, 0x80, 1, 1, PEF_SEV_CRIT, 0xff, 0xff, 0x02, 0xff, 0x01, 0x95, 0x0a, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /*Volt */ {0x03, 0x80, 1, 1, PEF_SEV_CRIT, 0xff, 0xff, 0x04, 0xff, 0x01, 0x95, 0x0a, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /*Fan */ {0x04, 0x80, 1, 1, PEF_SEV_WARN, 0xff, 0xff, 0x05, 0x05, 0x03, 0x01, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /*Chass */ {0x05, 0x80, 1, 1, PEF_SEV_WARN, 0xff, 0xff, 0x08, 0xff, 0x6f, 0x06, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /*PS*/ {0x06, 0x80, 1, 1, PEF_SEV_WARN, 0xff, 0xff, 0x0c, 0x08, 0x6f, 0x02, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /*ECC*/ {0x07, 0x80, 1, 1, PEF_SEV_CRIT, 0xff, 0xff, 0x0f, 0x06, 0x6f, 0x01, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /*FRB*/ {0x08, 0x80, 1, 1, PEF_SEV_WARN, 0xff, 0xff, 0x07, 0xff, 0x6f, 0x1c, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /*POST*/ {0x09, 0x80, 1, 1, PEF_SEV_CRIT, 0xff, 0xff, 0x13, 0xff, 0x6f, 0x3e, 0x03, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /*NMI*/ {0x0a, 0x80, 1, 1, PEF_SEV_INFO, 0xff, 0xff, 0x23, 0x03, 0x6f, 0x0e, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /*WDT*/ {0x0b, 0x80, 1, 1, PEF_SEV_MON, 0xff, 0xff, 0x12, 0xff, 0x6f, 0x02, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0} /*Restart */ }; char **pefdesc; char *pefdesc1[MAXPEF] = { /* for Sahalee BMC */ /* 0 0x00 */ "", /* 1 0x01 */ "Temperature Sensor", /* 2 0x02 */ "Voltage Sensor", /* 3 0x04 */ "Fan Failure", /* 4 0x05 */ "Chassis Intrusion", /* 5 0x08 */ "Power Supply Fault", /* 6 0x0c */ "Memory ECC Error", /* 7 0x0f */ "BIOS POST Error", /* 8 0x07 */ "FRB Failure", /* 9 0x13 */ "Fatal NMI", /*10 0x23 */ "Watchdog Timer Reset", /*11 0x12 */ "System Restart", /*12 0x20 */ "OS Critical Stop", /*13 0x09 */ "Power Redundancy Lost", /*14 0x00 */ "reserved", /*15 0x00 */ "reserved", /*16 0x00 */ "reserved", /*17 */ "reserved", /*18 */ "reserved", /*19 */ "reserved", /*20 */ "reserved", /*21 */ "reserved", /*22 */ "reserved", /*23 */ "reserved", /*24 */ "reserved", /*25 */ "reserved", /*26 */ "reserved", /*27 */ "reserved", /*28 */ "reserved", /*29 */ "unused", /*30 */ "unused" }; char *pefdesc2[MAXPEF] = { /* for NSC miniBMC */ /* 0 */ "", /* 1 0x02*/ "Voltage Sensor Assert", /* 2 0x23*/ "Watchdog FRB Timeout", /* was "Proc FRB Thermal", */ /* 3 0x02*/ "Voltage Sensor Deassert", /* 4 0x07*/ "Proc1 IERR", /* 5 0xff*/ "Digital Sensor OK", /* 6 0x14*/ "Chassis Identify", /* 7 0x13*/ "NMI Button", /* 8 0x14*/ "Clear CMOS via Panel", /* 9 0x0f*/ "OS Load POST Code", /*10 0x20*/ "OS Critical Stop", /*11 0x09 */ "Power Redundancy Lost", /*12 0x00*/ "reserved", /*13 */ "reserved", /*14 */ "reserved", /*15 */ "reserved", /*16 */ "reserved", /*17 */ "reserved", /*18 */ "reserved", /*19 */ "reserved", /*20 */ "reserved", /*21 */ "reserved", /*22 */ "reserved", /*23 */ "reserved", /*24 */ "reserved", /*25 */ "reserved", /*26 0x05*/ "Chassis Intrusion", /*27 0x0f*/ "POST Code Error", /*28 0x02*/ "Voltage Failure", /*29 0x04*/ "Fan Failure", /*30 0x01*/ "Temperature Failure" }; #define NLAN 39 char canon_param[NLAN] = { 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 }; struct { int cmd; int sz; char desc[28]; } lanparams[NLAN] = { /* see IPMI Table 19-4 */ /* 0 */ { 0, 1, "Set in progress"}, /* 1 */ { 1, 1, "Auth type support"}, /* 2 */ { 2, 5, "Auth type enables"}, /* 3 */ { 3, 4, "IP address"}, /* 4 */ { 4, 1, "IP addr src"}, /* (DHCP/Static) */ /* 5 */ { 5, 6, "MAC addr"}, /* 6 */ { 6, 4, "Subnet mask"}, /* 7 */ { 7, 3, "IPv4 header"}, /* 8 */ { 8, 2, "Prim RMCP port"}, /* 9 */ { 9, 2, "Sec RMCP port"}, /* 10 */ { 10, 1, "BMC grat ARP"}, /* 11 */ { 11, 1, "grat ARP interval"}, /* 12 */ { 12, 4, "Def gateway IP"}, /* 13 */ { 13, 6, "Def gateway MAC"}, /* 14 */ { 14, 4, "Sec gateway IP"}, /* 15 */ { 15, 6, "Sec gateway MAC"}, /* 16 */ { 16, 18, "Community string"}, /* 17 */ { 17, 1, "Num dest"}, /* 18 */ { 18, 5, "Dest type"}, /* 19 */ { 19, 13, "Dest address"}, /* 20 */ { 20, 2, "VLAN ID"}, /* 21 */ { 21, 1, "VLAN Priority"}, /* 22 */ { 22, 1, "Cipher Suite Support"}, /* 23 */ { 23, 17, "Cipher Suites "}, /* 24 */ { 24, 9, "Cipher Suite Priv"}, /* 25 */ { 25, 4, "VLAN Dest Tag"}, /* 26 */ { 96, 28, "OEM Alert String"}, /* 27 */ { 97, 1, "Alert Retry Algorithm"}, /* 28 */ { 98, 3, "UTC Offset"}, /* 29 */ { 102, 1, "IPv6 Enable"}, /* 30 */ { 103, 1, "IPv6 Addr Source"}, /* 31 */ { 104, 16, "IPv6 Address"}, /* 32 */ { 105, 1, "IPv6 Prefix Len"}, /* 33 */ { 106, 16, "IPv6 Default Gateway"}, /* 34 */ { 108, 17, "IPv6 Dest address"}, /* 35 */ { 192, 4, "DHCP Server IP"}, /* 36 */ { 193, 6, "DHCP MAC Address"}, /* 37 */ { 194, 1, "DHCP Enable"}, /* 38 */ { 201, 2, "Channel Access Mode(Lan)"} }; #define NSER 22 /* max=32 */ struct { int cmd; int sz; char desc[28]; } serparams[NSER] = { /* see IPMI Table 20-4 */ /* 0 */ { 0, 1, "Set in progress"}, /* 1 */ { 1, 1, "Auth type support"}, /* 2 */ { 2, 5, "Auth type enables"}, /* 3 */ { 3, 1, "Connection Mode"}, /* 4 */ { 4, 1, "Sess Inactiv Timeout"}, /* 5 */ { 5, 5, "Channel Callback"}, /* 6 */ { 6, 1, "Session Termination"}, /* 7 */ { 7, 2, "IPMI Msg Comm"}, /* 8 */ { 8, 2, "Mux Switch"}, /* 9 */ { 9, 2, "Modem Ring Time"}, /* 10 */ { 10, 17, "Modem Init String"}, /* 11 */ { 11, 5, "Modem Escape Seq"}, /* 12 */ { 12, 8, "Modem Hangup Seq"}, /* 13 */ { 13, 8, "Modem Dial Command"}, /* 14 */ { 14, 1, "Page Blackout Interval"}, /* 15 */ { 15, 18, "Community String"}, /* 16 */ { 16, 1, "Num of Alert Dest"}, /* 17 */ { 17, 5, "Destination Info"}, /* 18 */ { 18, 1, "Call Retry Interval"}, /* 19 */ { 19, 3, "Destination Comm Settings"}, /* 20 */ { 29, 2, "Terminal Mode Config"}, /* 21 */ { 201, 2, "Channel Access Mode (Ser)"} }; static void getauthstr (uchar auth, char *s) { if (s == NULL) return; s[0] = 0; if (auth & 0x01) strcat (s, "None "); if (auth & 0x02) strcat (s, "MD2 "); if (auth & 0x04) strcat (s, "MD5 "); if (auth & 0x10) strcat (s, "Pswd "); if (auth & 0x20) strcat (s, "OEM "); return; } static int GetDeviceID (LAN_RECORD * pLanRecord) { /*See also ipmi_getdeviceid( pLanRecord, sizeof(LAN_RECORD),fdebug); */ uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar inputData[24]; uchar completionCode; if (pLanRecord == NULL) return (-1); status = ipmi_cmd (GET_DEVICE_ID, inputData, 0, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if (completionCode) { SELprintf ("GetDeviceID: completion code=%x\n", completionCode); status = completionCode; } else { memcpy (pLanRecord, &responseData[0], responseLength); set_mfgid (&responseData[0], responseLength); return (0); // successful, done } } /* endif */ /* if get here, error */ return (status); } /*end GetDeviceID() */ static int GetChanAcc (uchar chan, uchar parm, LAN_RECORD * pLanRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar inputData[24]; uchar completionCode; if (pLanRecord == NULL) return (-1); responseLength = 3; inputData[0] = chan; inputData[1] = parm; /* 0x80 = active, 0x40 = non-volatile */ responseLength = sizeof (responseData); status = ipmi_cmd (GET_CHANNEL_ACC, inputData, 2, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if (completionCode) { SELprintf ("GetChanAcc: completion code=%x\n", completionCode); status = completionCode; } else { // dont copy first byte (Parameter revision, usu 0x11) memcpy (pLanRecord, &responseData[0], responseLength); return (0); // successful, done } } /* endif */ /* if get here, error */ return (status); } /*GetChanAcc() */ static int SetChanAcc (uchar chan, uchar parm, uchar val) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar inputData[24]; uchar completionCode; if (fmBMC) return (0); /* mBMC doesn't support this */ /* parm: 0x80 = active, 0x40 = set non-vol */ responseLength = 1; inputData[0] = chan; /* channel */ inputData[1] = (parm & 0xc0) | (val & 0x3F); inputData[2] = (parm & 0xc0) | lan_access; /* set priv level to Admin */ responseLength = sizeof (responseData); status = ipmi_cmd (SET_CHANNEL_ACC, inputData, 3, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if (completionCode) { SELprintf ("SetChanAcc: completion code=%x\n", completionCode); status = completionCode; } else { return (0); // successful, done } } /* endif */ /* if get here, error */ return (status); } /*SetChanAcc() */ int SetPasswd (int unum, char *uname, char *upswd, uchar chan, uchar priv) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status, i, psw_len; uchar completionCode; uchar inputData[24]; int ret = 0; inputData[0] = (uchar) unum; /*user 1 = null user */ responseLength = sizeof (responseData); status = ipmi_cmd (GET_USER_NAME, inputData, 1, responseData, &responseLength, &completionCode, fdebug); SELprintf ("GET_USERNAME: %x %x %x, status = %x, ccode=%x\n", responseData[0], responseData[1], responseData[2], status, completionCode); if (fdebug) { char aname[17]; printf ("User %d: ", unum); for (i = 0; i < responseLength; i++) { printf ("%02x ", responseData[i]); if (responseData[i] < 0x20) aname[i] = '.'; else aname[i] = responseData[i]; } aname[16] = 0; printf (" %s\n", aname); } if (unum != 1) { /* user specified a lan username */ if (fiBMC && (unum == 2)) { /* cannot set user 2 name */ if (uname != NULL) { if (strcmp (uname, "root") != 0) printf ("SETUSERNAME - user2 name %s must be root\n", uname); } } else if (unum == 2 && (vend_id == VENDOR_SUPERMICROX || vend_id == VENDOR_SUPERMICRO)) { /* cannot set user 2 name */ if (uname != NULL) { if (strcmp (uname, "ADMIN") != 0) printf ("SETUSERNAME - user2 name %s must be ADMIN\n", uname); } } else if (uname != NULL) { inputData[0] = (uchar) unum; memset (&inputData[1], 0, 16); memcpy (&inputData[1], uname, strlen (uname)); status = ipmi_cmd (SET_USER_NAME, inputData, 17, responseData, &responseLength, &completionCode, fdebug); if (completionCode == 0xCC) status = 0; /*setting username to previous gives 0xCC, ok */ else { SELprintf ("SETUSERNAME - %x %x %x status = %x, ccode=%x\n", inputData[0], inputData[1], inputData[2], status, completionCode); if (status == 0) status = completionCode; if (status != 0) ret = status; } } } if ((unum != 1) && (uname == NULL)) { ; /* if no username, do not enable user */ } else { inputData[0] = (uchar) unum; inputData[1] = 0x01; /*enable user */ responseLength = sizeof (responseData); status = ipmi_cmd (SET_USER_PASSWORD, inputData, 2, responseData, &responseLength, &completionCode, fdebug); printf ("SETUSERENAB - inputData %x %x %x, status = %x, ccode=%x\n", inputData[0], inputData[1], inputData[2], status, completionCode); if (status == 0) status = completionCode; if (status != 0) ret = status; } if (upswd != NULL) { inputData[0] = (uchar) unum; inputData[1] = 0x02; /*set password */ psw_len = PSW_LEN; /*=16 change if 20-byte passwords supported */ memset (&inputData[2], 0, psw_len); strcpy ((char *) &inputData[2], upswd); if (fdebug) { char apsw[PSW_MAX + 1]; char c; printf ("Pswd %d: ", unum); for (i = 0; i < psw_len; i++) { c = inputData[i + 2]; printf ("%02x ", (unsigned char) c); if (c < 0x20) apsw[i] = '.'; else apsw[i] = c; } apsw[psw_len] = 0; printf (" %s\n", apsw); } responseLength = sizeof (responseData); status = ipmi_cmd (SET_USER_PASSWORD, inputData, 2 + psw_len, responseData, &responseLength, &completionCode, fdebug); SELprintf ("SETUSERPSW - inputData %x %x %x, status = %x, ccode=%x\n", inputData[0], inputData[1], inputData[2], status, completionCode); if (status == 0) status = completionCode; if (status != 0) ret = status; inputData[0] = (uchar) unum; /*user 1 = null user */ inputData[1] = 0x03; /*test password */ memset (&inputData[2], 0, psw_len); if (upswd != NULL) strcpy ((char *) &inputData[2], upswd); responseLength = sizeof (responseData); status = ipmi_cmd (SET_USER_PASSWORD, inputData, 2 + psw_len, responseData, &responseLength, &completionCode, fdebug); SELprintf ("TESTUSERPSW - inputData %x %x %x, status = %x, ccode=%x\n", inputData[0], inputData[1], inputData[2], status, completionCode); } if (fiBMC && (unum == 2)) { /*iBMC doesn't support this on user 2 */ if (fdebug) printf ("skipping SETUSER_ACCESS on iBMC for user %d\n", unum); } else { inputData[0] = 0x90 | chan; /* = 0x97 for chan=lan_ch=7 */ inputData[1] = (uchar) unum; /* user num */ inputData[2] = priv; /* usu priv=lan_access is admin */ inputData[3] = 0x00; /* User Session Limit, 0=not limited */ responseLength = sizeof (responseData); status = ipmi_cmd (SET_USER_ACCESS, inputData, 4, responseData, &responseLength, &completionCode, fdebug); printf ("SETUSER_ACCESS - inputData %x %x %x, status = %x ccode=%x\n", (uchar) inputData[0], inputData[1], inputData[2], status, completionCode); if (status == 0) status = completionCode; if (status != 0) ret = status; } return (ret); } /*end SetPswd() */ int SetUser (int unum, char *uname, char *passwd, uchar chan) { int ret = 0; /* if the user specified a username or password, set it. */ if ((fpassword) || (uname != NULL)) { /* set username and password */ ret = SetPasswd (unum, uname, passwd, chan, lan_access); } return (ret); } /*end SetUser() */ int DisableUser (int unum, uchar chan) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar completionCode; uchar inputData[24]; inputData[0] = 0x80 | chan; /* = 0x87, no IPMI */ inputData[1] = (uchar) unum; /* user 1 */ inputData[2] = 0x0F; /* No access */ inputData[3] = 0x00; /* User Session Limit, 0=not limited */ responseLength = sizeof (responseData); status = ipmi_cmd (SET_USER_ACCESS, inputData, 4, responseData, &responseLength, &completionCode, fdebug); if (status == 0) status = completionCode; return (status); } char * parse_priv (uchar c) { char *p; c = (c & 0x0f); switch (c) { case 1: p = "Callback"; break; case 2: p = "User "; break; case 3: p = "Operator"; break; case 4: p = "Admin "; break; case 5: p = "OEM "; break; case 0x0f: p = "No access"; break; default: p = "Reserved"; /*usually =0 */ } return (p); } static void show_priv (uchar c) { char *privstr; privstr = parse_priv (c); printf ("%s", privstr); } static int valid_priv (int c) { int rv; switch (c) { case 1: case 2: case 3: case 4: case 5: case 0x0f: rv = 1; break; default: rv = 0; break; } return rv; } /* GetUserINfo - get user configuration info for user subfunction */ int GetUserInfo (uchar unum, uchar chan, uchar * enab, uchar * priv, char *uname, char fdbg) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status, rv; uchar completionCode; uchar inputData[24]; uchar upriv; if (fdbg) fdebug = 1; if (enab == NULL || priv == NULL) return (-2); inputData[0] = chan; /*lan_ch */ inputData[1] = unum; /* user number for IPMI LAN */ responseLength = sizeof (responseData); status = ipmi_cmd (GET_USER_ACCESS, inputData, 2, responseData, &responseLength, &completionCode, fdebug); rv = status; if (status == 0 && completionCode != 0) rv = completionCode; if (rv == 0) { if (unum == 1) { /*get max_users and enabled_users */ max_users = responseData[0] & 0x3f; enabled_users = responseData[1] & 0x3f; } upriv = responseData[3]; if ((responseData[1] & 0x80) != 0) *enab = 0; else *enab = 1; inputData[0] = unum; /* usually = 1 for BMC LAN */ responseLength = sizeof (responseData); status = ipmi_cmd (GET_USER_NAME, inputData, 1, responseData, &responseLength, &completionCode, fdebug); if (status != 0 || completionCode != 0) responseData[0] = 0; /*empty user name */ responseData[PSW_MAX - 1] = 0; /*for safety */ *priv = upriv; if (uname != NULL) strcpy (uname, responseData); } return (rv); } /* GetUser - get and show user configuration */ int GetUser (uchar user_num, uchar chan) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar completionCode; uchar inputData[24]; inputData[0] = chan; /*lan_ch */ inputData[1] = user_num; /* usually = 1 for BMC LAN */ responseLength = sizeof (responseData); status = ipmi_cmd (GET_USER_ACCESS, inputData, 2, responseData, &responseLength, &completionCode, fdebug); if (status == 0 && completionCode == 0) { uchar c; if (user_num == 1) { /*get max_users and enabled_users */ max_users = responseData[0] & 0x3f; enabled_users = responseData[1] & 0x3f; if (enabled_users > show_users) show_users = enabled_users; if (show_users > max_users) show_users = max_users; if (!fcanonical) SELprintf ("Users: showing %d of max %d users (%d enabled)\n", show_users, max_users, enabled_users); } if (fcanonical) SELprintf ("Channel %d User %d Access %s%c ", chan, user_num, pspace2, bdelim); else SELprintf ("User Access(chan%d,user%d): %02x %02x %02x %02x : ", chan, user_num, (uchar) responseData[0], responseData[1], responseData[2], responseData[3]); c = responseData[3]; inputData[0] = user_num; /* usually = 1 for BMC LAN */ responseLength = sizeof (responseData); status = ipmi_cmd (GET_USER_NAME, inputData, 1, responseData, &responseLength, &completionCode, fdebug); if (status != 0 || completionCode != 0) responseData[0] = 0; if (c & 0x10) printf ("IPMI, "); show_priv (c); printf (" (%s)\n", responseData); /*show user name */ } else SELprintf ("Get User Access(%d,%d), status=%x, ccode=%x\n", chan, user_num, status, completionCode); return (status); } /*end ShowUser() */ static int GetSerEntry (uchar subfunc, LAN_RECORD * pLanRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; uchar chan; uchar bset; if (pLanRecord == NULL) { if (fdebug) printf ("GetSerEntry(%d): error, output buffer is NULL\n", subfunc); return (-1); } chan = ser_ch; /* 1=EMP, 0=IPMB, 6=LAN2, 7=LAN1 */ bset = 0; inputData[0] = chan; // flags, channel 3:0 (1=EMP) inputData[1] = subfunc; // Param selector inputData[2] = bset; // Set selector inputData[3] = 0; // Block selector if (subfunc == 10) { inputData[2] = 0; inputData[3] = 1; } status = ipmi_cmd (GET_SER_CONFIG, inputData, 4, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if (completionCode) { if (fdebug) SELprintf ("GetSerEntry(%d,%d): completion code=%x\n", chan, subfunc, completionCode); } else { // dont copy first byte (Parameter revision, usu 0x11) memcpy (pLanRecord, &responseData[1], responseLength - 1); pLanRecord->data[responseLength - 1] = 0; //successful, done return (0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) SELprintf ("GetSerEntry(%d,%d): ipmi_cmd status=%x ccode=%x\n", chan, subfunc, status, completionCode); return -1; } static int GetLanEntry (uchar subfunc, uchar bset, LAN_RECORD * pLanRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status, n; uchar completionCode; uchar chan; if (pLanRecord == NULL) { if (fdebug) printf ("GetLanEntry: error, output buffer is NULL\n"); return (-1); } chan = lan_ch; /* LAN 1 = 7 */ inputData[0] = chan; // flags, channel 3:0 (LAN 1) inputData[1] = subfunc; // Param selector (3 = ip addr) inputData[2] = bset; // Set selector inputData[3] = 0; // Block selector status = ipmi_cmd (GET_LAN_CONFIG, inputData, 4, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if (completionCode) { if (fdebug) SELprintf ("GetLanEntry: completion code=%x\n", completionCode); status = completionCode; } else { // dont copy first byte (Parameter revision, usu 0x11) if (responseLength > 0) { n = responseLength - 1; memcpy (pLanRecord, &responseData[1], n); } else n = 0; pLanRecord->data[n] = 0; //successful, done return (0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) SELprintf ("GetLanEntry: ipmi_cmd status=%d completionCode=%x\n", status, completionCode); return status; } /* end GetLanEntry() */ static int SetLanEntry (uchar subfunc, LAN_RECORD * pLanRecord, int reqlen) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; if (pLanRecord == NULL) { if (fdebug) printf ("SetLanEntry(%d): error, input buffer is NULL\n", subfunc); return (-1); } if (vend_id == VENDOR_SUPERMICROX || vend_id == VENDOR_SUPERMICRO) { /* SUPERMICRO cannot set grat arp or grat arp interval */ if (subfunc == 10 || subfunc == 11) return (0); } inputData[0] = lan_ch; // flags, channel 3:0 (LAN 1) inputData[1] = subfunc; // Param selector (3 = ip addr) memcpy (&inputData[2], pLanRecord, reqlen); status = ipmi_cmd (SET_LAN_CONFIG, inputData, (uchar) (reqlen + 2), responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if (completionCode) { if (fdebug) SELprintf ("SetLanEntry(%d): completion code=%x\n", subfunc, completionCode); // responseData[0]); return (completionCode); } else { //successful, done return (0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) SELprintf ("SetLanEntry(%d): ipmi_cmd status=%d ccode=%x\n", subfunc, status, completionCode); return status; } /* end SetLanEntry() */ int GetPefEntry (uchar subfunc, ushort rec_id, PEF_RECORD * pPefRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; /* only use 3 bytes for input */ int status, n; uchar completionCode; if (pPefRecord == NULL) { if (fdebug) printf ("GetPefEntry(%d): error, output buffer is NULL\n", subfunc); return (-1); } inputData[0] = subfunc; // Parameter = Evt Filter Table inputData[1] = (uchar) rec_id; inputData[2] = 0; status = ipmi_cmd (GET_PEF_CONFIG, inputData, 3, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if (completionCode) { if (fdebug) SELprintf ("GetPefEntry(%d/%d): completion code=%x\n", subfunc, rec_id, completionCode); status = completionCode; } else { /* expect PEF record to be >=21 bytes */ if (responseLength > 1) n = responseLength - 1; else n = 0; if (n > 21) n = 21; /*only use 21 bytes */ if ((subfunc == 6) && (n < 21)) { if (fdebug) printf ("GetPefEntry(%d/%d): length %d too short\n", subfunc, rec_id, responseLength); } // dont copy first byte (Parameter revision, usu 0x11) if (n == 0) memset (pPefRecord, 0, 21); else memcpy (pPefRecord, &responseData[1], n); //successful, done return (0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) SELprintf ("GetPefEntry: ipmi_cmd status=%x completionCode=%x\n", status, completionCode); return status; } /* end GetPefEntry() */ int SetPefEntry (PEF_RECORD * pPefRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[32]; /* sizeof(PEF_RECORD) = 21 +1=22 */ int status; uchar completionCode; uchar subfunc; subfunc = 0x06; // Parameter = Evt Filter Table if (pPefRecord == NULL) { if (fdebug) printf ("SetPefEntry: error, output buffer is NULL\n"); return (-1); } // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 // 06 0c 80 01 01 00 ff ff 20 ff 6f ff 00 00 00 00 00 00 00 00 00 00 // memset(&inputData[0],0,requestData.dataLength); inputData[0] = subfunc; memcpy (&inputData[1], pPefRecord, sizeof (PEF_RECORD)); status = ipmi_cmd (SET_PEF_CONFIG, inputData, sizeof (PEF_RECORD) + 1, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if (completionCode) { if (fdebug) SELprintf ("SetPefEntry: completion code=%x\n", completionCode); // responseData[0]); status = completionCode; } else { //successful, done return (0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) SELprintf ("SetPefEntry: ipmi_cmd status=%d completion code=%x\n", status, completionCode); return (status); } /* end SetPefEntry() */ int DisablePef (int anum) { uchar iData[24]; /* sizeof(PEF_RECORD) = 21 +1=22 */ uchar rData[MAX_BUFFER_SIZE]; int rLength = MAX_BUFFER_SIZE; uchar cc; int status; if (fmBMC) { SELprintf ("mini-BMC does not support disabling BMC LAN\n"); return (-1); } else { status = SetChanAcc (lan_ch, 0x80, CHAN_ACC_DISABLE); if (fdebug) SELprintf ("SetChanAcc(lan/active), ret = %d\n", status); status = SetChanAcc (lan_ch, 0x40, CHAN_ACC_DISABLE); SELprintf ("SetChanAcc(lan), ret = %d\n", status); if (status != 0) return (status); } iData[0] = 0x01; /* PEF Control Param */ iData[1] = 0x00; /* PEF disable */ rLength = MAX_BUFFER_SIZE; status = ipmi_cmd (SET_PEF_CONFIG, iData, 2, rData, &rLength, &cc, fdebug); if (status != 0) return (status); if (cc) { SELprintf ("DisablePef[%d]: completion code=%x\n", iData[0], cc); return (-1); } if (anum != 0) { iData[0] = 0x09; /* PEF Alert Policy Table */ iData[1] = (uchar) anum; /* Policy number (default 0x01) */ iData[2] = 0x10; /* PEF LAN, policy disable */ iData[3] = 0x00; /* LAN_CH=00, default dest=00 */ iData[4] = 0x00; /* No alert string */ rLength = MAX_BUFFER_SIZE; status = ipmi_cmd (SET_PEF_CONFIG, iData, 5, rData, &rLength, &cc, fdebug); if (status != 0) return (status); if (cc) { SELprintf ("DisablePef[%d]: completion code=%x\n", iData[0], cc); return (-1); } } return (status); } int ShowPef (void) { uchar iData[24]; /* sizeof(PEF_RECORD) = 21 +1=22 */ uchar rData[MAX_BUFFER_SIZE]; int rLength = MAX_BUFFER_SIZE; uchar cc; int status, i, j; for (j = 1; j < MAX_PEFPARAMS; j++) { if (j == 4 && fmBMC) { /* fmBMC gets cc=0x80 for param 4, so skip it. */ continue; } iData[0] = (uchar) j; /* PEF Control Param */ if (j == 6 || j == 7 || j == 9) iData[1] = 1; else iData[1] = 0x00; /* PEF Set Selector */ if (j == 13) iData[2] = 1; else iData[2] = 0x00; /* PEF Block Selector */ rLength = MAX_BUFFER_SIZE; status = ipmi_cmd (GET_PEF_CONFIG, iData, 3, rData, &rLength, &cc, fdebug); if (status == 0 && cc == 0) { SELprintf ("PefParam[%d]: ", iData[0]); if (rLength > 0) for (i = 0; i < peflen[j]; i++) SELprintf ("%02x ", rData[1 + i]); SELprintf ("\n"); } else SELprintf ("PefParam[%d]: GET_PEF status=%d cc=%x\n", iData[0], status, cc); } return (status); } int EnablePef (int anum) { uchar iData[24]; /* sizeof(PEF_RECORD) = 21 +1=22 */ uchar rData[MAX_BUFFER_SIZE]; int rLength = MAX_BUFFER_SIZE; uchar cc; int status; uchar sdelay; status = SetChanAcc (lan_ch, 0x80, chan_pefon); if (fdebug) SELprintf ("SetChanAcc(lan/active), ret = %d\n", status); status = SetChanAcc (lan_ch, 0x40, chan_pefon); SELprintf ("SetChanAcc(lan), ret = %d\n", status); if (status != 0) return (status); { iData[0] = 0x01; /* PEF Control Param */ iData[1] = 0x00; /* PEF Set Selector */ iData[2] = 0x00; /* PEF Block Selector */ rLength = MAX_BUFFER_SIZE; status = ipmi_cmd (GET_PEF_CONFIG, iData, 3, rData, &rLength, &cc, fdebug); if (status != 0 || cc != 0) sdelay = 0; else sdelay = rData[1]; if (fdebug) SELprintf ("EnablePef[%d]: get cc=%x, control=%02x\n", iData[0], cc, sdelay); iData[0] = 0x01; /* PEF Control Param (0x01 or 0x05) */ iData[1] = 0x01; /* PEF enable, & no startup delay */ rLength = MAX_BUFFER_SIZE; status = ipmi_cmd (SET_PEF_CONFIG, iData, 2, rData, &rLength, &cc, fdebug); if (status != 0) return (status); if (cc) { SELprintf ("EnablePef[%d]: completion code=%x\n", iData[0], cc); return (-1); } #ifdef TEST iData[0] = 0x01; /* Serial Channel */ iData[1] = 0x13; /* Dest Com settings = 19. */ iData[2] = 0x01; /* POL Default Dest */ iData[3] = 0x60; iData[4] = 0x07; status = ipmi_cmd (SET_SER_CONFIG, iData, 5, rData, &rLength, &cc, fdebug); #endif iData[0] = 0x02; /* PEF Action Param */ iData[1] = 0x00; /* PEF Set Selector */ iData[2] = 0x00; /* PEF Block Selector */ rLength = MAX_BUFFER_SIZE; status = ipmi_cmd (GET_PEF_CONFIG, iData, 3, rData, &rLength, &cc, fdebug); if (fdebug) SELprintf ("EnablePef[%d]: get cc=%x, val=%02x\n", iData[0], cc, rData[1]); iData[0] = 0x02; /* PEF Action Param */ if (vend_id == VENDOR_INTEL) iData[1] = 0x2f; /* enable alerts, reset, power cycle/down, diag */ else iData[1] = 0x0f; /* enable alerts, reset, power cycle/down */ rLength = MAX_BUFFER_SIZE; status = ipmi_cmd (SET_PEF_CONFIG, iData, 2, rData, &rLength, &cc, fdebug); if (status != 0) return (status); if (cc) { SELprintf ("EnablePef[%d]: completion code=%x\n", iData[0], cc); return (-1); } if ((sdelay & 0x04) != 0) { /* startup delay is supported */ iData[0] = 0x03; /* PEF Startup Delay Param */ iData[1] = 0x00; /* 0 seconds, default is 0x3c (60 sec) */ rLength = MAX_BUFFER_SIZE; status = ipmi_cmd (SET_PEF_CONFIG, iData, 2, rData, &rLength, &cc, fdebug); if (fdebug) SELprintf ("EnablePef[%d]: set val=%02x cc=%x\n", iData[0], iData[1], cc); if (status != 0) return (status); if (cc) { SELprintf ("EnablePef[%d]: completion code=%x\n", iData[0], cc); // return(-1); } iData[0] = 0x04; /* PEF Alert Startup Delay Param */ iData[1] = 0x00; /* 0 seconds, default is 0x3c (60 sec) */ rLength = MAX_BUFFER_SIZE; status = ipmi_cmd (SET_PEF_CONFIG, iData, 2, rData, &rLength, &cc, fdebug); if (fdebug) SELprintf ("EnablePef[%d]: set val=%02x cc=%x\n", iData[0], iData[1], cc); if (status != 0) return (status); if (cc) { SELprintf ("EnablePef[%d]: completion code=%x\n", iData[0], cc); // return(-1); } } /*endif sdelay */ iData[0] = 0x09; /* PEF Alert Policy Table */ iData[1] = (uchar) anum; /* Policy number (default 0x01) */ iData[2] = 0x18; /* PEF LAN, always alert, policy enable */ iData[3] = (lan_ch << 4) + anum; /* LAN_CH=70, default dest=01 */ iData[4] = 0x00; /* No alert string */ rLength = MAX_BUFFER_SIZE; status = ipmi_cmd (SET_PEF_CONFIG, iData, 5, rData, &rLength, &cc, fdebug); if (fdebug) SELprintf ("EnablePef[%d]: set val=%02x cc=%x\n", iData[0], iData[1], cc); if (status != 0) return (status); if (cc) { SELprintf ("EnablePef[%d]: completion code=%x\n", iData[0], cc); return (-1); } } /*endif IPMI 1.5 */ return (status); } /* end EnablePef */ #define NBAUDS 10 static struct { unsigned char val; char str[8]; } mapbaud[NBAUDS] = { { 6, "9600"}, { 6, "9.6K"}, { 7, "19.2K"}, { 7, "19200"}, { 8, "38.4K"}, { 8, "38400"}, { 9, "57.6K"}, { 9, "57600"}, { 10, "115.2K"}, { 10, "115200"} }; static unsigned char Str2Baud (char *str) { unsigned char baud = 0; int i, n, len; len = strlen_ (str); for (i = 0; i < len; i++) /*toupper */ if (str[i] >= 'a' && str[i] <= 'z') str[i] &= 0x5F; for (i = 0; i < NBAUDS; i++) { n = strlen_ (mapbaud[i].str); if (strncmp (str, mapbaud[i].str, n) == 0) { baud = mapbaud[i].val; break; } } if (i == NBAUDS || baud == 0) { printf ("Invalid -B parameter value (%s), using 19.2K.\n", str); i = 1; /* default is 19.2K */ baud = mapbaud[i].val; /* =7 */ } if (fdebug) printf ("new baud = %02x (%s)\n", baud, mapbaud[i].str); return (baud); } static char * Baud2Str (unsigned char bin) { char *baudstr; unsigned char b; b = bin & 0x0f; switch (b) { case 6: baudstr = "9600 "; break; case 7: baudstr = "19.2k"; break; case 8: baudstr = "38.4k"; break; case 9: baudstr = "57.6k"; break; case 10: baudstr = "115.2k"; break; default: baudstr = "nobaud"; } return (baudstr); } static int BaudValid (unsigned char b) { int val = 0; switch (b) { case 6: val = 1; break; case 7: val = 1; break; case 8: val = 1; break; case 9: val = 1; break; case 10: val = 1; break; default: val = 0; break; } return (val); } /* * atomac - converts ASCII string to binary MAC address (array). * Accepts input formatted as 11:22:33:44:55:66 or 11-22-33-44-55-66. */ void atomac (uchar * array, char *instr) { int i, j, n; char *pi; j = 0; pi = instr; n = strlen_ (instr); for (i = 0; i <= n; i++) { if (instr[i] == ':') { array[j++] = htoi (pi); pi = &instr[i + 1]; } else if (instr[i] == '-') { array[j++] = htoi (pi); pi = &instr[i + 1]; } else if (instr[i] == 0) { array[j++] = htoi (pi); } if (j >= MAC_LEN) break; /*safety valve */ } if (fdebug) printf ("atomac: %02x %02x %02x %02x %02x %02x\n", array[0], array[1], array[2], array[3], array[4], array[5]); } /*end atomac() */ /* extern void atoip(uchar *array,char *instr); *from subs.c*/ void MacSetInvalid (uchar * mac) { int i; if (mac == NULL) return; for (i = 0; i < MAC_LEN; i++) { if (i == 0) mac[i] = 0xFF; else mac[i] = 0x00; } } int MacIsValid (uchar * mac) { int fvalid = 0; int i; /* check for initial invalid value of FF:00:... */ if (mac[0] == 0xff && mac[1] == 0x00) /* marked as invalid */ return (fvalid); /* check for all zeros */ for (i = 0; i < MAC_LEN; i++) if (mac[i] != 0) { /* not all zeros */ fvalid = 1; break; } return (fvalid); } int IpIsValid (uchar * ipadr) { int fvalid = 1; if (ipadr[0] == 0) fvalid = 0; return (fvalid); } int SubnetIsValid (uchar * subnet) { int fvalid = 0; /* if masking off at least one bit, say valid */ if (subnet[0] != 0) fvalid = 1; return (fvalid); } int SubnetIsSame (uchar * ip1, uchar * ip2, uchar * subnet) { int i; uchar c1, c2; for (i = 0; i < 4; i++) { c1 = ip1[i] & subnet[i]; c2 = ip2[i] & subnet[i]; if (c1 != c2) return 0; } return 1; /*same, return true */ } #ifdef WIN32 /* * Obtain network adapter information (Windows). */ PIP_ADAPTER_ADDRESSES GetAdapters () { PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL; ULONG OutBufferLength = 0; ULONG RetVal = 0, i; // The size of the buffer can be different // between consecutive API calls. // In most cases, i < 2 is sufficient; // One call to get the size and one call to get the actual parameters. // But if one more interface is added or addresses are added, // the call again fails with BUFFER_OVERFLOW. // So the number is picked slightly greater than 2. // We use i <5 in the example for (i = 0; i < 5; i++) { RetVal = GetAdaptersAddresses (AF_INET, 0, NULL, AdapterAddresses, &OutBufferLength); if (RetVal != ERROR_BUFFER_OVERFLOW) { break; } if (AdapterAddresses != NULL) { free (AdapterAddresses); } AdapterAddresses = (PIP_ADAPTER_ADDRESSES) malloc (OutBufferLength); if (AdapterAddresses == NULL) { RetVal = GetLastError (); break; } } if (RetVal == NO_ERROR) { // If successful, return pointer to structure return AdapterAddresses; } else { LPVOID MsgBuf; printf ("Call to GetAdaptersAddresses failed.\n"); if (FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, RetVal, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) & MsgBuf, 0, NULL)) { printf ("\tError: %s", MsgBuf); } LocalFree (MsgBuf); } return NULL; } /* * Set BMC MAC corresponding to current BMC IP address (Windows). */ int GetLocalMACByIP () { PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL; PIP_ADAPTER_ADDRESSES AdapterList; int result = 0; struct sockaddr_in *si; AdapterAddresses = GetAdapters (); AdapterList = AdapterAddresses; while (AdapterList) { PIP_ADAPTER_UNICAST_ADDRESS addr; addr = AdapterList->FirstUnicastAddress; if (addr == NULL) si = NULL; else si = (struct sockaddr_in *) addr->Address.lpSockaddr; if (si != NULL) { if (memcmp (&si->sin_addr.s_addr, rgmyip, 4) == 0) { if (!MacIsValid (rgmymac)) memcpy (rgmymac, AdapterList->PhysicalAddress, MAC_LEN); memcpy (osmyip, &si->sin_addr.s_addr, 4); memcpy (osmymac, AdapterList->PhysicalAddress, MAC_LEN); wcstombs (ifname, AdapterList->FriendlyName, sizeof (ifname)); result = 1; break; } } AdapterList = AdapterList->Next; } if (AdapterAddresses != NULL) { free (AdapterAddresses); } return result; } /* * Get First IP Address in Windows OS * ipaddr is 4 bytes, macaddr is 6 bytes, ipname can be 64 bytes. * (called by idiscover.c) */ int GetFirstIP (uchar * ipaddr, uchar * macadr, char *ipname, char fdbg) { PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL; PIP_ADAPTER_ADDRESSES AdapterList; struct sockaddr_in *si; uchar *psaddr; int result = -1; AdapterAddresses = GetAdapters (); AdapterList = AdapterAddresses; while (AdapterList) { PIP_ADAPTER_UNICAST_ADDRESS addr; addr = AdapterList->FirstUnicastAddress; si = (struct sockaddr_in *) addr->Address.lpSockaddr; psaddr = (uchar *) & si->sin_addr.s_addr; if ((psaddr[0] != 0) && (psaddr[0] != 169)) { if (fdbg) printf ("found IP: s_addr=%d.%d.%d.%d\n", psaddr[0], psaddr[1], psaddr[2], psaddr[3]); if (ipaddr != NULL) memcpy (ipaddr, &si->sin_addr.s_addr, 4); if (macadr != NULL) { memcpy (macadr, AdapterList->PhysicalAddress, MAC_LEN); if (fdbg) printf ("found MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", macadr[0], macadr[1], macadr[2], macadr[3], macadr[4], macadr[5]); } if (ipname != NULL) { wcstombs (ipname, AdapterList->FriendlyName, sizeof (ifname)); if (fdbg) printf ("found Adapter: %d\n", ipname); } result = 0; break; } AdapterList = AdapterList->Next; } if (AdapterAddresses != NULL) { free (AdapterAddresses); } return result; } /* * Get BMC MAC corresponding to current BMC IP address (Windows). */ int GetLocalIPByMAC (uchar * macadr) { PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL; PIP_ADAPTER_ADDRESSES AdapterList; int result = 0; struct sockaddr_in *si; AdapterAddresses = GetAdapters (); AdapterList = AdapterAddresses; while (AdapterList) { PIP_ADAPTER_UNICAST_ADDRESS addr; if (memcmp (AdapterList->PhysicalAddress, macadr, MAC_LEN) == 0) { addr = AdapterList->FirstUnicastAddress; si = (struct sockaddr_in *) addr->Address.lpSockaddr; if (fdebug) { uchar *psaddr; psaddr = (uchar *) & si->sin_addr.s_addr; printf ("mac match: rgmyip=%d.%d.%d.%d s_addr=%d.%d.%d.%d\n", rgmyip[0], rgmyip[1], rgmyip[2], rgmyip[3], psaddr[0], psaddr[1], psaddr[2], psaddr[3]); } if (!IpIsValid (rgmyip) && (fsharedMAC == 1)) /*not specified, shared */ memcpy (rgmyip, &si->sin_addr.s_addr, 4); memcpy (osmyip, &si->sin_addr.s_addr, 4); memcpy (osmymac, AdapterList->PhysicalAddress, MAC_LEN); wcstombs (ifname, AdapterList->FriendlyName, sizeof (ifname)); result = 1; break; } AdapterList = AdapterList->Next; } if (AdapterAddresses != NULL) { free (AdapterAddresses); } return result; } /* * Set MAC and IP address from given interface name (Windows). */ int GetLocalDataByIface () { PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL; PIP_ADAPTER_ADDRESSES AdapterList; int result = 0; size_t origsize, newsize, convertedChars; wchar_t *wcstring; struct sockaddr_in *si; AdapterAddresses = GetAdapters (); AdapterList = AdapterAddresses; origsize = strlen (ifname) + 1; newsize = origsize; convertedChars = 0; wcstring = (wchar_t *) malloc (sizeof (wchar_t) * newsize); if (wcstring == NULL) AdapterList = NULL; /*skip loop, do free */ else mbstowcs (wcstring, ifname, origsize); while (AdapterList) { PIP_ADAPTER_UNICAST_ADDRESS addr; if (wcsstr (AdapterList->FriendlyName, wcstring)) { printf ("Using interface: %S\n", AdapterList->FriendlyName); printf ("\t%S\n", AdapterList->Description); addr = AdapterList->FirstUnicastAddress; si = (struct sockaddr_in *) addr->Address.lpSockaddr; if (fdebug) { uchar *psaddr; psaddr = (uchar *) & si->sin_addr.s_addr; printf ("mac match: rgmyip=%d.%d.%d.%d s_addr=%d.%d.%d.%d " "fsharedMAC=%d\n", rgmyip[0], rgmyip[1], rgmyip[2], rgmyip[3], psaddr[0], psaddr[1], psaddr[2], psaddr[3], fsharedMAC); } if (!IpIsValid (rgmyip)) { /*IP not specified */ memcpy (rgmyip, &si->sin_addr.s_addr, 4); memcpy (rgmymac, AdapterList->PhysicalAddress, MAC_LEN); } memcpy (osmyip, &si->sin_addr.s_addr, 4); memcpy (osmymac, AdapterList->PhysicalAddress, MAC_LEN); /* FriendlyName == ifname already */ result = 1; break; } AdapterList = AdapterList->Next; } if (AdapterAddresses != NULL) { free (AdapterAddresses); } return result; } int FindEthNum (uchar * macadrin) { int i; uchar macadr[MAC_LEN]; memcpy (macadr, macadrin, MAC_LEN); if (fsharedMAC == 0 && vend_id == VENDOR_INTEL) { /* Intel factory assigns them this way, so use that to compare */ macadr[MAC_LEN - 1] -= 2; /*OS MAC = BMC MAC - 2 */ } i = GetLocalIPByMAC (macadr); if (i == 1) fethfound = 1; if (fdebug) /* show the local OS eth if and MAC */ printf ("FindEth: OS %s IP=%d.%d.%d.%d MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", ifname, osmyip[0], osmyip[1], osmyip[2], osmyip[3], osmymac[0], osmymac[1], osmymac[2], osmymac[3], osmymac[4], osmymac[5]); /* The actual Windows ethernet interface is determined * in Get_IPMac_Addr using ipconfig, so * init eth interface number as eth0 for Windows. */ return (0); } #elif defined(HPUX) #define INSAP 22 #define OUTSAP 24 #include #include #include #include #include #include #include #include #include #include #define bcopy(source, destination, length) memcpy(destination, source, length) #define AREA_SZ 5000 /*=* buffer length in bytes *=*/ #define GOT_CTRL 1 #define GOT_DATA 2 #define GOT_BOTH 3 #define GOT_INTR 4 #define GOT_ERR 128 static u_long ctl_area[AREA_SZ]; static u_long dat_area[AREA_SZ]; static struct strbuf ctl = { AREA_SZ, 0, (char *) ctl_area }; static struct strbuf dat = { AREA_SZ, 0, (char *) dat_area }; static char *dlpi_dev[] = { "/dev/dlpi", "" }; /*=* get a message from a stream; return type of message *=*/ static int get_msg (int fd) { int flags = 0; int res, ret; ctl_area[0] = 0; dat_area[0] = 0; ret = 0; res = getmsg (fd, &ctl, &dat, &flags); if (res < 0) { if (errno == EINTR) { return (GOT_INTR); } else { return (GOT_ERR); } } if (ctl.len > 0) { ret |= GOT_CTRL; } if (dat.len > 0) { ret |= GOT_DATA; } return (ret); } /*=* verify that dl_primitive in ctl_area = prim *=*/ static int check_ctrl (int prim) { dl_error_ack_t *err_ack = (dl_error_ack_t *) ctl_area; if (err_ack->dl_primitive != prim) { return GOT_ERR; } return 0; } /*=* put a control message on a stream *=*/ static int put_ctrl (int fd, int len, int pri) { ctl.len = len; if (putmsg (fd, &ctl, 0, pri) < 0) { return GOT_ERR; } return 0; } /*=* put a control + data message on a stream *=*/ static int put_both (int fd, int clen, int dlen, int pri) { ctl.len = clen; dat.len = dlen; if (putmsg (fd, &ctl, &dat, pri) < 0) { return GOT_ERR; } return 0; } /*=* open file descriptor and attach *=*/ static int dl_open (const char *dev, int ppa, int *fd) { dl_attach_req_t *attach_req = (dl_attach_req_t *) ctl_area; if ((*fd = open (dev, O_RDWR)) == -1) { return GOT_ERR; } attach_req->dl_primitive = DL_ATTACH_REQ; attach_req->dl_ppa = ppa; put_ctrl (*fd, sizeof (dl_attach_req_t), 0); get_msg (*fd); return check_ctrl (DL_OK_ACK); } /*=* send DL_BIND_REQ *=*/ static int dl_bind (int fd, int sap, u_char * addr) { dl_bind_req_t *bind_req = (dl_bind_req_t *) ctl_area; dl_bind_ack_t *bind_ack = (dl_bind_ack_t *) ctl_area; bind_req->dl_primitive = DL_BIND_REQ; bind_req->dl_sap = sap; bind_req->dl_max_conind = 1; bind_req->dl_service_mode = DL_CLDLS; bind_req->dl_conn_mgmt = 0; bind_req->dl_xidtest_flg = 0; put_ctrl (fd, sizeof (dl_bind_req_t), 0); get_msg (fd); if (GOT_ERR == check_ctrl (DL_BIND_ACK)) { return GOT_ERR; } bcopy ((u_char *) bind_ack + bind_ack->dl_addr_offset, addr, bind_ack->dl_addr_length); return 0; } int FindEthNum (uchar * addr) { /* Need to use DLPI for HPUX */ /*See http://cplus.kompf.de/artikel/macaddr.html */ int fd; int ppa; u_char mac_addr[25]; char **dev; int i = 0; for (dev = dlpi_dev; **dev != ''; ++dev) { for (ppa = 0; ppa < 10; ++ppa) { if (GOT_ERR != dl_open (*dev, ppa, &fd)) { if (GOT_ERR != dl_bind (fd, INSAP, mac_addr)) { // bcopy( mac_addr, addr, 6); i = ppa; if (memcmp (mac_addr, addr, MAC_LEN) == 0) { memcpy (osmymac, addr, MAC_LEN); return (ppa); } } } close (fd); } } return (i); } #else static char * get_ifreq_mac (struct ifreq *ifrq) { char *ptr; #ifdef SOLARIS ptr = (char *) &ifrq->ifr_ifru.ifru_enaddr[0]; #elif BSD ptr = (char *) &ifrq->ifr_ifru.ifru_addr.sa_data[0]; #elif MACOS static uchar mactmp[MAC_LEN]; ptr = &mactmp[0]; MacSetInvalid (ptr); #else ptr = (char *) &ifrq->ifr_hwaddr.sa_data[0]; #endif return (ptr); } extern int find_ifname (char *ifname); /*see idiscover.c */ int FindEthNum (uchar * macadrin) { /*only used for Linux */ struct ifreq ifr; int skfd; int nCurDevice; int devnum = -1; int devos = 0; uchar macadr[MAC_LEN]; uchar macsav[MAC_LEN]; uchar mactmp[MAC_LEN]; uchar ipsav[4]; char szDeviceName[16]; /* MAX_DEVICE_NAME_LENGTH + 1 */ uchar fipvalid = 0; int n; memcpy (macadr, macadrin, MAC_LEN); if (fsharedMAC == 0 && vend_id == VENDOR_INTEL) { /* Intel factory assigns them this way, so use that to compare */ macadr[MAC_LEN - 1] -= 2; /*OS MAC = BMC MAC - 2 */ } #ifdef DBG if (fdebug) { uchar *pb; pb = macadrin; printf ("input mac:%02x:%02x:%02x:%02x:%02x:%02x " "tmp mac:%02x:%02x:%02x:%02x:%02x:%02x\n", pb[0], pb[1], pb[2], pb[3], pb[4], pb[5], macadr[0], macadr[1], macadr[2], macadr[3], macadr[4], macadr[5]); } #endif n = find_ifname (szDeviceName); if (n >= 0) { n = strlen_ (szDeviceName); if (n < sizeof (ifpattn)) { strcpy (ifpattn, szDeviceName); ifpattn[n - 1] = 0; /*truncate last digit */ } if (fdebug) printf ("found ifname %s, pattern %s\n", szDeviceName, ifpattn); } if ((skfd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { if (fdebug) { perror ("socket"); return devnum; } } for (nCurDevice = 0; (nCurDevice < NUM_DEVICES_TO_CHECK) && (devnum == -1); nCurDevice++) { sprintf (szDeviceName, "%s%d", ifpattn, nCurDevice); /*eth%d */ memset ((char *) &ifr, 0, sizeof (ifr)); strcpy (ifr.ifr_name, szDeviceName); #ifdef SIOCGIFHWADDR if (ioctl (skfd, SIOCGIFHWADDR, &ifr) > 0) { if (fdebug) printf ("FindEthNum: Could not get MAC address for %s\n", szDeviceName); } else #endif { uchar *pb; pb = (uchar *) get_ifreq_mac (&ifr); #ifdef DBG if (fdebug) { printf ("%s mac: %02x:%02x:%02x:%02x:%02x:%02x\n", szDeviceName, pb[0], pb[1], pb[2], pb[3], pb[4], pb[5]); } #endif memcpy (macsav, pb, MAC_LEN); /* check if this device is configured for IP addr */ memset ((char *) &ifr, 0, sizeof (ifr)); strcpy (ifr.ifr_name, szDeviceName); ifr.ifr_addr.sa_family = AF_INET; if (ioctl (skfd, SIOCGIFADDR, &ifr) >= 0) { fipvalid = 1; memcpy (ipsav, &ifr.ifr_addr.sa_data[2], 4); } else fipvalid = 0; if (memcmp (macsav, macadr, MAC_LEN) == 0) { /*found match */ devnum = nCurDevice; memcpy (osmymac, macsav, MAC_LEN); if (fipvalid) memcpy (osmyip, ipsav, 4); break; } if (nCurDevice == 0) { /*set a default of eth0 */ devos = nCurDevice; memcpy (osmymac, macsav, MAC_LEN); if (fipvalid) memcpy (osmyip, ipsav, 4); } else if (fipvalid) { /*check if NIC1 is eth1,2,3,... */ memcpy (mactmp, osmymac, MAC_LEN); mactmp[MAC_LEN - 1] -= 1; if (memcmp (mactmp, macsav, MAC_LEN) == 0) { devos = nCurDevice; memcpy (osmymac, macsav, MAC_LEN); memcpy (osmyip, ipsav, 4); } } } /*end else */ } if (!fsetifn) { if (devnum == -1) { /*not found, use devos default */ devnum = devos; sprintf (ifname, "%s%d", ifpattn, devnum); /*eth%d */ } else { /* match was found, devnum set */ fethfound = 1; strcpy (ifname, szDeviceName); } } close (skfd); if (fdebug) /* show the local OS eth if and MAC */ printf ("FindEth: OS %s IP=%d.%d.%d.%d MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", ifname, osmyip[0], osmyip[1], osmyip[2], osmyip[3], osmymac[0], osmymac[1], osmymac[2], osmymac[3], osmymac[4], osmymac[5]); return (devnum); } #endif int show_channels (void) { int ret, rlen; uchar iData[2]; uchar rData[10]; uchar cc, mtype; int j; int rv = -1; for (j = 1; j < MAXCHAN; j++) { rlen = sizeof (rData); iData[0] = (uchar) j; /*channel # */ memset (rData, 0, 9); /*initialize recv data */ ret = ipmi_cmd (GET_CHANNEL_INFO, iData, 1, rData, &rlen, &cc, fdebug); if (rv != 0) rv = ret; if (ret == 0xcc || cc == 0xcc) /* special case for ipmi_lan */ continue; if (ret != 0) { if (fdebug) printf ("get_chan_info rc = %x\n", ret); break; } mtype = rData[1]; /* channel medium type */ switch (mtype) { case 4: printf ("channel[%d] type = lan\n", j); break; /*802.3 LAN type */ case 5: printf ("channel[%d] type = serial\n", j); break; case 7: printf ("channel[%d] type = pci_smbus\n", j); break; case 12: printf ("channel[%d] type = system_interface\n", j); break; default: printf ("channel[%d] type = other %d\n", j, mtype); break; } rv = 0; } /*end for j */ return (rv); } /* * GetBmcEthDevice * Attempt to auto-detect the BMC LAN channel and matching OS eth port. * INPUT: lan_parm = lan channel from user -L option, 0xFF if not specified * OUTPUT: lan_ch is set to BMC LAN channel number * if success, returns index of OS eth port (0, 1, ...). * if no lan channels found, returns -2. * if other error, returns -1. */ int GetBmcEthDevice (uchar lan_parm, uchar * pchan) { LAN_RECORD LanRecord; int devnum = -1; int ret; uchar bmcMacAddress[MAC_LEN]; /*MAC_LEN = 6 */ int rlen; uchar iData[2]; uchar rData[10]; uchar cc; int i = 0; int j, jstart, jend, jlan; uchar mtype; uchar *pb; int fchgmac; // int found = 0; /* Find the LAN channel(s) via Channel Info */ if (lan_parm < MAXCHAN) { /* try user-specified channel only */ lan_ch = lan_parm; jstart = lan_parm; jend = lan_parm + 1; } else { jstart = 1; jend = MAXCHAN; } memset (bmcMacAddress, 0xff, sizeof (bmcMacAddress)); /*initialize to invalid */ for (j = jstart; j < jend; j++) { rlen = sizeof (rData); iData[0] = (uchar) j; /*channel # */ memset (rData, 0, 9); /*initialize recv data */ ret = ipmi_cmd (GET_CHANNEL_INFO, iData, 1, rData, &rlen, &cc, fdebug); if (ret == 0xcc || cc == 0xcc) /* special case for ipmi_lan */ continue; if (ret != 0) { if (fdebug) printf ("get_chan_info rc = %x\n", ret); break; } mtype = rData[1]; /* channel medium type */ if (mtype == 4) { /* 802.3 LAN type */ if (fdebug) printf ("chan[%d] = lan\n", j); jlan = lan_ch; /*save prev lan chan */ /* Get BMC MAC for this LAN channel. */ /* Note: BMC MAC may not be valid yet. */ lan_ch = (uchar) j; /*set lan channel for GetLanEntry */ ret = GetLanEntry (5 /*MAC_ADDRESS_LAN_PARAM */ , 0, &LanRecord); if (ret != 0) { lan_ch = (uchar) jlan; /*restore lan_ch */ printf ("GetBmcEthDevice: GetLanEntry(5) failed\n"); return devnum; } else { pb = &LanRecord.data[0]; if (fdebug) printf ("chan[%d] BMC MAC %x:%x:%x:%x:%x:%x\n", j, pb[0], pb[1], pb[2], pb[3], pb[4], pb[5]); fchgmac = 0; /* use the lowest valid lan channel MAC address */ if (!MacIsValid (bmcMacAddress)) /* old MAC not valid */ fchgmac = 1; else if (MacIsValid (pb) && /* new MAC is valid and */ (memcmp (bmcMacAddress, pb, sizeof (bmcMacAddress)) > 0)) fchgmac = 1; /* new MAC lower */ /* if no -L 3 and this is gcm, do not pick it. */ if ((j == gcm_ch) && (lan_parm == PARM_INIT)) fchgmac = 0; if (fchgmac) { /* pick this channel & MAC */ memcpy (bmcMacAddress, pb, sizeof (bmcMacAddress)); lan_ch = (uchar) j; } else lan_ch = (uchar) jlan; /*restore prev lan chan */ } i++; /* i = num lan channels found */ } else if (mtype == 5) { /* serial type */ if (fdebug) printf ("chan[%d] = serial\n", j); ser_ch = (uchar) j; /* set to last serial channel */ } else if (mtype == 7) { /* PCI SMBus */ if (fdebug) printf ("chan[%d] = pci_smbus\n", j); } else if (mtype == 12) { /* system interface */ if (fdebug) printf ("chan[%d] = system_interface\n", j); } else if (mtype == 1) { /* IPMB */ if (fdebug) printf ("chan[%d] = IPMB\n", j); } else /* other channel medium types, see IPMI 1.5 Table 6-3 */ if (fdebug) printf ("chan[%d] = %d\n", j, mtype); } if (i == 0) return (-2); /* no lan channels found */ if (fdebug) printf ("lan_ch detected = %d\n", lan_ch); /* This will work if the BMC MAC is shared with the OS */ /* Otherwise, wait until we get the eth dev from the gateway below */ devnum = FindEthNum (bmcMacAddress); if (fdebug) printf ("GetBmcEthDevice: channel %d, %s%d\n", lan_ch, ifpattn, devnum); if (pchan != NULL) *pchan = lan_ch; return devnum; } /* file_grep/findmatch - No longer used here, see ievents.c */ /* * Get_Mac * This routine finds a MAC address from a given IP address. * Usually for the Alert destination. * It uses ARP cache to do this. */ #if defined(WIN32) int Get_Mac (uchar * ipadr, uchar * macadr, char *nodname) { DWORD dwRetVal; IPAddr DestIp = 0; IPAddr SrcIp = 0; /* default for src ip */ ULONG MacAddr[2]; /* for 6-byte hardware addresses */ ULONG PhysAddrLen = MAC_LEN; /* default to length of six bytes */ BYTE *bPhysAddr; if (!IpIsValid (ipadr)) { if (fdebug) printf ("Get_Mac: invalid IP addr\n"); return 1; /*error */ } memcpy (&DestIp, ipadr, 4); /* invoke system ARP query */ dwRetVal = SendARP (DestIp, SrcIp, MacAddr, &PhysAddrLen); if (dwRetVal == NO_ERROR) { /* no error - get the MAC */ bPhysAddr = (BYTE *) & MacAddr; if (PhysAddrLen) { memcpy (macadr, bPhysAddr, MAC_LEN); } else printf ("Warning: SendArp completed successfully, but returned length=0\n"); } else if (dwRetVal == ERROR_GEN_FAILURE) { /* MAC not available in this network - get gateway MAC */ memcpy (macadr, rggwymac, MAC_LEN); } else { /* other errors */ printf ("Error: SendArp failed with error: %d", dwRetVal); switch (dwRetVal) { case ERROR_INVALID_PARAMETER: printf (" (ERROR_INVALID_PARAMETER)\n"); break; case ERROR_INVALID_USER_BUFFER: printf (" (ERROR_INVALID_USER_BUFFER)\n"); break; case ERROR_BAD_NET_NAME: printf (" (ERROR_GEN_FAILURE)\n"); break; case ERROR_BUFFER_OVERFLOW: printf (" (ERROR_BUFFER_OVERFLOW)\n"); break; case ERROR_NOT_FOUND: printf (" (ERROR_NOT_FOUND)\n"); break; default: printf ("\n"); break; } return 1; } return 0; } /* end Get_Mac() for WIN32 */ #elif defined(SOLARIS) int Get_Mac (uchar * ipadr, uchar * macadr, char *nodename) { FILE *fparp; char buff[1024]; /* char arpfile[] = "/proc/net/arp"; */ char alertfile[] = "/tmp/dest.arping"; char arping_cmd[128]; char *pb, *pm; int num, i; int foundit = 0; int ret = 0; if (IpIsValid (ipadr)) { /* if valid IP address */ sprintf (arping_cmd, "ping %d.%d.%d.%d >/dev/null; arp -a -n |grep %d.%d.%d.%d >%s\n", ipadr[0], ipadr[1], ipadr[2], ipadr[3], ipadr[0], ipadr[1], ipadr[2], ipadr[3], alertfile); } else if (nodename != NULL) { /*if valid nodename */ sprintf (arping_cmd, "ping %s >/dev/null; arp -a |grep %s >%s\n", nodename, nodename, alertfile); } else ret = -1; if (ret == 0) { /* if valid IP address */ /* make sure the destination is in the arp cache */ if (fdebug) printf ("%s", arping_cmd); system (arping_cmd); fparp = fopen (alertfile, "r"); if (fparp == NULL) { fprintf (stdout, "Get_Mac: Cannot open %s, errno = %d\n", alertfile, get_errno ()); ret = -1; } else { /* sample output: */ /* e1000g0 cooper9 255.255.255.255 o 00:07:e9:06:55:c8 */ while (fgets (buff, 1023, fparp)) { /* should only run through loop once */ num = strcspn (buff, " \t"); /* skip 1st word ("e1000g0") */ i = strspn (&buff[num], " \t"); /* skip whitespace */ pb = &buff[num + i]; num = strcspn (pb, " \t"); /* skip 2nd word (nodename/IP) */ i = strspn (&pb[num], " \t"); /* skip whitespace */ pb += (num + i); pm = &pb[25]; /* Now pb[25] has the MAC address */ { /*validate new address? */ if (fdebug) printf ("Get_Mac: mac=%s\n", pm); foundit = 1; if (!MacIsValid (macadr)) atomac (macadr, pm); break; } } /*end while */ fclose (fparp); } /*end else file opened */ } /*endif valid IP */ if (foundit == 0) { /* no errors, but no mac reply */ if (MacIsValid (rggwymac) && !MacIsValid (macadr)) /* this is useful if the ipadr is not in the local subnet */ memcpy (macadr, rggwymac, 6); /* get to it from the default gateway */ } return (ret); } /*end Get_Mac for Solaris */ #elif defined(BSD) int Get_Mac (uchar * ipadr, uchar * macadr, char *nodename) { FILE *fparp; char buff[1024]; /* char arpfile[] = "/proc/net/arp"; */ char alertfile[] = "/tmp/dest.arping"; char arping_cmd[128]; char *pb, *pm; int num, i, j; int foundit = 0; int ret = 0; if (IpIsValid (ipadr)) { /* if valid IP address */ sprintf (arping_cmd, "ping -c2 %d.%d.%d.%d >/dev/null; arp -a -n |grep %d.%d.%d.%d >%s\n", ipadr[0], ipadr[1], ipadr[2], ipadr[3], ipadr[0], ipadr[1], ipadr[2], ipadr[3], alertfile); } else if (nodename != NULL) { /*if valid nodename */ sprintf (arping_cmd, "ping -c2 %s >/dev/null; arp -a |grep %s >%s\n", nodename, nodename, alertfile); } else ret = -1; if (ret == 0) { /* if valid IP address */ /* make sure the destination is in the arp cache */ if (fdebug) printf ("%s", arping_cmd); system (arping_cmd); fparp = fopen (alertfile, "r"); if (fparp == NULL) { fprintf (stdout, "Get_Mac: Cannot open %s, errno = %d\n", alertfile, get_errno ()); ret = -1; } else { /* sample output of arp -a -n: */ /* ? (192.168.1.200) at 00:0e:0c:e5:df:65 on em0 [ethernet] */ /* sample output of arp -a: */ /* telcoserv (192.168.1.200) at 00:0e:0c:e5:df:65 on em0 [ethernet] */ while (fgets (buff, 1023, fparp)) { /* should only run through loop once */ pb = &buff[0]; for (j = 0; j < 3; j++) { /* skip 3 words */ num = strcspn (pb, " \t"); /* skip jth word */ i = strspn (&pb[num], " \t"); /* skip whitespace */ pb += (num + i); } pm = &pb[0]; /* Now pb[0] has the MAC address */ { /* no need to validate new address */ if (fdebug) printf ("Get_Mac: mac=%s\n", pm); foundit = 1; if (!MacIsValid (macadr)) atomac (macadr, pm); break; } } /*end while */ fclose (fparp); } /*end else file opened */ } /*endif valid IP */ if (foundit == 0) { /* no errors, but no mac reply */ if (MacIsValid (rggwymac) && !MacIsValid (macadr)) /* this is useful if the ipadr is not in the local subnet */ memcpy (macadr, rggwymac, 6); /* get to it from the default gateway */ } return (ret); } /*end Get_Mac for BSD */ #else int Get_Mac (uchar * ipadr, uchar * macadr, char *nodename) { /* Get_Mac for Linux */ FILE *fparp; char buff[1024]; /* char arpfile[] = "/proc/net/arp"; */ char alertfile[] = "/tmp/dest.arping"; char arping_cmd[128]; char *pb, *pm, *px; int num, i; int foundit = 0; int ret = 0; char *_ifname; if (strcmp (ifname, "gcm") == 0) _ifname = ifname0; /*see gcm_ch instead */ else _ifname = ifname; /* Get a MAC address for a given IP address or nodename */ if (IpIsValid (ipadr)) { /* if valid IP address */ sprintf (arping_cmd, "arping -I %s -c 2 %d.%d.%d.%d |grep reply |tail -n1 >%s\n", _ifname, ipadr[0], ipadr[1], ipadr[2], ipadr[3], alertfile); } else if (nodename != NULL) { /*if valid nodename */ sprintf (arping_cmd, "arping -I %s -c 2 %s |grep reply |tail -n1 >%s\n", _ifname, nodename, alertfile); } else ret = -1; if (ret == 0) { /* if valid IP address */ /* make sure the destination is in the arp cache */ if (fdebug) printf ("%s", arping_cmd); ret = system (arping_cmd); fparp = fopen (alertfile, "r"); if (fparp == NULL) { fprintf (stdout, "Get_Mac: Cannot open %s, errno = %d\n", alertfile, get_errno ()); ret = -1; } else { ret = 0; while (fgets (buff, 1023, fparp)) { /* should only run through loop once */ num = strcspn (buff, " \t"); /* skip 1st word ("Unicast") */ i = strspn (&buff[num], " \t"); pb = &buff[num + i]; if (strncmp (pb, "reply", 5) == 0) { /* valid output */ /* Find the ip address */ pb += 6 + 5; /* skip "reply from " */ num = strcspn (pb, " \t"); pb[num] = 0; if (fdebug) printf ("Get_Mac: ip=%s\n", pb); /* IP address should already match input param */ if (!IpIsValid (ipadr)) /* had nodname only */ atoip (ipadr, pb); /* fill in ipadr */ /* Now find the mac address */ pm = strchr (&pb[num + 1], '['); if (pm == NULL) pm = &pb[num + 2]; /* just in case */ pm++; px = strchr (pm, ']'); if (px == NULL) px = pm + 17; /* just in case */ px[0] = 0; if (fdebug) printf ("Get_Mac: mac=%s\n", pm); foundit = 1; if (!MacIsValid (macadr)) atomac (macadr, pm); break; } } /*end while */ fclose (fparp); } /*end else file opened */ } /*endif valid IP */ if (foundit == 0) { /* no errors, but no mac reply */ if (MacIsValid (rggwymac) && !MacIsValid (macadr)) /* this is useful if the ipadr is not in the local subnet */ memcpy (macadr, rggwymac, 6); /* get to it from the default gateway */ } return (ret); } /* end Get_Mac() for Linux */ #endif #ifdef WIN32 /* * Set subnet mask based on current IP address (Windows). */ int SetSubnetMask () { PMIB_IPADDRTABLE pIPAddrTable; unsigned int i; DWORD dwSize = 0, dwRetVal; LPVOID lpMsgBuf; pIPAddrTable = (MIB_IPADDRTABLE *) malloc (sizeof (MIB_IPADDRTABLE)); if (pIPAddrTable) { // Make an initial call to GetIpAddrTable to get the // necessary size into the dwSize variable if (GetIpAddrTable (pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { free (pIPAddrTable); pIPAddrTable = (MIB_IPADDRTABLE *) malloc (dwSize); } } else printf ("Memory allocation failed.\n"); if (pIPAddrTable) { // Make a second call to GetIpAddrTable to get the // actual data we want if ((dwRetVal = GetIpAddrTable (pIPAddrTable, &dwSize, 0)) == NO_ERROR) { for (i = 0; i < pIPAddrTable->dwNumEntries; ++i) { if (memcmp (&(pIPAddrTable->table[i].dwAddr), rgmyip, 4) == 0) { memcpy (rgsubnet, &(pIPAddrTable->table[i].dwMask), 4); free (pIPAddrTable); return 1; } } } else { if (FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) & lpMsgBuf, 0, NULL)) { printf ("\tError: %s", lpMsgBuf); } printf ("Call to GetIpAddrTable failed.\n"); } } if (pIPAddrTable) free (pIPAddrTable); return 0; } /* * Extract gateway address from routing table (Windows). */ int SetDefaultGateway () { PMIB_IPFORWARDTABLE pIpForwardTable; DWORD dwRetVal, dwSize; unsigned int nord_mask; unsigned int nord_ip; unsigned int nord_net; unsigned int i; nord_mask = *((unsigned int *) rgsubnet); nord_ip = *((unsigned int *) rgmyip); nord_net = nord_ip & nord_mask; pIpForwardTable = (MIB_IPFORWARDTABLE *) malloc (sizeof (MIB_IPFORWARDTABLE)); if (pIpForwardTable == NULL) { printf ("Error allocating memory\n"); return 0; } dwSize = 0; if (GetIpForwardTable (pIpForwardTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { free (pIpForwardTable); pIpForwardTable = (MIB_IPFORWARDTABLE *) malloc (dwSize); if (pIpForwardTable == NULL) { printf ("Error allocating memory\n"); return 0; } } /* * Note that the IPv4 addresses returned in * GetIpForwardTable entries are in network byte order */ if ((dwRetVal = GetIpForwardTable (pIpForwardTable, &dwSize, 0)) == NO_ERROR) { for (i = 0; i < (int) pIpForwardTable->dwNumEntries; i++) { unsigned int gwaddr = pIpForwardTable->table[i].dwForwardNextHop; if (nord_net == (gwaddr & nord_mask) && nord_ip != gwaddr) { /* searching for gateways from our network with different address than ours */ memcpy (rggwyip, &gwaddr, 4); return 0; } } free (pIpForwardTable); return 1; } else { printf ("\tGetIpForwardTable failed.\n"); free (pIpForwardTable); return 0; } } /*endif WIN32*/ #endif /* * Get_IPMac_Addr * This routine finds the IP and MAC for the local interface, * the default gateway, and SNMP alert destination from the * BMC and OS information. * * Linux snmpd.conf locations (see ipmiutil.spec): * RedHat, MontaVista: /etc/snmp/snmpd.conf * SuSE SLES 8: /etc/ucdsnmpd.conf * SuSE SLES 9: /etc/snmpd.conf */ #ifdef WIN32 int Get_IPMac_Addr () { /*for Windows */ char ipstr[] = "IP Address"; char macstr[] = "Physical Address"; char gwystr[] = "Default Gateway"; char substr[] = "Subnet Mask"; int found = 0; char fgetmac; if (IpIsValid (rgmyip)) { /* user-specified ip, get mac */ if (fdebug) printf ("User IP was specified\n"); if (!MacIsValid (rgmymac)) { /* no user-specified MAC, get it from IP */ if (fdebug) printf ("No user MAC specified\n"); if (!GetLocalMACByIP ()) { /* couldn't get MAC from IP, get old one */ if (fdebug) printf ("No MAC from IP, use old\n"); if (IpIsValid (bmcmyip) && MacIsValid (bmcmymac)) { printf ("Using current BMC MAC %02x:%02x:%02x:%02x:%02x:%02x\n", bmcmymac[0], bmcmymac[1], bmcmymac[2], bmcmymac[3], bmcmymac[4], bmcmymac[5]); memcpy (rgmymac, bmcmymac, MAC_LEN); } else { printf ("Failed to obtain valid MAC\n"); } } else { printf ("Using adapter MAC %02x:%02x:%02x:%02x:%02x:%02x\n", rgmymac[0], rgmymac[1], rgmymac[2], rgmymac[3], rgmymac[4], rgmymac[5]); } } else { /* user MAC available */ printf ("Using user MAC %02x:%02x:%02x:%02x:%02x:%02x\n", rgmymac[0], rgmymac[1], rgmymac[2], rgmymac[3], rgmymac[4], rgmymac[5]); } } else { /* no user-specified IP */ if (fdebug) printf ("No user IP specified\n"); if (!MacIsValid (rgmymac)) { /* no user-specified MAC, get it from interface */ if (!GetLocalDataByIface ()) { /* use existing MAC an IP */ printf ("Using current BMC IP %d.%d.%d.%d\n", bmcmyip[0], bmcmyip[1], bmcmyip[2], bmcmyip[3]); memcpy (rgmyip, bmcmyip, 4); printf ("Using current BMC MAC %02x:%02x:%02x:%02x:%02x:%02x\n", bmcmymac[0], bmcmymac[1], bmcmymac[2], bmcmymac[3], bmcmymac[4], bmcmymac[5]); memcpy (rgmymac, bmcmymac, MAC_LEN); } } else { /* user-specified MAC */ if (!GetLocalIPByMAC (rgmymac)) { /* use existing MAC and IP */ printf ("Using current BMC IP %d.%d.%d.%d\n", bmcmyip[0], bmcmyip[1], bmcmyip[2], bmcmyip[3]); memcpy (rgmyip, bmcmyip, 4); printf ("Using current BMC MAC %02x:%02x:%02x:%02x:%02x:%02x\n", bmcmymac[0], bmcmymac[1], bmcmymac[2], bmcmymac[3], bmcmymac[4], bmcmymac[5]); memcpy (rgmymac, bmcmymac, MAC_LEN); } } } if (rghostname[0] == 0) { /*hostname not specified */ if (!fipmilan) gethostname (rghostname, sizeof (rghostname)); } if (fdebug) /* show the local OS eth if and MAC */ printf ("OS %s IP=%d.%d.%d.%d %s MAC=%02x:%02x:%02x:%02x:%02x:%02x used for arp\n", ifname, osmyip[0], osmyip[1], osmyip[2], osmyip[3], rghostname, osmymac[0], osmymac[1], osmymac[2], osmymac[3], osmymac[4], osmymac[5]); if (!SubnetIsValid (rgsubnet)) { SetSubnetMask (); } if (!IpIsValid (rggwyip)) { /* if gwy ip not user-specified */ SetDefaultGateway (); } if (lan_ch == gcm_ch) { if (SubnetIsSame (rgmyip, rggwyip, rgsubnet)) fgetmac = 1; else fgetmac = 0; } else fgetmac = 1; if (fgetmac) { if (IpIsValid (rggwyip) && !MacIsValid (rggwymac)) /*gwy mac not specified */ Get_Mac (rggwyip, rggwymac, NULL); if (IpIsValid (rggwy2ip) && !MacIsValid (rggwy2mac)) /*gwy2 mac not valid */ Get_Mac (rggwy2ip, rggwy2mac, NULL); } return (0); } /* end Get_IPMac_Addr for Windows */ #elif defined(HPUX) int Get_IPMac_Addr () { /*for HP-UX */ return (-1); } #else int Get_IPMac_Addr () { /*for Linux */ #if defined(SOLARIS) char rtfile[] = "/tmp/route"; char snmpfile[] = "/etc/snmp/conf/snmpd.conf"; #elif defined(BSD) char rtfile[] = "/tmp/route"; char snmpfile[] = "/etc/snmpd.config"; #else char rtfile[] = "/proc/net/route"; char snmpfile[] = "/etc/snmp/snmpd.conf"; #endif // char alertfile[] = "/tmp/alert.arping"; // FILE *fparp; FILE *fprt; int fd = -1; int skfd; uchar *pc; int rc = 0; int i, j; uchar bnetadr[4]; uchar bgateadr[4]; char gate_addr[128]; char iface[16]; char defcommunity[19] = "public"; char buff[1024]; char alertname[60]; int num, nmatch; struct ifreq ifr; char *_ifname; char fgetmac; /* Get the IP address and associated MAC address specified. */ /* Local for ethN; Default Gateway; Alert Destination */ /* Get the default gateway IP */ #if defined(SOLARIS) || defined(BSD) char rtcmd[80]; sprintf (rtcmd, "netstat -r -n |grep default |awk '{ print $2 }' >%s", rtfile); system (rtcmd); /* use rtfile output from netstat -r, see also /etc/defaultroute */ fprt = fopen (rtfile, "r"); if (fprt == NULL) { fprintf (stdout, "netstat: Cannot open %s, errno = %d\n", rtfile, get_errno ()); } else { while (fgets (buff, 1023, fprt)) { if ((buff[0] > '0') && (buff[0] <= '9')) { /*valid */ atoip (bgateadr, buff); if (fdebug) printf ("default gateway: %s, %d.%d.%d.%d %s\n", buff, bgateadr[0], bgateadr[1], bgateadr[2], bgateadr[3], ifname); if (!IpIsValid (rggwyip)) /* if not user-specified */ memcpy (rggwyip, bgateadr, 4); break; } } fclose (fprt); } /*end-else good open */ #else /* cat /proc/net/route and save Gwy if Dest == 0 and Gateway != 0 */ fprt = fopen (rtfile, "r"); if (fprt == NULL) { fprintf (stdout, "route: Cannot open %s, errno = %d\n", rtfile, get_errno ()); } else { char rtfmt[] = "%16s %128s %128s %X %d %d %d %128s %d %d %d\n"; int iflags, refcnt, use, metric, mss, window, irtt; char mask_addr[128], net_addr[128]; uint *pnet; uint *pgate; pnet = (uint *) & bnetadr[0]; pgate = (uint *) & bgateadr[0]; while (fgets (buff, 1023, fprt)) { num = sscanf (buff, rtfmt, iface, net_addr, gate_addr, &iflags, &refcnt, &use, &metric, mask_addr, &mss, &window, &irtt); if (num < 10 || !(iflags & RTF_UP)) continue; j = 6; for (i = 0; i < 4; i++) { bnetadr[i] = htoi (&net_addr[j]); bgateadr[i] = htoi (&gate_addr[j]); j -= 2; } if ((*pnet == 0) && (*pgate != 0)) { /* found default gateway */ if (fdebug) printf ("default gateway: %s, %d.%d.%d.%d %s\n", gate_addr, bgateadr[0], bgateadr[1], bgateadr[2], bgateadr[3], iface); if (!IpIsValid (rggwyip)) /* if not user-specified */ memcpy (rggwyip, bgateadr, 4); _ifname = iface; /*use this iface for gwy mac */ if (!fsetifn) strncpy (ifname, iface, 16); break; } } /*end while */ fclose (fprt); } /*end-else good open */ #endif /* Create a channel to the NET kernel. */ if ((skfd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { perror ("socket"); return (-3); } /* Find a valid local BMC MAC Address */ if (lan_ch == gcm_ch) { /* GCM has its own unique mac address */ if (!MacIsValid (rgmymac)) { if (MacIsValid (bmcmymac)) { memcpy (rgmymac, bmcmymac, MAC_LEN); /*use existing */ } else { /*error */ printf ("invalid MAC address for gcm\n"); } } /*else use rgmymac if specified */ _ifname = iface; /*use the iface from gwy (e.g. eth0) */ fsharedMAC = 0; /*gcm has separate NIC, separate MAC */ // fd = -1; fd = skfd; // get_socket_for_af(AF_INET) below; } else { /*else not gcm */ if (!fsetifn && !fethfound) { /*do not have ifname yet */ i = FindEthNum (bmcmymac); if (i >= 0) sprintf (ifname, "%s%d", ifpattn, i); } ifr.ifr_addr.sa_family = AF_INET; if (fdebug) printf ("getipmac: ifname=%s\n", ifname); _ifname = ifname; strcpy (ifr.ifr_name, _ifname); #ifdef SIOCGIFHWADDR /* Get the local if HWADDR (MAC Address) from OS */ if (ioctl (skfd, SIOCGIFHWADDR, &ifr) < 0) { if (fdebug) printf ("ioctl(SIOCGIFHWADDR,%s) error, errno = %d\n", _ifname, get_errno ()); } else memcpy (osmymac, get_ifreq_mac (&ifr), MAC_LEN); /*OS mac */ #endif if (memcmp (bmcmymac, osmymac, MAC_LEN) == 0) { /* osmymac and ifname were set above by FindEthNum */ printf ("\tBMC shares IP/MAC with OS NIC %s\n", _ifname); fsharedMAC = 1; } /* else fsharedMAC = 0; */ if (fsharedMAC == 0) { /* then BMC has separate MAC */ if (!MacIsValid (rgmymac) && MacIsValid (bmcmymac)) memcpy (rgmymac, bmcmymac, MAC_LEN); /*use existing */ } else { /* else OS & BMC share a MAC */ /* Use the local if HWADDR (MAC Address) from OS */ if (!MacIsValid (rgmymac)) { /* if not user-specified */ if (MacIsValid (bmcmymac)) memcpy (rgmymac, bmcmymac, MAC_LEN); /*use existing */ else memcpy (rgmymac, osmymac, MAC_LEN); /*use OS mac */ } } fd = skfd; // get_socket_for_af(AF_INET) below; } if (fd >= 0) { /* if valid fd, find OS IP */ strcpy (ifr.ifr_name, _ifname); ifr.ifr_addr.sa_family = AF_INET; /* Get the IFADDR (IP Address) from OS */ if (ioctl (fd, SIOCGIFADDR, &ifr) < 0) { int err; err = get_errno (); /* errno 99 here means that eth0 is not enabled/up/defined. */ if (err == 99) printf ("ioctl(SIOCGIFADDR) error, %s not enabled\n", _ifname); else if (fdebug) printf ("ioctl(SIOCGIFADDR,%s) error, errno=%d\n", _ifname, err); } else { /* got the local OS IP successfully */ pc = (uchar *) & ifr.ifr_addr.sa_data[2]; if (fdebug) printf ("%s addr = %d.%d.%d.%d\n", _ifname, pc[0], pc[1], pc[2], pc[3]); memcpy (osmyip, pc, 4); if (!IpIsValid (rgmyip) && (fsharedMAC == 1)) /*not specified, shared */ memcpy (rgmyip, osmyip, 4); /* get the local OS netmask */ strcpy (ifr.ifr_name, _ifname); if (ioctl (fd, SIOCGIFNETMASK, &ifr) < 0) { if (fdebug) printf ("ioctl(SIOCGIFNETMASK) error, errno=%d\n", get_errno ()); /* if leave invalid, will use default rgsubnet */ } else { // sizeof(struct sockaddr) pc = (uchar *) & ifr.ifr_netmask.sa_data[2]; if (fdebug) printf ("subnet = %d.%d.%d.%d \n", pc[0], pc[1], pc[2], pc[3]); memcpy (ossubnet, pc, 4); if (!SubnetIsValid (rgsubnet) && fsharedMAC) /*not specified */ memcpy (rgsubnet, pc, 4); } #ifdef SIOCGIFHWADDR /* Get the localhost OS HWADDR (MAC Address) */ if (ioctl (fd, SIOCGIFHWADDR, &ifr) < 0) { if (fdebug) printf ("ioctl(SIOCGIFHWADDR,%s) error, errno = %d\n", _ifname, get_errno ()); } else memcpy (osmymac, get_ifreq_mac (&ifr), MAC_LEN); /*OS mac */ #endif } } close (skfd); /* done, close the socket */ if (rghostname[0] == 0) { /*hostname not specified */ if (!fipmilan) gethostname (rghostname, sizeof (rghostname)); } if (fdebug) /* show the local OS eth if and MAC */ printf ("OS %s IP=%d.%d.%d.%d %s MAC=%02x:%02x:%02x:%02x:%02x:%02x used for arp\n", _ifname, osmyip[0], osmyip[1], osmyip[2], osmyip[3], rghostname, osmymac[0], osmymac[1], osmymac[2], osmymac[3], osmymac[4], osmymac[5]); if (!IpIsValid (rgmyip) && IpIsValid (bmcmyip)) { /* If no user-specified IP and there is a valid IP already in the * BMC LAN configuration, use the existing BMC LAN IP. */ memcpy (rgmyip, bmcmyip, 4); if (fdebug) printf ("Using current IP %d.%d.%d.%d\n", bmcmyip[0], bmcmyip[1], bmcmyip[2], bmcmyip[3]); } /* Get the default gateway MAC */ if (lan_ch == gcm_ch) { if (SubnetIsSame (osmyip, rggwyip, ossubnet)) fgetmac = 1; else { /* gateway is not on the same subnet as RMM/GCM */ fgetmac = 0; /*don't try to get mac if not the same subnet */ if ((fset_ip & GWYIP) == 0) memset (rggwyip, 0, 4); } } else fgetmac = 1; if (fgetmac && IpIsValid (rggwyip) && !MacIsValid (rggwymac)) Get_Mac (rggwyip, rggwymac, NULL); /*gwy mac not specified, so get mac */ /* Get the Alert Destination IP */ /* By default, attempt to obtain this from /etc/snmp/snmpd.conf. */ /* cat /etc/snmp/snmpd.conf | grep trapsink |tail -n1 | cut -f2 -d' ' */ alertname[0] = 0; /* default to null string */ fprt = fopen (snmpfile, "r"); if (fprt == NULL) { printf ("snmp: Cannot open %s, errno = %d\n", snmpfile, get_errno ()); } else { // char snmpfmt[] = "%20s %60s\n"; // char *keywd, *value; while (fgets (buff, 1023, fprt)) { /* parse each line */ if (buff[0] == '#') continue; /*skip comment lines */ /* skip leading whitespace here */ j = strspn (&buff[0], " \t"); if (strncmp (&buff[j], "com2sec", 7) == 0) { /* found community line */ /* usu like this: "com2sec demouser default public" */ i = j + 7; for (j = 0; j < 3; j++) { num = strspn (&buff[i], " \t"); i += num; num = strcspn (&buff[i], " \t\r\n"); if (j < 2) i += num; } buff[i + num] = 0; if (fsetcommunity == 0) { /* if not user-specified */ strcpy (rgcommunity, &buff[i]); strcpy (defcommunity, &buff[i]); } } #ifdef BSD if (strncmp (&buff[j], "traphost :=", 11) == 0) nmatch = 11; else nmatch = 0; #else if (strncmp (&buff[j], "trapsink", 8) == 0) nmatch = 8; else if (strncmp (&buff[j], "trap2sink", 9) == 0) nmatch = 9; else nmatch = 0; #endif if (nmatch > 0) { /* found trapsink line match */ if (fdebug) printf ("%s: %s", snmpfile, &buff[j]); num = strspn (&buff[j + nmatch], " \t"); i = j + nmatch + num; if (buff[i] == '`') continue; num = strcspn (&buff[i], " \t\r\n"); strncpy (alertname, &buff[i], num); /* save alert destination */ alertname[num] = 0; i += num; num = strspn (&buff[i], " \t"); /*skip whitespace */ i += num; num = strcspn (&buff[i], " \t\r\n"); /*span next word */ if (num != 0) { /* there is another word, that is community */ if (fsetcommunity == 0) { /* if not user-specified */ strncpy (rgcommunity, &buff[i], num); /* save community */ rgcommunity[num] = 0; } } else { /*have trapsink node with no community */ /* use previously discovered default community from above */ strcpy (rgcommunity, defcommunity); } /* dont break, keep looking, use the last one */ } } /*end while */ fclose (fprt); if (fdebug) printf ("snmp alertname=%s community=%s\n", alertname, rgcommunity); } /*end else snmpfile */ /* Get the Alert Destination MAC from the alertname. */ if (alertname[0] != 0) { #ifdef TEST char arping_cmd[128]; char *pb, *pm, *px; int num, i; if (fdebug) printf ("alert %s ip=%d.%d.%d.%d osip=%d.%d.%d.%d " "mac=%02x:%02x:%02x:%02x:%02x:%02x " "osmac=%02x:%02x:%02x:%02x:%02x:%02x\n", alertname, rgdestip[0], rgdestip[1], rgdestip[2], rgdestip[3], osmyip[0], osmyip[1], osmyip[2], osmyip[3], rgdestmac[0], rgdestmac[1], rgdestmac[2], rgdestmac[3], rgdestmac[4], rgdestmac[5], osmymac[0], osmymac[1], osmymac[2], osmymac[3], osmymac[4], osmymac[5]); #endif if (!IpIsValid (rgdestip)) { /* if not user-specified with -A */ if (IpIsValid (bmcdestip)) { /* use existing if valid */ memcpy (rgdestip, bmcdestip, 4); if (MacIsValid (bmcdestmac)) memcpy (rgdestmac, bmcdestmac, MAC_LEN); } else if ((strncmp (alertname, "localhost", 9) == 0)) { /* snmpd.conf = localhost (self) is the SNMP alert destination */ if (IpIsValid (osmyip)) memcpy (rgdestip, osmyip, 4); if (!MacIsValid (rgdestmac)) { /* if not user-specified */ // Get_Mac(rgdestip,rgdestmac,alertname); (wont work for local) memcpy (rgdestmac, osmymac, MAC_LEN); } } /*endif local */ } if (!MacIsValid (rgdestmac)) { /* if MAC not vaild or user-specified */ /* Use arping to get MAC from alertname or IP */ Get_Mac (rgdestip, rgdestmac, alertname); } } /*endif have alertname */ return (rc); } /* end Get_IPMac_Addr */ #endif int ShowChanAcc (uchar bchan) { LAN_RECORD LanRecord; int ret = 0; uchar access; char *pstr; uchar pb0, pb1; if (bchan == lan_ch) pstr = "lan"; else if (bchan == ser_ch) pstr = "ser"; else pstr = "?"; ret = GetChanAcc (bchan, 0x40, &LanRecord); if (fdebug) printf (" GetChanAcc(%d), ret = %d, data = %02x %02x\n", bchan, ret, LanRecord.data[0], LanRecord.data[1]); pb0 = LanRecord.data[0]; pb1 = LanRecord.data[1]; if (fcanonical) printf ("Channel %d Access Mode %s%c ", bchan, pspace3, bdelim); else printf ("Channel(%d=%s) Access Mode: %02x %02x : ", bchan, pstr, pb0, pb1); access = pb0; switch (access & 0x03) { case 0: printf ("Disabled, "); break; case 1: printf ("Pre-Boot, "); break; case 2: printf ("Always Avail, "); break; case 3: printf ("Shared, "); break; } if (access & 0x20) printf ("PEF Alerts Disabled\n"); /*0 */ else printf ("PEF Alerts Enabled\n"); /*1 */ return (ret); } static int GetSessionInfo (uchar * rData, int sz) { int rv, rlen; uchar ccode; uchar iData[5]; iData[0] = 0x00; /*get data for this session */ rlen = sz; rv = ipmi_cmdraw (CMD_GET_SESSION_INFO, NETFN_APP, BMC_SA, PUBLIC_BUS, BMC_LUN, iData, 1, rData, &rlen, &ccode, fdebug); if ((rv == 0) && (ccode != 0)) rv = ccode; return (rv); } static int GetPefCapabilities (uchar * bmax) { int rv, rlen; uchar ccode; uchar rData[MAX_BUFFER_SIZE]; rlen = sizeof (rData); rv = ipmi_cmdraw (0x10, NETFN_SEVT, BMC_SA, PUBLIC_BUS, BMC_LUN, NULL, 0, rData, &rlen, &ccode, fdebug); if ((rv == 0) && (ccode != 0)) rv = ccode; if ((rv == 0) && (bmax != NULL)) *bmax = rData[2]; /*max num PEF table entries */ return (rv); } int GetSerialOverLan (uchar chan, uchar bset, uchar block) { uchar requestData[24]; uchar rData[MAX_BUFFER_SIZE]; int rlen; int status, i; uchar ccode; uchar enable_parm, auth_parm, baud_parm; ushort getsolcmd; uchar user; if (fIPMI20 && fSOL20) { getsolcmd = GET_SOL_CONFIG2; enable_parm = SOL_ENABLE_PARAM; auth_parm = SOL_AUTHENTICATION_PARAM; baud_parm = SOL_BAUD_RATE_PARAM; } else { getsolcmd = GET_SOL_CONFIG; enable_parm = SOL_ENABLE_PARAM; auth_parm = SOL_AUTHENTICATION_PARAM; baud_parm = SOL_BAUD_RATE_PARAM; chan = 0; /*override chan for IPMI 1.5 */ } if (!fcanonical) printf ("%s, GetSOL for channel %d ...\n", progname, chan); requestData[0] = chan; /*channel */ requestData[1] = enable_parm; requestData[2] = bset; /*set */ requestData[3] = block; /*block */ rlen = sizeof (rData); status = ipmi_cmd (getsolcmd, requestData, 4, rData, &rlen, &ccode, fdebug); if (status != 0) return (status); if (ccode) { if (ccode == 0xC1) { /* unsupported command */ printf ("Serial-Over-Lan not available on this platform\n"); return (status); } else { printf ("SOL Enable ccode = %x\n", ccode); status = ccode; } } else { /*success */ if (fcanonical) { printf ("Channel %d SOL Enable %s", chan, pspace3); } else { printf ("SOL Enable: "); for (i = 1; i < rlen; i++) printf ("%02x ", rData[i]); } if (rData[1] == 0x01) printf ("%c enabled\n", bdelim); else printf ("%c disabled\n", bdelim); } if (!fcanonical) { requestData[0] = chan; requestData[1] = auth_parm; requestData[2] = bset; // selector requestData[3] = block; // block rlen = sizeof (rData); status = ipmi_cmd (getsolcmd, requestData, 4, rData, &rlen, &ccode, fdebug); if (status != 0) return (status); if (ccode) { printf ("SOL Auth ccode = %x\n", ccode); status = ccode; } else { /*success */ printf ("SOL Auth: "); for (i = 1; i < rlen; i++) printf ("%02x ", rData[i]); printf (": "); show_priv (rData[1]); /* priv level = User,Admin,... */ printf ("\n"); } requestData[0] = chan; requestData[1] = SOL_ACC_INTERVAL_PARAM; requestData[2] = bset; requestData[3] = block; rlen = sizeof (rData); status = ipmi_cmd (getsolcmd, requestData, 4, rData, &rlen, &ccode, fdebug); if (status != 0) return (status); if (ccode) { printf ("SOL Accum Interval ccode = %x\n", ccode); status = ccode; } else { /*success */ printf ("SOL Accum Interval: "); for (i = 1; i < rlen; i++) printf ("%02x ", rData[i]); printf (": %d msec\n", (rData[1] * 5)); } requestData[0] = chan; requestData[1] = SOL_RETRY_PARAM; requestData[2] = bset; requestData[3] = block; rlen = sizeof (rData); status = ipmi_cmd (getsolcmd, requestData, 4, rData, &rlen, &ccode, fdebug); if (status != 0) return (status); if (ccode) { printf ("SOL Retry ccode = %x\n", ccode); status = ccode; } else { /*success */ printf ("SOL Retry Interval: "); for (i = 1; i < rlen; i++) printf ("%02x ", rData[i]); printf (": %d msec\n", (rData[2] * 10)); } } if (!fRomley) { requestData[0] = chan; requestData[1] = baud_parm; requestData[2] = bset; requestData[3] = block; rlen = sizeof (rData); status = ipmi_cmd (getsolcmd, requestData, 4, rData, &rlen, &ccode, fdebug); if (status != 0) return (status); if (ccode) { printf ("SOL nvol Baud ccode = %x\n", ccode); status = ccode; } else { /*success */ uchar b; if (fcanonical) { printf ("Channel %d SOL Baud Rate%s", chan, pspace3); } else { printf ("SOL nvol Baud Rate: "); for (i = 1; i < rlen; i++) printf ("%02x ", rData[i]); } /* if not user-specified and previously enabled, use existing */ b = (rData[1] & 0x0f); if ((fnewbaud == 0) && BaudValid (b)) { sol_baud = b; sol_bvalid = 1; } printf ("%c %s\n", bdelim, Baud2Str (b)); } if (!fcanonical) { requestData[0] = chan; requestData[1] = SOL_VOL_BAUD_RATE_PARAM; /*0x06 */ requestData[2] = bset; requestData[3] = block; rlen = sizeof (rData); status = ipmi_cmd (getsolcmd, requestData, 4, rData, &rlen, &ccode, fdebug); if (status != 0) return (status); if (ccode) { printf ("SOL vol Baud ccode = %x\n", ccode); status = ccode; } else { /*success */ printf ("SOL vol Baud Rate: "); for (i = 1; i < rlen; i++) printf ("%02x ", rData[i]); printf ("%c %s\n", bdelim, Baud2Str (rData[1])); } } } if (fIPMI20) { if (vend_id != VENDOR_IBM) { /* IBM 0x00DC returns invalid cmd for SOL Payload commands. */ if (!fcanonical) { requestData[0] = chan; rlen = sizeof (rData); status = ipmi_cmdraw (GET_PAYLOAD_SUPPORT, NETFN_APP, BMC_SA, PUBLIC_BUS, BMC_LUN, requestData, 1, rData, &rlen, &ccode, fdebug); if ((status != 0) || (ccode != 0)) { printf ("SOL Payload Support error %d, ccode = %x\n", status, ccode); if (status == 0) status = ccode; } else { /*success */ printf ("SOL Payload Support(%d): ", chan); for (i = 0; i < rlen; i++) printf ("%02x ", rData[i]); printf ("\n"); } } /*endif not canonical */ /* get Payload Access for 4 users, not just lan_user */ for (user = 1; user <= show_users; user++) { /* mBMC doesn't support more than 1 user */ if (fmBMC && (user > 1)) break; /* IPMI 2.0 has >= 4 users */ requestData[0] = chan; requestData[1] = user; rlen = sizeof (rData); status = ipmi_cmdraw (GET_PAYLOAD_ACCESS, NETFN_APP, BMC_SA, PUBLIC_BUS, BMC_LUN, requestData, 2, rData, &rlen, &ccode, fdebug); if ((status != 0) || (ccode != 0)) { printf ("SOL Payload Access(%d,%d) error %d, ccode = %x\n", chan, user, status, ccode); if (status == 0) status = ccode; } else { /*success */ if (fcanonical) { printf ("Channel %d SOL Payload Access(user%d)%s", chan, user, pspace1); } else { printf ("SOL Payload Access(%d,%d): ", chan, user); for (i = 0; i < rlen; i++) printf ("%02x ", rData[i]); } if ((rData[0] & 0x02) != 0) printf ("%c enabled\n", bdelim); else printf ("%c disabled\n", bdelim); } } /*end user loop */ } /*endif not IBM */ } return (status); } /*end GetSerialOverLan */ /* ECHO SOL Config Enable CMDTOOL 20 30 21 %1 01 01 ECHO SOL Authentication (Administrator) CMDTOOL 20 30 21 %1 02 04 ECHO SOL Accumlate Interval and threshold CMDTOOL 20 30 21 %1 03 06 14 ECHO SOL Retry Interval and threshold CMDTOOL 20 30 21 %1 04 06 14 ECHO SOL non-volatile baud rate CMDTOOL 20 30 21 %1 05 07 ECHO SOL volatile baud rate CMDTOOL 20 30 21 %1 06 07 ECHO Set user Payload Access for user 1 CMDTOOL 20 18 4c %1 01 02 00 00 00 */ int SetupSerialOverLan (int benable) { uchar requestData[24]; uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar completionCode; uchar enable_parm, auth_parm, baud_parm; ushort setsolcmd; ushort getsolcmd; uchar bchan, b; if (fIPMI20 && fSOL20) { setsolcmd = SET_SOL_CONFIG2; getsolcmd = GET_SOL_CONFIG2; enable_parm = SOL_ENABLE_PARAM; auth_parm = SOL_AUTHENTICATION_PARAM; baud_parm = SOL_BAUD_RATE_PARAM; bchan = lan_ch; } else { setsolcmd = SET_SOL_CONFIG; getsolcmd = GET_SOL_CONFIG; enable_parm = SOL_ENABLE_PARAM; auth_parm = SOL_AUTHENTICATION_PARAM; baud_parm = SOL_BAUD_RATE_PARAM; bchan = 0x00; /*override chan for IPMI 1.5 */ } memset (requestData, 0, sizeof (requestData)); /* zero-fill */ requestData[0] = bchan; requestData[1] = enable_parm; if (benable == 0) requestData[2] = SOL_DISABLE_FLAG; else requestData[2] = SOL_ENABLE_FLAG; responseLength = MAX_BUFFER_SIZE; status = ipmi_cmd (setsolcmd, requestData, 3, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { switch (completionCode) { case 0x00: /* success */ break; case 0xC1: /* unsupported command */ SELprintf ("SetupSerialOverLan: SOL not available on this platform\n"); return 0; default: /* other error */ SELprintf ("SetupSerialOverLan: SOL_ENABLE_PARAM ccode=%x\n", completionCode); return -1; break; } } else { SELprintf ("SET_SOL_CONFIG, enable SOL failed\n"); return -1; } if (benable == 0) return 0; requestData[0] = bchan; /* channel */ requestData[1] = auth_parm; requestData[2] = 0x00; /* set selector */ requestData[3] = 0x00; /* block selector */ responseLength = MAX_BUFFER_SIZE; status = ipmi_cmd (getsolcmd, requestData, 4, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if (completionCode) { SELprintf ("SetupSerialOverLan: GET_SOL_AUTHENTICATION_PARAM code=%x\n", completionCode); return -1; } } else { SELprintf ("SOL_CONFIG, get SOL authentication failed\n"); return -1; } if ((vend_id == VENDOR_SUPERMICROX) || (vend_id == VENDOR_SUPERMICRO)) b = SOL_PRIVILEGE_LEVEL_OPERATOR; else b = SOL_PRIVILEGE_LEVEL_USER; requestData[0] = bchan; requestData[1] = auth_parm; requestData[2] = b | (responseData[1] & 0x80); /* priv | enable */ responseLength = MAX_BUFFER_SIZE; status = ipmi_cmd (setsolcmd, requestData, 3, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if (completionCode) { SELprintf ("SET_SOL_AUTHENTICATION_PARAM code=%x\n", completionCode); return -1; } } else { SELprintf ("SET_SOL_CONFIG, set SOL authentication failed\n"); return -1; } requestData[0] = bchan; requestData[1] = SOL_ACC_INTERVAL_PARAM; requestData[2] = sol_accum[0]; //0x04; requestData[3] = sol_accum[1]; //0x32; responseLength = MAX_BUFFER_SIZE; if (fdebug) SELprintf ("Setting SOL AccumInterval\n"); status = ipmi_cmd (setsolcmd, requestData, 4, responseData, &responseLength, &completionCode, fdebug); if (status != ACCESS_OK || completionCode) { SELprintf ("SET SOL AccumInterval ret=%d ccode=%x\n", status, completionCode); return -1; } /* Some BMCs return sporadic errors for SOL params (e.g. Kontron) */ // if (vend_id == VENDOR_KONTRON) ; // else { requestData[0] = bchan; requestData[1] = SOL_RETRY_PARAM; requestData[2] = sol_retry[0]; //0x06; requestData[3] = sol_retry[1]; //0x14; responseLength = MAX_BUFFER_SIZE; if (fdebug) SELprintf ("Setting SOL RetryInterval\n"); status = ipmi_cmd (setsolcmd, requestData, 4, responseData, &responseLength, &completionCode, fdebug); if (status != ACCESS_OK || completionCode) { SELprintf ("SET SOL RetryInterval ret=%d ccode=%x\n", status, completionCode); return -1; } } if (fRomley); /* skip SOL BAUD */ else { /* else SOL BAUD is used, so set it. */ if (fnewbaud == 0) { /* no user-specified SOL baud */ /* if sol_bvalid, sol_baud was set to existing value above */ if (!sol_bvalid) { status = GetSerEntry (7, (LAN_RECORD *) & responseData); if (status == 0) { /* use Serial baud for SOL */ sol_baud = responseData[1]; if (fdebug) SELprintf ("Serial Baud is %s\n", Baud2Str (sol_baud)); } } } requestData[0] = bchan; requestData[1] = baud_parm; requestData[2] = sol_baud; responseLength = MAX_BUFFER_SIZE; if (fdebug) SELprintf ("Setting SOL BAUD to %s\n", Baud2Str (sol_baud)); status = ipmi_cmd (setsolcmd, requestData, 3, responseData, &responseLength, &completionCode, fdebug); if (status != ACCESS_OK || completionCode) { SELprintf ("SET SOL BAUD ret=%d ccode=%x\n", status, completionCode); return -1; } requestData[0] = bchan; requestData[1] = SOL_VOL_BAUD_RATE_PARAM; requestData[2] = sol_baud; responseLength = MAX_BUFFER_SIZE; if (fdebug) printf ("Setting SOL vol BAUD to %s\n", Baud2Str (sol_baud)); status = ipmi_cmd (setsolcmd, requestData, 3, responseData, &responseLength, &completionCode, fdebug); if (status != ACCESS_OK || completionCode) { printf ("SET SOL vol BAUD ret=%d ccode=%x\n", status, completionCode); return -1; } } if (fIPMI20 && fSOL20) { if (vend_id == VENDOR_KONTRON && lan_user == 1) { if (fdebug) SELprintf ("Skipping SOL Payload Access for user %d\n", lan_user); } else if (vend_id == VENDOR_IBM) { /*non-conformance */ if (fdebug) SELprintf ("Skipping SOL Payload Access for user %d\n", lan_user); } else { if (fdebug) SELprintf ("Setting SOL Payload Access for user %d\n", lan_user); requestData[0] = bchan; requestData[1] = lan_user; /*enable this user */ requestData[2] = 0x02; /*enable std 2.0 SOL */ requestData[3] = 0; requestData[4] = 0; requestData[5] = 0; responseLength = MAX_BUFFER_SIZE; status = ipmi_cmdraw (SET_PAYLOAD_ACCESS, NETFN_APP, BMC_SA, PUBLIC_BUS, BMC_LUN, requestData, 6, responseData, &responseLength, &completionCode, fdebug); if (status != ACCESS_OK || completionCode) { SELprintf ("SET SOL Payload Access ret=%d ccode=%x\n", status, completionCode); return -1; } } } return 0; } /*end SetupSerialOverLan */ static char * PefDesc (int idx, uchar stype) { char *pdesc, *p; static char mystr[60]; int mylen = sizeof (mystr); pdesc = &mystr[0]; if (pefdesc != NULL) strcpy (pdesc, pefdesc[idx]); /* if Intel, pre-defined */ else strcpy (pdesc, "reserved"); /* else set default to detect */ if ((stype != 0) && (strcmp (pdesc, "reserved") == 0)) { /* Dynamically set the pef desc string from the sensor type */ switch (stype) { case 0x01: strcpy (pdesc, "Temperature"); break; case 0x02: strcpy (pdesc, "Voltage"); break; case 0x04: strcpy (pdesc, "Fan"); break; case 0x05: strcpy (pdesc, "Chassis"); break; case 0x07: strcpy (pdesc, "BIOS"); break; case 0x08: strcpy (pdesc, "Power Supply"); break; case 0x09: strcpy (pdesc, "Power Unit"); break; case 0x0c: strcpy (pdesc, "Memory"); break; case 0x0f: strcpy (pdesc, "Boot"); break; case 0x12: strcpy (pdesc, "System Restart"); break; case 0x13: strcpy (pdesc, "NMI"); break; case 0x23: strcpy (pdesc, "Watchdog"); break; case 0x20: strcpy (pdesc, "OS Critical Stop"); break; default: #ifdef METACOMMAND p = get_sensor_type_desc (stype); if (p != NULL) { strncpy (pdesc, p, mylen); mystr[mylen - 1] = 0; /*stringify */ } #else sprintf (pdesc, "Other[%02x]", stype); #endif break; } if (pef_array[idx - 1][4] == PEF_SEV_OK) strcat (pdesc, " OK"); } return (pdesc); } #ifdef METACOMMAND int i_lan(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int ret; PEF_RECORD PefRecord; LAN_RECORD LanRecord; int i, idx, j; int c; char *pstr; uchar bset; int ndest = 4; int idest; char mystr[80]; char fpefok = 1; uchar *pc; int sz; char *pa; char *pb; // progname = argv[0]; printf ("%s ver %s \n", progname, progver); j = 0; freadonly = FLAG_INIT; idx = argc; /*getopt loop counter */ /* available opt chars: y O Q + = ~ _ */ while ((c = getopt (argc, argv, "a:b:cdef:gh:i:j:klm:n:op:q:rstu:v:w:xy:z#::A:B:C:DEF:G:H:I:J:K:L:M:N:OP:Q:R:S:T:U:V:X:YZ:?")) != EOF) { switch (c) { case 'a': /* alert dest number (usu 1 thru 4) */ alertnum = atob (optarg); if (alertnum > alertmax) alertnum = 1; j++; break; case 'b': bAuth = htoi (optarg); j++; break; /*undocumented */ case 'c': fcanonical = 1; bdelim = BDELIM; break; case 'd': fenable = 0; fdisable = 1; freadonly = 0; break; case 'e': fenable = 1; fdisable = 0; freadonly = 0; break; case 'f': i = atoi (optarg); /*set arp_ctl */ if (i < 0 || i > 3) printf ("Invalid ARP control %d\n", i); else { arp_ctl = i; fsetarp = 1; j++; } break; case 'l': fpefenable = 0; fenable = 2; fdisable = 0; freadonly = 0; break; case 'h': /* VLAN ID */ i = atoi (optarg); if (i > 4095) vlan_enable = 0; else { vlan_enable = 1; vlan_id = (ushort) i; } j++; break; case 'y': /* OEM LAN Failover enable/disable */ i = atoi (optarg); if (i < 0) printf ("Failover(-y) parameter is negative\n"); else failover_enable = i; j++; break; case 'Q': /* VLAN Priority */ i = atoi (optarg); if (i > 7 || i < 0) vlan_enable = 0; else { vlan_enable = 1; vlan_prio = (uchar) i; } j++; break; case 'i': /* eth interface (ifname) */ fsetifn = 1; i = sizeof (ifname); if (strlen (optarg) > (uint) i) optarg[i] = 0; strcpy (ifname, optarg); if (fdebug) printf ("ifname = %s\n", ifname); j++; break; case 'j': fCustomPEF = 1; /*custom 10 PEF bytes */ fpefenable = 1; /* PEF is implied here */ freadonly = 0; memset (custPEF, 0, sizeof (custPEF)); custPEF[0] = htoi (&optarg[0]); /*action */ custPEF[1] = htoi (&optarg[2]); /*policy */ custPEF[2] = htoi (&optarg[4]); /*severity */ custPEF[3] = htoi (&optarg[6]); /*genid1 */ custPEF[4] = htoi (&optarg[8]); /*genid2 */ custPEF[5] = htoi (&optarg[10]); /*sensor_type */ custPEF[6] = htoi (&optarg[12]); /*sensor_num */ custPEF[7] = htoi (&optarg[14]); /*evt_trigger */ custPEF[8] = htoi (&optarg[16]); /*data1offset */ custPEF[9] = htoi (&optarg[18]); /*data1mask */ if (optarg[20] != 0) { /* optionally get 8 extra PEF entry bytes */ custPEF[10] = htoi (&optarg[20]); /*data1cmp1 */ custPEF[11] = htoi (&optarg[22]); /*data1cmp2 */ custPEF[12] = htoi (&optarg[24]); /*data2mask */ custPEF[13] = htoi (&optarg[26]); /*data2cmp1 */ custPEF[14] = htoi (&optarg[28]); /*data2cmp2 */ custPEF[15] = htoi (&optarg[30]); /*data3mask */ custPEF[16] = htoi (&optarg[32]); /*data3cmp1 */ custPEF[17] = htoi (&optarg[34]); /*data3cmp2 */ } j++; break; case 'k': fSetPEFOks = 1; j++; break; /*configure PEF OK rules */ case 'm': set_max_kcs_loops (atoi (optarg)); break; case 'n': /* number/index in PEF table to insert new entry */ fpefenable = 1; pefnum = atob (optarg); if (pefnum >= MAXPEF) { pefnum = MAXPEF - 1; fAdjustPefNum = 1; } else fUserPefNum = 1; j++; break; case 'o': fdisableSOL = 1; /*disable SOL only */ fpefenable = 0; /*no change to PEF */ freadonly = 0; break; case 'r': freadonly = 1; fenable = 0; break; case 's': fgetser = 1; break; case 't': ftestonly = 1; freadonly = 1; break; case 'v': /* user access privilege level */ i = atoi (optarg); if (valid_priv (i)) lan_access = i & 0x0f; else printf ("Invalid privilege -v %d, using Admin\n", i); j++; break; case 'w': i = atoi (optarg); /*set grat arp interval, in #sec */ if (i >= 0 && i < 256) arp_interval = i * 2; else printf ("Invalid arp interval -w %d, skipping\n", i); break; case 'x': fdebug = 1; break; case 'z': flanstats = 1; break; case 'D': lan_dhcp = 1; j++; break; case 'O': flansecure = 1; j++; break; case 'I': /* My BMC IP Address */ fset_ip |= MYIP; atoip (rgmyip, optarg); j++; break; case 'M': /* My BMC MAC Address */ atomac (rgmymac, optarg); if (!MacIsValid (rgmymac)) printf ("Invalid MAC for -M\n"); j++; break; case 'S': /* Subnet IP Address */ atoip (rgsubnet, optarg); j++; break; case 'G': /* Gateway IP Address */ fset_ip |= GWYIP; atoip (rggwyip, optarg); j++; break; case 'g': /* Secondary Gateway IP Address */ fset_ip |= GWYIP; atoip (rggwy2ip, optarg); j++; break; case 'H': /* Gateway MAC Address */ atomac (rggwymac, optarg); if (!MacIsValid (rggwymac)) printf ("Invalid MAC for -H\n"); j++; break; case 'B': /* SOL Baud rate */ fnewbaud = 1; sol_baud = Str2Baud (optarg); j++; break; case 'A': /* Alert Dest IP Address */ fset_ip |= DESTIP; /* allow name or ip here via Get_Mac() ? */ atoip (rgdestip, optarg); fpefenable = 1; /* PEF is implied here */ j++; break; case 'X': /* Alert Dest MAC Address */ atomac (rgdestmac, optarg); if (!MacIsValid (rgdestmac)) printf ("Invalid MAC for -X\n"); fpefenable = 1; /* PEF is implied here */ j++; break; case 'K': /* Kontron IPMI hostname */ i = sizeof (rghostname); /*usu 18 */ if (strlen (optarg) > (uint) i) optarg[i] = 0; strcpy (rghostname, optarg); j++; break; case 'C': /* Community String */ fsetcommunity = 1; i = sizeof (rgcommunity); /*usu 18 */ if (strlen (optarg) > (uint) i) optarg[i] = 0; strcpy (rgcommunity, optarg); fpefenable = 1; /* PEF is implied here */ j++; break; case 'u': /* username to set */ myuser = strdup_ (optarg); /*remote username */ j++; break; case 'p': /* password to set */ fpassword = 1; if (strlen (optarg) > PSW_MAX) optarg[PSW_MAX] = 0; strcpy (passwordData, optarg); if (fdebug) printf ("Password = %s\n", passwordData); /* Hide password from 'ps' */ memset (optarg, ' ', strlen (optarg)); j++; break; case 'q': case '#': usernum = atob (optarg); if (usernum > 15) usernum = 0; /*MAX_IPMI_USERS = 15 */ j++; break; case 'L': if (strcmp (optarg, "list") == 0) fshowchan = 1; lan_ch_parm = atob (optarg); if (lan_ch_parm > MAXCHAN) lan_ch_parm = PARM_INIT; /*invalid */ 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: printf ("Usage: %s [-abcdefghijklmnopq#rstuvwxyzBDQK]\n", progname); printf (" \t [-a alertnum -i eth1 -n pefnum ]\n"); printf (" \t [-I ipadr -M macadr -S subnet ]\n"); printf (" \t [-G gwyip -H gwymac -L lan_channel_num]\n"); printf (" \t [-A alertip -X alertmac -C community ]\n"); printf (" \t [-g 2nd_gwyip -v priv -B sol_baud ]\n"); printf (" \t [-j 10_bytes_custom_pef -b authmask ]\n"); printf ("where -c shows Canonical, simpler output format\n"); printf (" -d Disables BMC LAN & PEF\n"); printf (" -e Enables BMC LAN & PEF\n"); printf (" -f set ARP Control to 1=grat, 2=resp, 3=both\n"); printf (" -g secondary Gateway IP (-G=primary_gwy_ip)\n"); printf (" -h VLAN ID (>=4096 to disable)\n"); printf (" -j specify custom PEF rule (10 or 18 hex bytes)\n"); printf (" -k add PEF oK rules, if PEF enable\n"); printf (" -l Enables BMC LAN only, not PEF\n"); printf (" -o disable Only SOL\n"); printf (" -p password to set \n"); printf (" -q/-# User number of LAN username_to_set\n"); printf (" -r Read-only BMC LAN & PEF settings\n"); printf (" -s Show some Serial settings also \n"); printf (" -t Test if BMC LAN is already configured\n"); printf (" -u username to set \n"); printf (" -v access priVilege: 4=Admin,3=Operator,2=User\n"); printf (" -w set Grat ARP Interval to specified # seconds\n"); printf (" -x Show eXtra debug messages\n"); printf (" -y OEM LAN Failover (1=enable,0=disable if Intel)\n"); printf (" -z Show IPMI LAN statistics\n"); printf (" -B Baud for SerialOverLan (19.2K,115.2K,...)\n"); printf (" -D Use DHCP instead of static IP (-I for server)\n"); printf (" -K (Kontron) IPMI hostname to set\n"); printf (" -Q VLAN Priority (default =0)\n"); printf (" -O Force LAN security: no null user, cipher 0 off\n"); print_lan_opt_usage (0); ret = ERR_USAGE; goto do_exit; } /*end switch */ nopts++; } /*end while */ if ((freadonly == FLAG_INIT) && (j > 0)) { /* got some options implying set, but no -e -l -d option specified. */ foptmsg = 1; /*show warning message later */ freadonly = 1; /*assume read only */ } fipmilan = is_remote (); if (fipmilan && !fprivset) parse_lan_options ('V', "4", 0); /*even if freadonly request admin */ if ((fsetarp == 0) && ostype == OS_WINDOWS) arp_ctl = 0x03; /*grat arp & arp resp enabled */ ret = ipmi_getdeviceid((uchar *)&LanRecord,16,fdebug); if (ret != 0) { goto do_exit; } else { /* success */ uchar ipmi_maj, ipmi_min; ipmi_maj = LanRecord.data[4] & 0x0f; ipmi_min = LanRecord.data[4] >> 4; show_devid (LanRecord.data[2], LanRecord.data[3], ipmi_maj, ipmi_min); if (ipmi_maj == 0) fIPMI10 = 1; /* IPMI 1.0 is limited */ else if (ipmi_maj == 1 && ipmi_min < 5) fIPMI10 = 1; else fIPMI10 = 0; /* >= IPMI 1.5 is ok */ if (ipmi_maj >= 2) fIPMI20 = 1; /* IPMI 2.0 has more */ if (fIPMI20) show_users = 5; else show_users = 3; if (fIPMI10) { printf ("This IPMI v%d.%d system does not support PEF records.\n", ipmi_maj, ipmi_min); /* Wont handle PEF, but continue and look for BMC LAN anyway */ } prod_id = LanRecord.data[9] + (LanRecord.data[10] << 8); vend_id = LanRecord.data[6] + (LanRecord.data[7] << 8) + (LanRecord.data[8] << 16); /* check Device ID response for Manufacturer ID = 0x0322 (NSC) */ if (vend_id == VENDOR_NSC) { /* NSC = 0x000322 */ fmBMC = 1; /*NSC miniBMC */ if (pefnum == 12) pefnum = 10; /* change CritStop pefnum to 0x0a */ pefdesc = &pefdesc2[0]; /*mini-BMC PEF */ pefmax = 30; fsharedMAC = 1; /* shared MAC with OS */ } else if (vend_id == VENDOR_LMC) { /* LMC (on SuperMicro) = 0x000878 */ pefdesc = NULL; /* unknown, see PefDesc() */ if (pefnum == 12) pefnum = 15; /* change CritStop pefnum */ pefmax = 16; fsharedMAC = 0; /* not-shared BMC LAN port */ } else if (vend_id == VENDOR_INTEL) { /* Intel = 0x000157 */ pefdesc = &pefdesc1[0]; /*default Intel PEF */ pefmax = 20; /*default Intel PEF */ switch (prod_id) { case 0x4311: /* Intel NSI2U w SE7520JR23 */ fmBMC = 1; /* Intel miniBMC */ if (pefnum == 12) pefnum = 14; /* change CritStop pefnum */ pefdesc = &pefdesc2[0]; /*mini-BMC PEF */ pefmax = 30; fsharedMAC = 1; /* shared-MAC BMC LAN port, same MAC */ break; case 0x0022: /* Intel TIGI2U w SE7520JR23 +IMM */ fsharedMAC = 1; /* shared-MAC BMC LAN port, same MAC */ gcm_ch = 3; /* IMM GCM port, dedicated MAC */ show_users = 4; break; case 0x000C: /*TSRLT2 */ case 0x001B: /*TIGPR2U */ /* fmBMC=0; Intel Sahalee BMC */ fsharedMAC = 1; /* shared-MAC BMC LAN port, same MAC */ break; case 0x0026: /*S5000 Bridgeport */ case 0x0028: /*S5000PAL Alcolu */ case 0x0029: /*S5000PSL StarLake */ case 0x0811: /*S5000PHB TIGW1U */ /* fmBMC=0; Intel Sahalee ESB2 BMC */ fsharedMAC = 0; /* not-shared BMC LAN port, separate MAC */ gcm_ch = 3; parm7 = &iparm7[0]; /*TTL=30 */ break; case 0x003E: /*NSN2U or CG2100 Urbanna */ fiBMC = 1; /* Intel iBMC */ fsharedMAC = 0; /* not-shared BMC LAN port, separate MAC */ // gcm_ch = 3; parm7 = &iparm7[0]; /*TTL=30 */ if (fsetarp == 0) arp_ctl = 0x02; /*grat arp disabled,arp resp enabled*/ arp_interval = 0x00; /*0 sec, since grat arp disabled */ sol_accum[0] = 0x0c; /*Intel defaults */ sol_accum[1] = 0x60; /*Intel defaults */ sol_retry[0] = 0x07; /*Intel defaults */ sol_retry[1] = 0x32; /*Intel defaults */ set_max_kcs_loops (URNLOOPS); /*longer for SetLan cmds (default 300)*/ break; case 0x0107: /* Intel Caneland */ fsharedMAC = 0; /* not-shared BMC LAN port, separate MAC */ gcm_ch = 3; break; case 0x0100: /*Tiger2 ia64 */ /* for ia64 set chan_pefon, chan_pefoff accordingly */ chan_pefon = CHAN_ACC_PEFON64; chan_pefoff = CHAN_ACC_PEFOFF64; /* fall through */ default: /* else other Intel */ /* fmBMC = 0; * Intel Sahalee BMC */ if (fIPMI20) fsharedMAC = 0; /* recent, not-shared BMC MAC */ else fsharedMAC = 1; /* usu IPMI 1.x has shared BMC MAC */ break; } /*end switch */ if (is_romley(vend_id, prod_id)) fRomley = 1; if (is_grantley(vend_id, prod_id)) fGrantley = 1; if (fRomley) { fiBMC = 1; /* Intel iBMC */ fsharedMAC = 0; /* not-shared BMC LAN port, separate MAC */ set_max_kcs_loops (URNLOOPS); /*longer for SetLan (default 300) */ fipv6 = 1; if (fsetarp == 0) arp_ctl = 0x03; /*default to both for Romley */ } } else { /* else other vendors */ if (fIPMI20) fsharedMAC = 0; /* recent, not-shared BMC MAC */ else fsharedMAC = 1; /* usu IPMI 1.x has shared BMC MAC */ pefdesc = NULL; /* unknown, see PefDesc() */ if (pefnum == 12) pefnum = 15; /* change CritStop pefnum to 15? */ pefmax = 20; if (!fUserPefNum) fAdjustPefNum = 1; } if (fmBMC) show_users = 1; /* mBMC doesn't support more than 1 user */ } if (fshowchan) { ret = show_channels (); exit (ret); } ret = GetPefCapabilities (&bset); if ((ret == 0) && (bset <= MAXPEF)) pefmax = bset; /* Get the BMC LAN channel & match it to an OS eth if. */ i = GetBmcEthDevice (lan_ch_parm, &lan_ch); if (i == -2) { /* no lan channels found (see lan_ch) */ if (lan_ch_parm == PARM_INIT) printf ("This system does not support IPMI LAN channels.\n"); else /*specified a LAN channel */ printf ("BMC channel %d does not support IPMI LAN.\n", lan_ch_parm); ret = LAN_ERR_NOTSUPPORT; goto do_exit; } else if (i < 0) { /* mac not found, use platform defaults */ i = 0; /* default to eth0, lan_ch set already. */ if (vend_id == VENDOR_INTEL) { if ((prod_id == 0x001B) || (prod_id == 0x000c)) { /* Intel TIGPR2U or TSRLT2 defaults are special */ if (lan_ch_parm == 6) { i = 0; lan_ch = 6; } else { i = 1; lan_ch = 7; } ser_ch = 1; } } } if ((i == gcm_ch) && (gcm_ch != PARM_INIT) && (lan_ch_parm == PARM_INIT)) { /* Has a GCM, defaulted to it, and user didn't specify -L */ /* Need this to avoid picking channel 3, the IMM/RMM GCM channel. */ lan_ch = 1; /*default BMC LAN channel */ // i = 0; /*default eth0 (was eth1) */ } if (fsetifn == 0) { /*not user specified, use the detected one */ // if (lan_ch == gcm_ch) strcpy(ifname,"gcm"); sprintf (ifname, "%s%d", ifpattn, i); /*eth%d */ } if (fdebug) printf ("lan_ch = %d, ifname = %s\n", lan_ch, ifname); /* set the lan_user appropriately */ if (myuser == NULL) { /* if no -u param */ if (ipmi_reserved_user (vend_id, 1)) lan_user = 2; else if (flansecure) lan_user = 2; else lan_user = 1; /*use default null user */ } else if (usernum != 0) lan_user = usernum; /*use -q specified usernum */ /* else use default lan_user (=2) if -u and not -q */ if (ftestonly) { /*test only if BMC LAN is configured or not */ /* TODO: test gcm also, if present */ ret = GetLanEntry (4, 0, &LanRecord); /*ip addr src */ if (ret == 0) { if ((LanRecord.data[0] == SRC_BIOS) || (LanRecord.data[0] == SRC_DHCP)) ret = 0; /* DHCP, so ok */ else { /*static IP */ ret = GetLanEntry (3, 0, &LanRecord); /* ip address */ if (ret == 0) { if (!IpIsValid (LanRecord.data)) { printf ("invalid BMC IP address\n"); ret = 1; /* invalid ip */ } else ret = GetLanEntry (12, 0, &LanRecord); /*gateway ip */ if (ret == 0) { if (!IpIsValid (LanRecord.data)) { printf ("invalid gateway ip\n"); ret = 2; /*invalid gwy ip */ } else ret = GetLanEntry (13, 0, &LanRecord); if (ret == 0) { if (!MacIsValid (&LanRecord.data[0])) { printf ("invalid gateway mac\n"); ret = 3; /*invalid gwy mac */ } } } } } } /*endif GetLanEntry ok */ if (ret == 0) printf ("BMC LAN already configured\n"); else printf ("BMC LAN not configured\n"); goto do_exit; } /*endif ftestonly */ memset (SessInfo, 0, sizeof (SessInfo)); ret = GetSessionInfo (SessInfo, sizeof (SessInfo)); // rlen = sizeof(SessInfo)); ret = get_session_info(0,0,SessInfo,&rlen); if (fdebug) printf ("GetSessionInfo ret=%d, data: %02x %02x %02x %02x \n", ret, SessInfo[0], SessInfo[1], SessInfo[2], SessInfo[3]); if (!freadonly && fipmilan) { /* setting LAN params, and using IPMI LAN */ if (SessInfo[2] > 1) { /* another session is active also */ printf ("Another session is also active, cannot change IPMI LAN settings now.\n"); ret = ERR_NOT_ALLOWED; goto do_exit; } } if (!fIPMI10) { if (fcanonical) { /* canonical/simple output */ ret = GetPefEntry (0x01, 0, (PEF_RECORD *) & LanRecord); if (ret != 0) ndest = 0; else { /*success */ j = LanRecord.data[0]; mystr[0] = 0; if (j == 0) strcat (mystr, "none "); else { if (j & 0x01) strcat (mystr, "PEFenable "); if (j & 0x02) strcat (mystr, "DoEventMsgs "); if (j & 0x04) strcat (mystr, "Delay "); if (j & 0x08) strcat (mystr, "AlertDelay "); } printf ("PEF Control %s%c %s\n", pspace4, bdelim, mystr); } } else { /* normal/full output */ ret = GetPefEntry (0x01, 0, (PEF_RECORD *) & LanRecord); if (ret == 0 && (LanRecord.data[0] != 0)) { fpefok = 1; bmcpefctl = LanRecord.data[0]; } else { /* skip PEF rules/params if disabled */ printf ("PEF Control %s%c %s\n", pspace4, bdelim, "none "); ndest = 0; fpefok = 0; } if (fpefok) { printf ("%s, GetPefEntry ...\n", progname); for (idx = 1; idx <= pefmax; idx++) { ret = GetPefEntry (0x06, (ushort) idx, &PefRecord); if (ret == 0) { // Show the PEF record pc = (uchar *) & PefRecord; sz = 21; // sizeof(PEF_RECORD) = 21 if (PefRecord.sensor_type == 0) { if (idx <= pefnum) printf ("PEFilter(%02d): empty\n", idx); memcpy (pef_array[idx - 1], &PefRecord, sz); if (fAdjustPefNum) pefnum = (char) idx; } else { memcpy (pef_array[idx - 1], &PefRecord, sz); if (PefRecord.fconfig & 0x80) pb = "enabled"; else pb = "disabled"; i = PefRecord.rec_id; switch (PefRecord.action) { case 0x01: pa = "alert"; break; case 0x02: pa = "poweroff"; break; case 0x04: pa = "reset"; break; case 0x08: pa = "powercycle"; break; case 0x10: pa = "OEMaction"; break; case 0x20: pa = "NMI"; break; default: pa = "no action"; } printf ("PEFilter(%02d): %02x %s event - %s for %s\n", idx, PefRecord.sensor_type, PefDesc (i, PefRecord.sensor_type), pb, pa); } if (fdebug) { /* show raw PEFilter record */ pc = &PefRecord.rec_id; printf ("raw PEF(%.2d): ", pc[0]); for (i = 0; i < sz; i++) printf ("%02x ", pc[i]); printf ("\n"); } } else { printf ("GetPefEntry(%d), ret = %d\n", idx, ret); if (ret == 0xC1) { /*PEF is not supported, so skip the rest. */ fpefok = 0; ndest = 0; /* if no PEF, no alerts & no alert dest */ break; } } } } /*endif fpefok */ if (fpefok) { if (fdebug) ShowPef (); ret = GetPefEntry (0x01, 0, (PEF_RECORD *) & LanRecord); if (ret == 0) { j = LanRecord.data[0]; mystr[0] = 0; if (j & 0x01) strcat (mystr, "PEFenable "); if (j & 0x02) strcat (mystr, "DoEventMsgs "); if (j & 0x04) strcat (mystr, "Delay "); if (j & 0x08) strcat (mystr, "AlertDelay "); printf ("PEF Control: %02x : %s\n", j, mystr); } ret = GetPefEntry (0x02, 0, (PEF_RECORD *) & LanRecord); if (ret == 0) { j = LanRecord.data[0]; mystr[0] = 0; if (j & 0x01) strcat (mystr, "Alert "); if (j & 0x02) strcat (mystr, "PwrDn "); if (j & 0x04) strcat (mystr, "Reset "); if (j & 0x08) strcat (mystr, "PwrCyc "); if (j & 0x10) strcat (mystr, "OEM "); if (j & 0x20) strcat (mystr, "DiagInt "); printf ("PEF Actions: %02x : %s\n", j, mystr); } ret = GetPefEntry (0x03, 0, (PEF_RECORD *) & LanRecord); if (ret == 0) printf ("PEF Startup Delay: %02x : %d sec\n", LanRecord.data[0], LanRecord.data[0]); if (!fmBMC) { ret = GetPefEntry (0x04, 0, (PEF_RECORD *) & LanRecord); if (ret == 0) printf ("PEF Alert Startup Delay: %02x: %d sec\n", LanRecord.data[0], LanRecord.data[0]); /* fmBMC gets cc=0x80 here */ } /* note that ndest should be read from lan param 17 below. */ for (i = 1; i <= ndest; i++) { ret = GetPefEntry (0x09, (ushort) i, (PEF_RECORD *) & LanRecord); if (ret == 0) { mystr[0] = 0; j = LanRecord.data[2]; if (LanRecord.data[1] & 0x08) { sprintf (mystr, "Chan[%d] Dest[%d] ", ((j & 0xf0) >> 4), (j & 0x0f)); strcat (mystr, "Enabled "); } else strcpy (mystr, "Disabled "); printf ("PEF Alert Policy[%d]: %02x %02x %02x %02x : %s\n", i, LanRecord.data[0], LanRecord.data[1], LanRecord.data[2], LanRecord.data[3], mystr); } } /*endfor ndest */ } /*endif fpefok */ } /*endif not canonical */ if (fpefenable && !freadonly) { /* fenable or fdisable */ if (fSetPEFOks) pefadd = 5; else pefadd = 2; sz = (pefnum - 1) + pefadd + fCustomPEF; printf ("\n%s, SetPefEntry(1-%d) ...\n", progname, sz); if (fdebug) printf ("pefnum = %d, pefmax = %d\n", pefnum, pefmax); for (idx = 1; idx <= pefmax; idx++) { // Set & Enable all PEF records memset (&PefRecord.rec_id, 0, sizeof (PEF_RECORD)); PefRecord.rec_id = (uchar) idx; /* next record, or user-specified */ if (idx < pefnum) { /* pefnum defaults to 12.(0x0c) */ if (pef_array[idx - 1][7] == 0) /*empty pef record, set to default */ memcpy (&PefRecord.rec_id, pef_defaults[idx - 1], sizeof (PEF_RECORD)); else { /* set config however it was previously */ memcpy (&PefRecord.rec_id, pef_array[idx - 1], sizeof (PEF_RECORD)); if (PefRecord.severity == 0) PefRecord.severity = pef_defaults[idx - 1][4]; } } else if ((idx == pefnum) && /* new OS Crit Stop entry */ (PefRecord.sensor_type == 0)) { // Set PEF values for 0x20, OS Critical Stop event PefRecord.severity = PEF_SEV_CRIT; PefRecord.genid1 = 0xff; PefRecord.genid2 = 0xff; PefRecord.sensor_type = 0x20; /* OS Critical Stop */ PefRecord.sensor_no = 0xff; PefRecord.event_trigger = 0x6f; PefRecord.data1 = 0xff; PefRecord.mask1 = 0x00; } else if ((idx == pefnum + 1) && /* new Power Redundancy entry */ (PefRecord.sensor_type == 0)) { // Set PEF values for 0x09/0x02/0x0b/0x41, Power Redundancy Lost PefRecord.severity = PEF_SEV_WARN; PefRecord.genid1 = 0xff; PefRecord.genid2 = 0xff; PefRecord.sensor_type = 0x09; /* Power Unit */ PefRecord.sensor_no = 0xff; /* usu 01 or 02 */ PefRecord.event_trigger = 0x0b; /* event trigger */ PefRecord.data1 = 0x02; /* 02 -> 41=Redundancy Lost */ PefRecord.mask1 = 0x00; } else if (fSetPEFOks && idx == (pefnum + 2)) { PefRecord.severity = PEF_SEV_OK; PefRecord.genid1 = 0xff; PefRecord.genid2 = 0xff; PefRecord.sensor_type = 0x09; /* Power Unit, Redund OK */ PefRecord.sensor_no = 0xff; /* usu 01 or 02 */ PefRecord.event_trigger = 0x0b; /* event trigger */ PefRecord.data1 = 0x01; /* 01 -> 40=Redundancy OK */ PefRecord.mask1 = 0x00; } else if (fSetPEFOks && idx == (pefnum + 3)) { PefRecord.severity = PEF_SEV_OK; PefRecord.genid1 = 0xff; PefRecord.genid2 = 0xff; PefRecord.sensor_type = 0x01; /* Temp OK */ PefRecord.sensor_no = 0xff; /* usu 01 or 02 */ PefRecord.event_trigger = 0x81; /* event trigger */ PefRecord.data1 = 0x95; /* 95 -> 50(NC),52(Crit) match */ PefRecord.mask1 = 0x0a; } else if (fSetPEFOks && idx == (pefnum + 4)) { PefRecord.severity = PEF_SEV_OK; PefRecord.genid1 = 0xff; PefRecord.genid2 = 0xff; PefRecord.sensor_type = 0x02; /* Voltage OK */ PefRecord.sensor_no = 0xff; /* usu 01 or 02 */ PefRecord.event_trigger = 0x81; /* event trigger */ PefRecord.data1 = 0x95; /* 95 -> 50(NC),52(Crit) match */ PefRecord.mask1 = 0x0a; } else if (fCustomPEF && idx == (pefnum + pefadd)) { /* user entered 10 or 18 PEF entry bytes */ PefRecord.action = custPEF[0]; PefRecord.policy = custPEF[1]; PefRecord.severity = custPEF[2]; PefRecord.genid1 = custPEF[3]; PefRecord.genid2 = custPEF[4]; PefRecord.sensor_type = custPEF[5]; PefRecord.sensor_no = custPEF[6]; PefRecord.event_trigger = custPEF[7]; PefRecord.data1 = custPEF[8]; PefRecord.mask1 = custPEF[9]; memcpy (&PefRecord.action, custPEF, 18); } else { memcpy (&PefRecord.rec_id, pef_array[idx - 1], sizeof (PEF_RECORD)); if (PefRecord.sensor_type == 0) continue; /* if reserved, skip it */ } if (fdebug && (PefRecord.rec_id != idx)) { /* memcpy from pef_defaults or pef_array clobbered rec_id */ printf ("Warning: SetPef idx=%d, rec_id=%d\n", idx, PefRecord.rec_id); PefRecord.rec_id = (uchar) idx; /*fix it */ } if (fdisable) { /* Disable all PEF rules */ if (idx >= pefnum) PefRecord.fconfig = 0x00; /*disabled, software */ else PefRecord.fconfig = 0x40; /*disabled, preset */ PefRecord.action = 0x00; PefRecord.policy = 0x00; } else { /*fenable */ if (PefRecord.sensor_type != 0) { /* not an empty PEF entry */ /* Enable all non-empty PEF rules */ if (fCustomPEF && (idx == (pefnum + pefadd))) { PefRecord.action = custPEF[0]; PefRecord.policy = custPEF[1]; } else { PefRecord.action = 0x01; /*Alert */ PefRecord.policy = 0x01; /*see Alert Policy #1 */ } if (idx < pefnum) { /* special handling for presets, 1 thru 11 */ PefRecord.fconfig = 0x80; /* enabled, software */ ret = SetPefEntry (&PefRecord); if (fdebug) printf ("SetPefEntry(%d/80) ret=%d\n", PefRecord.rec_id, ret); // if (ret != 0) { nerrs++; lasterr = ret; } // else ngood++; PefRecord.fconfig = 0xC0; /* enabled, preset */ } else { PefRecord.fconfig = 0x80; /* enabled, software */ } } /*endif not empty */ } { // Show the new PEF record before setting it. pc = (uchar *) & PefRecord; sz = 21; printf ("PEFilter(%d): ", PefRecord.rec_id); for (i = 0; i < sz; i++) printf ("%02x ", pc[i]); printf ("\n"); } ret = SetPefEntry (&PefRecord); if (fdebug) printf ("SetPefEntry(%d) ret = %d\n", PefRecord.rec_id, ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } /*end for */ } } /*end if not fIPMI10 */ if (!fcanonical) printf ("\n%s, GetLanEntry for channel %d ...\n", progname, lan_ch); idest = 1; for (idx = 0; idx < NLAN; idx++) { int ival; if (fcanonical && (canon_param[idx] == 0)) continue; if (idx == 8 || idx == 9) continue; /* not implemented */ ival = lanparams[idx].cmd; if (ival >= 96 && ival <= 98) continue; /* not implemented */ if (ival >= 102 && ival <= 108) { /*custom IPv6 parameters */ if (fipv6 == 0) continue; /*skip these */ } if (ival == 194 && vend_id == VENDOR_KONTRON) { /*oem hostname parm */ lanparams[idx].sz = 36; strcpy (lanparams[idx].desc, "IPMI Hostname"); } else if (ival >= 192 && ival <= 194) { /*custom DHCP parameters */ if (vend_id != VENDOR_INTEL) continue; if (fmBMC || fiBMC || fcanonical) continue; /*skip these */ } if (ival >= 20 && ival <= 25) { if (!fIPMI20) continue; /*VLAN params 20-25, fIPMI20 only/opt */ } if ((ndest == 0) && (ival >= 18 && ival <= 19)) continue; /*skip dest */ if (ival == 11) { /*grat arp interval */ if (vend_id == VENDOR_SUPERMICROX) continue; if (vend_id == VENDOR_SUPERMICRO) continue; } if (ival == 14 || ival == 15) { /*secondary gateway is optional */ if (vend_id == VENDOR_KONTRON) continue; } if (ival == 201) { /*Get Channel Access */ ret = ShowChanAcc (lan_ch); } else { if (ival == 18 || ival == 19) { /*dest params */ if (ndest == 0) continue; /*skip if ndest==0 */ bset = (uchar) idest; /* dest id = 1 thru n */ } else bset = 0; ret = GetLanEntry ((uchar) ival, bset, &LanRecord); } if (ret == 0) { // Show the LAN record pc = (uchar *) & LanRecord; sz = lanparams[idx].sz; if (ival == 18) { /*skip if invalid dest type param */ if ((idest > 1) && (pc[2] == 0)) { idest = 1; continue; } } else if (ival == 19) { /*skip if invalid dest addr param */ if ((idest > 1) && !IpIsValid (&pc[3])) { idest = 1; continue; } } if (ival == 201); /* did it above */ else { if (fcanonical) { if ((ival == 19) && (idest > 1)); /*skip it */ else { j = strlen_ (lanparams[idx].desc); // (ival < 7) || (ival == 19) || ival == 102) if (j <= 12) pstr = pspace3; else pstr = pspace2; printf ("Channel %d %s %s%c ", lan_ch, lanparams[idx].desc, pstr, bdelim); } } else printf ("Lan Param(%d) %s: ", ival, lanparams[idx].desc); } if (ival == 1) { authmask = pc[0]; /* auth type support mask */ /* if (fmBMC) authmask is usually 0x15, else 0x14 */ } else if (ival == 3) { if (IpIsValid (pc)) memcpy (bmcmyip, pc, 4); } else if (ival == 5) { if (MacIsValid (pc)) memcpy (bmcmymac, pc, MAC_LEN); } else if (ival == 6) { if (SubnetIsValid (pc)) memcpy (bmcsubnet, pc, 4); /* else if invalid, leave default as 255.255.255.0 */ //} else if (ival == 7) { // if (pc[0] >= 30) memcpy(bparm7,pc,3); } else if (ival == 17) { /* num dest */ ndest = pc[0]; /* save the number of destinations */ } else if (ival == 12) { /* gateway addr */ if (IpIsValid (pc)) memcpy (bmcgwyip, pc, 4); } else if (ival == 13) { /* gateway mac */ if (MacIsValid (pc)) memcpy (bmcgwymac, pc, MAC_LEN); } else if (ival == 19) { /* dest addr */ if (IpIsValid (&pc[3])) memcpy (bmcdestip, &pc[3], 4); if (MacIsValid (&pc[7])) memcpy (bmcdestmac, &pc[7], MAC_LEN); } else if (ival == 22) { /*Cipher Suite Support */ nciphers = pc[0]; } /* now start to display data */ if (ival == 16) { printf ("%s \n", pc); /* string */ } else if (ival == 194 && vend_id == VENDOR_KONTRON) { printf ("%s \n", pc); /* string */ } else if (ival == 201) {; /* did it above */ } else { /* print results for all other ival's */ pstr = ""; /*interpreted meaning */ if (fcanonical) { switch (ival) { case 4: /*param 4, ip src */ if (pc[0] == SRC_STATIC) pstr = "Static"; /*0x01 */ else if (pc[0] == SRC_DHCP) pstr = "DHCP"; /*0x02 */ else if (pc[0] == SRC_BIOS) pstr = "BIOS"; /*0x03 */ else pstr = "Other"; printf ("%s\n", pstr); break; case 5: /*param 5, mac addr */ case 13: /*param 6, def gwy mac */ printf ("%02x:%02x:%02x:%02x:%02x:%02x\n", pc[0], pc[1], pc[2], pc[3], pc[4], pc[5]); break; case 3: /*param 4, ip address */ case 6: /*param 6, subnet mask */ case 12: /*param 12, def gwy ip */ case 14: /*param 14, sec gwy ip */ case 192: /*param 192, DHCP svr ip */ printf ("%d.%d.%d.%d\n", pc[0], pc[1], pc[2], pc[3]); break; case 19: /*param 19, dest address */ if (idest == 1) { printf ("IP=%d.%d.%d.%d " "MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", pc[3], pc[4], pc[5], pc[6], pc[7], pc[8], pc[9], pc[10], pc[11], pc[12]); } break; case 102: /*param 102, IPv6 enable */ if (pc[0] == 0x01) printf ("enabled\n"); else printf ("disabled\n"); break; default: printf ("%02x \n", pc[0]); break; } } else { /*not canonical */ if (ival == 3 || ival == 6 || ival == 12 || ival == 14 || ival == 192) { printf ("%d.%d.%d.%d", pc[0], pc[1], pc[2], pc[3]); } else if (ival == 23) { /*Cipher Suites */ for (i = 1; i <= nciphers; i++) { if (pc[i] == 0) ncipher0 = pc[i]; printf ("%2d ", pc[i]); } } else if (ival == 24) { /*Cipher Suite Privi Levels */ j = 0; for (i = 1; i < 9; i++) { char c1, c2; char *p; p = parse_priv ((pc[i] & 0x0f)); c1 = p[0]; p = parse_priv ((pc[i] & 0xf0) >> 4); c2 = p[0]; rgciphers[j++] = (pc[i] & 0x0f); rgciphers[j++] = ((pc[i] & 0xf0) >> 4); if ((i * 2) >= nciphers) c2 = ' '; printf (" %c %c ", c1, c2); if ((i * 2) > nciphers) break; } } else for (i = 0; i < sz; i++) { /* print in hex, decimal, or string, based on ival */ if (ival == 1) { /* Auth type support */ pstr = &mystr[0]; getauthstr (authmask, pstr); printf ("%02x ", authmask); } else if (ival == 4) { /* IP addr source */ if (pc[i] == SRC_STATIC) pstr = "Static"; /*0x01 */ else if (pc[i] == SRC_DHCP) pstr = "DHCP"; /*0x02 */ else if (pc[i] == SRC_BIOS) pstr = "BIOS"; /*0x03 */ else pstr = "Other"; printf ("%02x ", pc[i]); } else if (ival == 10) { /* grat ARP */ mystr[0] = 0; if (pc[i] == 0) strcat (mystr, "ARP disabled "); else if (pc[i] & 0x01) strcat (mystr, "Grat-ARP enabled"); else strcat (mystr, "Grat-ARP disabled"); if (pc[i] & 0x02) strcat (mystr, ", ARP-resp enabled"); pstr = &mystr[0]; printf ("%02x ", pc[i]); } else if (ival == 11) { /* grat ARP interval */ float f; f = (float) pc[i] / (float) 2; /*500msec increments */ sprintf (mystr, "%.1f sec", f); pstr = &mystr[0]; printf ("%02x ", pc[i]); } else if (ival == 19) { /* dest addr */ if (i > 2 && i < 7) { char *sepstr; if (i == 3) printf ("["); if (i == 6) sepstr = "] "; else if (i >= 3 && i < 6) sepstr = "."; else sepstr = " "; printf ("%d%s", pc[i], sepstr); /* IP address in dec */ } else printf ("%02x ", pc[i]); /* show mac/etc. in hex */ } else printf ("%02x ", pc[i]); /* show in hex */ } /*end for */ if (ival == 2) { /*Auth type enables */ pstr = &mystr[0]; i = 0; if (lan_ch > 0) i = lan_ch - 1; getauthstr (pc[i], pstr); } if (pstr[0] != 0) printf (": %s\n", pstr); else printf ("\n"); } /*end-else not canonical */ } /*end-else others */ if (ival == 18 || ival == 19) { if (idest < ndest) { idest++; idx--; /* repeat this param */ } else idest = 1; } } else { /* ret != 0 */ if (ival >= 20 && ival <= 25) { /*if errors, optional */ if (fdebug) printf ("GetLanEntry(%d), ret = %d\n", ival, ret); } else printf ("GetLanEntry(%d), ret = %d\n", ival, ret); if (ival == 17) ndest = 0; /*error getting num dest */ } } /*end for */ if (fRomley || fGrantley) { /*get LAN Failover param */ uchar b; ret = lan_failover_intel (0xFF, (uchar *) & b); if (ret != 0) printf ("Intel Lan Failover, ret = %d\n", ret); else { if (b == 1) pstr = "enabled"; else pstr = "disabled"; if (fcanonical) printf ("Intel Lan Failover %s%c %s\n", pspace3, bdelim, pstr); else printf ("Intel Lan Failover %s%c %02x %c %s\n", pspace2, bdelim, b, bdelim, pstr); } } if (vend_id == VENDOR_SUPERMICROX || vend_id == VENDOR_SUPERMICRO) { ret = oem_supermicro_get_lan_port (&bset); if (ret == 0) { pstr = oem_supermicro_lan_port_string (bset); if (fcanonical) printf ("SuperMicro Lan Interface %s%c %s\n", pspace2, bdelim, pstr); else printf ("SuperMicro Lan Interface %c %02x %c %s\n", bdelim, bset, bdelim, pstr); } else { if (fdebug) printf ("oem_supermicro_get_lan_port error %d\n", ret); ret = 0; /*may not be supported on all smc plaforms */ } } // if (fmBMC) lan_access = 0x04; /*Admin*/ // else lan_access = 0x04; /*Admin*/ if (!fIPMI10) { /* Get SOL params */ ret = GetSerialOverLan (lan_ch, 0, 0); if (ret != 0) { printf ("GetSOL error %d, %s\n", ret, decode_rv(ret)); ret = 0; /*does not fail entire command*/ } } for (i = 1; i <= show_users; i++) GetUser ((uchar) i, lan_ch); if (fgetser && !fcanonical) { printf ("\n%s, GetSerEntry ...\n", progname); if (fmBMC) /* mBMC doesn't support serial */ printf ("No serial channel support on this platform\n"); else for (idx = 0; idx < NSER; idx++) { int ival; // if (idx == 9) continue; /* not implemented */ ival = serparams[idx].cmd; if (ival == 201) { ret = GetChanAcc (ser_ch, 0x40, &LanRecord); } else { ret = GetSerEntry ((uchar) ival, &LanRecord); } if (ret == 0) { // Show the SER record pc = (uchar *) & LanRecord; sz = serparams[idx].sz; printf ("Serial Param(%d) %s: ", ival, serparams[idx].desc); if (idx == 10) { /* modem init string */ pc[sz] = 0; printf ("%02x %s\n", pc[0], &pc[1]); } else if ((idx >= 11 && idx <= 13) || idx == 15) { /* strings */ printf ("%s\n", pc); } else { for (i = 0; i < sz; i++) { printf ("%02x ", pc[i]); /* show in hex */ } printf ("\n"); } /*end else */ } } /*end for */ } /*endif fgetser */ if (!freadonly) { /* Set IPMI LAN enable/disable params. */ if (fipmilan) /* Sets not valid via ipmi_lan if same channel. */ printf ("\nWarning: Setting LAN %d params while using a LAN channel.\n", lan_ch); { if (fenable && (fsharedMAC == 0) && !lan_dhcp) { /* must have an IP from -I option */ if (!IpIsValid (rgmyip)) { /* if not user-specified */ if (IpIsValid (bmcmyip)) { memcpy (rgmyip, bmcmyip, 4); if (fdebug) printf ("Using current IP %d.%d.%d.%d\n", bmcmyip[0], bmcmyip[1], bmcmyip[2], bmcmyip[3]); } else { printf ("\nNot shared BMC LAN, must specify a unique " "IP address via -I\n"); ret = ERR_BAD_PARAM; goto do_exit; } } } /* Set LAN parameters. fenable or fdisable */ printf ("\n%s, SetLanEntry for channel %d ...\n", progname, lan_ch); /* use ifname to resolve MAC addresses below */ if (fdisable) { if (!fIPMI10) { ret = DisablePef (alertnum); printf ("DisablePef, ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } if (lan_user != 0) { j = DisableUser (lan_user, lan_ch); /*disable this lan user */ printf ("DisableUser(%d), ret = %d\n", lan_user, j); if (j != 0) { nerrs++; lasterr = j; } else ngood++; } LanRecord.data[0] = 0x01; /* static IP address source */ ret = SetLanEntry (4, &LanRecord, 1); printf ("SetLanEntry(4), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; /* clear the BMC IP address */ memset (&LanRecord, 0, 4); ret = SetLanEntry (3, &LanRecord, 4); printf ("SetLanEntry(3), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; /* clear the gateway IP address */ memset (&LanRecord, 0, 4); ret = SetLanEntry (12, &LanRecord, 4); printf ("SetLanEntry(12), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; /* clear the gateway MAC address */ memset (&LanRecord, 0, 6); ret = SetLanEntry (13, &LanRecord, 6); printf ("SetLanEntry(13), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } else if (fdisableSOL) { ret = SetupSerialOverLan (0); /*disable */ SELprintf ("SetupSerialOverLan: ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } else { /*fenable */ uchar chanctl; if (bmcpefctl != 0) chanctl = chan_pefon; /*previously on */ else chanctl = chan_pefoff; ret = SetChanAcc (lan_ch, 0x80, chanctl); if (fdebug) printf ("SetChanAcc(lan/active), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; ret = SetChanAcc (lan_ch, 0x40, chanctl); if (fdebug) printf ("SetChanAcc(lan/nonvol), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; if (flansecure) { j = DisableUser (0, lan_ch); /*disable the default null user */ printf ("DisableUser(0), ret = %d\n", j); } ret = SetUser (lan_user, myuser, passwordData, lan_ch); printf ("SetUser(%d), ret = %d\n", lan_user, ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } if (fdisable && (vend_id == VENDOR_SUPERMICROX || vend_id == VENDOR_SUPERMICRO)) { failover_enable = 0; /*dedicated */ ret = oem_supermicro_set_lan_port (failover_enable); printf ("Set SuperMicro Lan port to %s, ret = %d\n", oem_supermicro_lan_port_string (failover_enable), ret); if (ret != 0) { nerrs++; lasterr = ret; } } if (fdisable || fdisableSOL) { // if (nerrs > 0) printf("Warning: %d errors occurred\n",nerrs); goto do_exit; } if (authmask == 0) authmask = 0x17; /*if none from GetLanEntry(1) */ LanRecord.data[0] = (bAuth & authmask); /*Callback level */ LanRecord.data[1] = (bAuth & authmask); /*User level */ LanRecord.data[2] = (bAuth & authmask); /*Operator level */ LanRecord.data[3] = (bAuth & authmask); /*Admin level */ LanRecord.data[4] = 0; /*OEM level */ if (fdebug) printf ("SetLanEntry(2): %02x %02x %02x %02x %02x\n", LanRecord.data[0], LanRecord.data[1], LanRecord.data[2], LanRecord.data[3], LanRecord.data[4]); ret = SetLanEntry (2, &LanRecord, 5); printf ("SetLanEntry(2), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; /* Get the values to use from Linux eth0, etc. */ ret = Get_IPMac_Addr (); if (lan_dhcp) { /* use DHCP */ LanRecord.data[0] = SRC_DHCP; /* BMC running DHCP */ /* = SRC_BIOS; * address source = BIOS using DHCP */ ret = SetLanEntry (4, &LanRecord, 1); printf ("SetLanEntry(4), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; if (MacIsValid (rgmymac)) { memcpy (&LanRecord, rgmymac, 6); ret = SetLanEntry (5, &LanRecord, 6); if (ret == 0x82) { /*BMC may not allow the MAC to be set */ if (fdebug) printf ("SetLanEntry(5), ret = %x cannot modify MAC\n", ret); } else { printf ("SetLanEntry(5), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } /* DHCP also relates to OEM LAN params 192, 193, 194 */ if ((vend_id == VENDOR_INTEL) && !fmBMC && !fiBMC) { /*DHCP params 192-194 are Intel only */ if (IpIsValid (rgmyip)) { /* Set DHCP Server IP in param 192 from -I param. */ memcpy (&LanRecord, rgmyip, 4); ret = SetLanEntry (192, &LanRecord, 4); printf ("SetLanEntry(192), ret = %d\n", ret); if (!MacIsValid (rgdhcpmac)) /* if MAC not set yet */ ret = Get_Mac (rgmyip, rgdhcpmac, NULL); if (ret == 0) { memcpy (&LanRecord, rgdhcpmac, MAC_LEN); ret = SetLanEntry (193, &LanRecord, MAC_LEN); printf ("SetLanEntry(193), ret = %d\n", ret); } } LanRecord.data[0] = 0x01; /*enable DHCP */ ret = SetLanEntry (194, &LanRecord, 1); printf ("SetLanEntry(194), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } else { /* use static IP */ printf ("LAN%d (%s)\tip=%d.%d.%d.%d mac=%02x:%02x:%02x:%02x:%02x:%02x\n", lan_ch, ifname, rgmyip[0], rgmyip[1], rgmyip[2], rgmyip[3], rgmymac[0], rgmymac[1], rgmymac[2], rgmymac[3], rgmymac[4], rgmymac[5]); if (IpIsValid (rgmyip)) { if (lan_ch != gcm_ch) { /*skip if gcm */ LanRecord.data[0] = 0x00; /*disable grat arp while setting IP */ ret = SetLanEntry (10, &LanRecord, 1); if (fdebug) printf ("SetLanEntry(10,0), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } } LanRecord.data[0] = 0x01; /* static IP address source */ ret = SetLanEntry (4, &LanRecord, 1); printf ("SetLanEntry(4), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; memcpy (&LanRecord, rgmyip, 4); ret = SetLanEntry (3, &LanRecord, 4); printf ("SetLanEntry(3), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; if (MacIsValid (rgmymac)) { memcpy (&LanRecord, rgmymac, 6); ret = SetLanEntry (5, &LanRecord, 6); if (ret == 0x82) { /* Do not show anything, not an error if BMC does not allow the BMC MAC to be changed. */ if (fdebug) printf ("SetLanEntry(5), ret = %x cannot modify MAC\n", ret); } else { printf ("SetLanEntry(5), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } if (!SubnetIsValid (rgsubnet)) /* not specified, use previous */ memcpy (rgsubnet, bmcsubnet, 4); memcpy (&LanRecord, rgsubnet, 4); ret = SetLanEntry (6, &LanRecord, 4); printf ("SetLanEntry(6), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; if (vend_id != VENDOR_PEPPERCON) { /* may want to check bparm7 here */ LanRecord.data[0] = parm7[0]; /*IPv4 header, TTL */ LanRecord.data[1] = parm7[1]; /*IPv4 header, Flags */ LanRecord.data[2] = parm7[2]; /*IPv4 hdr, Precedence/Service */ ret = SetLanEntry (7, &LanRecord, 3); printf ("SetLanEntry(7), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } /* if lan_ch == 3, gcm gets error setting grat arp (ccode=0xCD) */ if (lan_ch != gcm_ch) { /*skip if gcm */ /* 01=enable grat arp, 02=enable arp resp, 03=both */ LanRecord.data[0] = arp_ctl; /*grat arp */ ret = SetLanEntry (10, &LanRecord, 1); printf ("SetLanEntry(10,%x), ret = %d\n", arp_ctl, ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } LanRecord.data[0] = arp_interval; /*grat arp interval */ ret = SetLanEntry (11, &LanRecord, 1); printf ("SetLanEntry(11), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } if ((vend_id == VENDOR_INTEL) && !fmBMC && !fiBMC) { LanRecord.data[0] = 0x00; /*disable DHCP */ ret = SetLanEntry (194, &LanRecord, 1); printf ("SetLanEntry(194), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } else { /* error, don't continue */ printf ("Missing IP Address, can't continue. Use -I to specify\n"); ret = ERR_BAD_PARAM; goto do_exit; } if (vend_id == VENDOR_KONTRON && rghostname[0] != 0) { /* set the IPMI Hostname if specified */ sz = strlen_ (rghostname); /* LanRecord is larger than rghostname, bounds ok */ strncpy ((char *) &LanRecord.data, rghostname, sz); ret = SetLanEntry (194, &LanRecord, sz); printf ("SetLanEntry(194), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else { LanRecord.data[0] = 0x31; ret = SetLanEntry (195, &LanRecord, 1); /*re-read hostname */ // printf("SetLanEntry(195), ret = %d\n",ret); // if (ret != 0) { nerrs++; lasterr = ret; } } } if (IpIsValid (rggwyip)) { if (!MacIsValid (rggwymac)) /* if gwy MAC not set by user */ ret = Get_Mac (rggwyip, rggwymac, NULL); printf ("gateway \tip=%d.%d.%d.%d mac=%02x:%02x:%02x:%02x:%02x:%02x\n", rggwyip[0], rggwyip[1], rggwyip[2], rggwyip[3], rggwymac[0], rggwymac[1], rggwymac[2], rggwymac[3], rggwymac[4], rggwymac[5]); if (!SubnetIsSame (rgmyip, rggwyip, rgsubnet)) { printf ("WARNING: IP Address and Gateway are not on the same subnet," " setting Gateway to previous value\n"); memcpy (rggwyip, bmcgwyip, 4); memcpy (rggwymac, bmcgwymac, 6); } /* Set the Default Gateway IP & MAC */ memcpy (&LanRecord, rggwyip, 4); ret = SetLanEntry (12, &LanRecord, 4); printf ("SetLanEntry(12), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; if (!MacIsValid (rggwymac)) { /* if gwy MAC not resolved */ printf (" Warning: Gateway MAC address was not resolved! " "Check %s interface, use -i ethN, or use -H gwymac.\n", ifname); memcpy (&LanRecord, bmcgwymac, 6); } else { memcpy (&LanRecord, rggwymac, 6); } ret = SetLanEntry (13, &LanRecord, 6); printf ("SetLanEntry(13), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } if (IpIsValid (rggwy2ip)) { if (!MacIsValid (rggwy2mac)) /* if gwy2 MAC not set by user */ ret = Get_Mac (rggwy2ip, rggwy2mac, NULL); /* Set the Secondary Gateway IP & MAC */ memcpy (&LanRecord, rggwy2ip, 4); ret = SetLanEntry (14, &LanRecord, 4); printf ("SetLanEntry(14), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; memcpy (&LanRecord, rggwy2mac, 6); ret = SetLanEntry (15, &LanRecord, 6); printf ("SetLanEntry(15), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } /* end-else static IP */ if (flansecure) { /* disable cipher 0 */ char c1, c2; memset (&LanRecord, 0, 12); j = 1; for (i = 0; i < nciphers; i += 2) { c1 = rgciphers[i]; c2 = rgciphers[i + 1]; /* 0x0f may be vendor-specific, 0x00 = Reserved/Unused */ if (i == ncipher0) c1 = 0x00; if ((i + 1) == ncipher0) c2 = 0x00; LanRecord.data[j++] = (c2 << 4) | c1; } ret = SetLanEntry (24, &LanRecord, 9); printf ("SetLanEntry(24) disable cipher0, ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } ret = SetupSerialOverLan (1); /*enable */ SELprintf ("SetupSerialOverLan: ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; if (!IpIsValid (rgdestip) && IpIsValid (bmcdestip)) { memcpy (rgdestip, bmcdestip, 4); if (fdebug) printf ("Using current dest IP %d.%d.%d.%d\n", bmcdestip[0], bmcdestip[1], bmcdestip[2], bmcdestip[3]); } if (ndest == 0) { if (fdebug) printf ("ndest==0, anum=%d rgdestip=%d.%d.%d.%d\n", alertnum, rgdestip[0], rgdestip[1], rgdestip[2], rgdestip[3]); printf ("alert dest \tnot supported\n"); } else if (!IpIsValid (rgdestip)) { printf ("alert dest \taddress not specified\n"); } else { /* valid alert dest ip */ if (!MacIsValid (rgdestmac)) /* if dest MAC not set by user */ ret = Get_Mac (rgdestip, rgdestmac, NULL); /*try to resolve MAC */ if (!MacIsValid (rgdestmac)) { /* if dest MAC not resolved */ printf (" Warning: Alert mac address was not resolved!" " Check %s interface or use -i.\n", ifname); /* use existing BMC alert dest mac (as best guess) */ memcpy (rgdestmac, bmcdestmac, 6); } /* show destination data */ printf("alert dest %d\tip=%d.%d.%d.%d mac=%02x:%02x:%02x:%02x:%02x:%02x\n", alertnum, rgdestip[0], rgdestip[1], rgdestip[2], rgdestip[3], rgdestmac[0], rgdestmac[1], rgdestmac[2], rgdestmac[3], rgdestmac[4], rgdestmac[5]); printf ("snmp community \t%s\n", rgcommunity); /* Only need the SNMP community if there is an Alert Destination */ memset (&LanRecord.data[0], 0, 18); /* make sure zero-filled */ strcpy ((char *) &LanRecord.data[0], rgcommunity); ret = SetLanEntry (16, &LanRecord, 18); printf ("SetLanEntry(16), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; /* Set Alert Destination Type */ LanRecord.data[0] = alertnum; /* dest id = 1 */ LanRecord.data[1] = 0x00; /* dest type = PET, no ack */ LanRecord.data[2] = 0x01; /* ack timeout / retry interval */ LanRecord.data[3] = 0x00; /* no retries */ // LanRecord.data[4] = 0x69; ret = SetLanEntry (18, &LanRecord, 4); printf ("SetLanEntry(18), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; { /* Set the Alert Destination IP & MAC (param 19) */ LanRecord.data[0] = alertnum; /* dest id = 1 */ LanRecord.data[1] = 0x00; LanRecord.data[2] = 0x00; memcpy (&LanRecord.data[3], rgdestip, 4); memcpy (&LanRecord.data[7], rgdestmac, 6); ret = SetLanEntry (19, &LanRecord, 13); printf ("SetLanEntry(19), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } /*endif valid alert */ /* Now enable PEF since we have an Alert destination. */ if (!fdisable && !fIPMI10 && fpefenable) { /*fpefenable */ ret = EnablePef (alertnum); printf ("EnablePef, ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; /* ChanAcc changed, so show it again */ j = ShowChanAcc (lan_ch); } if ((vlan_enable != PARM_INIT) && (fIPMI20)) { if (vlan_enable == 0) { /*disable vlan */ LanRecord.data[0] = 0x00; LanRecord.data[1] = 0x00; ret = SetLanEntry (20, &LanRecord, 2); printf ("SetLanEntry(20,disable) ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } else { /*vlan_enable == 1, enable vlan with id */ LanRecord.data[0] = (vlan_id & 0x00ff); LanRecord.data[1] = ((vlan_id & 0x0f00) >> 8) | 0x80; ret = SetLanEntry (20, &LanRecord, 2); printf ("SetLanEntry(20,%d), ret = %d\n", vlan_id, ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; LanRecord.data[0] = vlan_prio; ret = SetLanEntry (21, &LanRecord, 1); printf ("SetLanEntry(21), ret = %d\n", ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } if (failover_enable != PARM_INIT) { if (fRomley || fGrantley) { if (failover_enable > 1) failover_enable = 0; /*default */ ret = lan_failover_intel (failover_enable, (uchar *) & i); printf ("Set Intel Lan Failover (%d), ret = %d\n", failover_enable, ret); if (ret != 0) { nerrs++; lasterr = ret; } } else if (vend_id == VENDOR_SUPERMICROX || vend_id == VENDOR_SUPERMICRO) { if (failover_enable > 2) failover_enable = 2; /*default */ ret = oem_supermicro_set_lan_port (failover_enable); printf ("Set SuperMicro Lan port to %s, ret = %d\n", oem_supermicro_lan_port_string (failover_enable), ret); if (ret != 0) { nerrs++; lasterr = ret; } } } /*endif failover specified */ } /*end-else not via ipmi_lan */ } /*endif not readonly */ if (flanstats) { /* get BMC LAN Statistics */ #ifdef METACOMMAND j = get_lan_stats (lan_ch); #else uchar idata[2]; uchar rdata[20]; int rlen; uchar cc; idata[0] = lan_ch; idata[1] = 0x00; /*do not clear stats */ rlen = sizeof (rdata); j = ipmi_cmd (GET_LAN_STATS, idata, 2, rdata, &rlen, &cc, fdebug); if (j == 0) { /*show BMC LAN stats */ ushort *rw; rw = (ushort *) & rdata[0]; printf ("IPMI LAN channel %d statistics: \n", lan_ch); printf (" \tReceived IP Packets = %d\n", rw[0]); printf (" \tRecvd IP Header errors = %d\n", rw[1]); printf (" \tRecvd IP Address errors = %d\n", rw[2]); printf (" \tRecvd IP Fragments = %d\n", rw[3]); printf (" \tTransmitted IP Packets = %d\n", rw[4]); printf (" \tReceived UDP Packets = %d\n", rw[5]); printf (" \tReceived Valid RMCP Pkts = %d\n", rw[6]); printf (" \tReceived UDP Proxy Pkts = %d\n", rw[7]); printf (" \tDropped UDP Proxy Pkts = %d\n", rw[8]); } #endif } do_exit: ipmi_close_ (); if (foptmsg) { if (fset_ip != 0) printf ("WARNING: IP address options were specified, but no -e,-l,-d option.\n"); else printf ("WARNING: %d options were specified, but no -e,-l,-d option.\n", nopts); printf ("Read-only usage assumed.\n"); } if (nerrs > 0) { printf ("Warning: %d ok, %d errors occurred, last error = %d\n", ngood, nerrs, lasterr); ret = lasterr; } // show_outcome(progname,ret); return (ret); } /* end main() */ /* end ilan.c */ ipmiutil-3.1.5/util/ipmilan.c0000644000076400007640000022736113566765324016243 0ustar mgportalloggers/*M* // PVCS: // $Workfile: ipmilan.c $ // $Revision: 1.0 $ // $Modtime: 2 Feb 2006 15:31:14 $ // $Author: arcress at users.sourceforge.net $ // // This implements support for the IPMI LAN interface natively. // // 02/02/06 ARC - created. // 05/16/06 ARC - more added. // 06/19/06 ARCress - fixed sequence numbers for 1.7.1 // 08/08/06 ARCress - fix AUTHTYPE masks // 08/11/06 ARCress - added lan command retries // 10/17/06 ARCress - special case for no MsgAuth headers // 11/28/06 ARCress - added ipmi_cmd_ipmb routine // 05/08/07 ARCress - added 1.5 SOL data packet format to _send_lan_cmd, // not working yet. // 08/21/07 ARCress - handle Dell 1855 blades that return different authcode // 04/17/08 ARCress - check FD_ISSET in fd_wait *M*/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2005-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 Corporation 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. *----------------------------------------------------------------------*/ #ifdef WIN32 #include #include #include #include #include #include #include //#define HAVE_IPV6 1 #ifdef HAVE_IPV6 #include //#include //#include #else #include #define MSG_WAITALL 0x100 /* Wait for a full request */ #endif #define INET_ADDRSTRLEN 16 #define MSG_NONE 0x000 #define int32_t int #define u_int32_t unsigned int #define uint32 unsigned int #define uchar unsigned char #define RECV_MSG_FLAGS MSG_NONE typedef unsigned int socklen_t; #elif defined(DOS) #include #include #include #include #undef HAVE_LANPLUS #else /* Linux, BSD, etc. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HPUX #define RECV_MSG_FLAGS 0x40 /*match MSG_WAITALL for HPUX*/ #else #define RECV_MSG_FLAGS MSG_WAITALL #endif #endif #include "ipmicmd.h" #include "ipmilan.h" #if defined(HAVE_CONFIG_H) #include "config.h" #else #if defined(MACOS) typedef unsigned int socklen_t; #endif #endif #if defined(LINUX) /* TODO: fixups in BSD/Solaris for ipv6 method */ #define HAVE_IPV6 1 #endif #if defined(CROSS_COMPILE) #undef HAVE_IPV6 static struct hostent *xgethostbyname(const char *nstr) { static struct hostent hptr; if (StrIsIp(nstr)) { /* the string is an IP address */ hptr.h_name = (char *)nstr; inet_aton(nstr,(struct in_addr *)&hptr.h_addr); return(&hptr); } else { /*the string is a node name */ return(NULL); } } #else #define xgethostbyname gethostbyname #endif // #define TEST_LAN 1 /*++++TEST_LAN for DEBUG++++*/ #if defined(ALLOW_GNU) #define MD2OK 1 /*use md2.h GPL code*/ #else /* if here, ALLOW_GPL is not defined, check for lanplus libcrypto. */ #if defined(HAVE_LANPLUS) #define MD2OK 1 /*use MD2 version from lanplus libcrypto */ #endif /* if libcrypto does not have EVP_md2, then skip MD2. */ #if defined(SKIP_MD2) #undef MD2OK #endif #endif /* Connection States: * 0 = init, 1 = socket() complete, 2 = bind/gethost complete, * 3 = ping sent, 4 = pong received, 5 = session activated. * see also conn_state_str[] below */ #define CONN_STATE_INIT 0 #define CONN_STATE_SOCK 1 #define CONN_STATE_BIND 2 #define CONN_STATE_PING 3 #define CONN_STATE_PONG 4 #define CONN_STATE_ACTIVE 5 #define SOL_DATA 0xFD /*SOL Data command*/ #define SOL_MSG 0x10000000 /*SOL message type*/ #define SOL_HLEN 14 // SZGNODE == 80 #define SZ_CMD_HDR 4 /*cmd, netfn/lun, sa*/ #define SWID_REMOTE 0x81 #define SWID_SMSOS 0x41 #pragma pack(1) typedef struct { /*first 30 bytes conform to IPMI header format*/ uchar rmcp_ver; uchar rmcp_res; uchar rmcp_seq; uchar rmcp_type; uchar auth_type; uint32 seq_num; /*outgoing seq*/ uint32 sess_id; uchar auth_code[16]; uchar msg_len; /* size here = 30 bytes = RQ_HDR_LEN */ uchar swid; /* usu SWID_REMOTE. From here down, order is changeable */ uchar swseq; /* outgoing swseq */ uchar swlun; uchar priv_level; uint32 iseq_num; /*incoming seq */ uchar bmc_addr; /*usu BMC_SA*/ uchar target_addr; uchar target_chan; uchar target_lun; uchar target_cmd; uchar target_netfn; uchar transit_addr; uchar transit_chan; uchar bridge_level; uchar password[16]; uchar challenge[16]; } IPMI_HDR; #pragma pack() typedef struct { int type; int len; char *data; } SOL_RSP_PKT; /* extern void atoip(uchar *array,char *instr); *subs.c*/ extern FILE *open_log(char *mname); /*ipmicmd.c*/ extern char * get_iana_str(int mfg); /*subs.c*/ #define dbglog printf #define dbg_dump dump_buf extern FILE *fperr; /*defined in ipmicmd.c, usu stderr */ extern FILE *fpdbg; /*defined in ipmicmd.c, usu stdout */ extern int gshutdown; /* from ipmicmd.c, usu =0 */ extern int fauth_type_set; /* from ipmicmd.c */ extern LAN_OPT lanp; /* from ipmicmd.c */ //extern char *gnode; /* from ipmicmd.c */ //extern char *guser; /* from ipmicmd.c */ //extern char *gpswd; /* from ipmicmd.c */ //extern int gauth_type; /* from ipmicmd.c */ //extern int gpriv_level; /* from ipmicmd.c */ extern ipmi_cmd_t ipmi_cmds[NCMDS]; static IPMI_HDR ipmi_hdr = { 0x06, 0, 0xFF, 0x07, 0x00, 0, 0, /*auth_code*/{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0, /*msg_len*/ /*swid*/SWID_REMOTE, 1,0,0,0, BMC_SA,0,0,0,0,0,0,0,0 /*bridge_level*/ }; // static IPMI_HDR *phdr; static uchar bmc_sa = BMC_SA; /*usu 0x20*/ static uchar sms_swid = SWID_REMOTE; /*usu 0x81*/ static int vend_id = 0; static int prod_id = 0; #if defined(DOS) || defined(EFI) int ipmi_open_lan(char *node, char *user, int port, char *pswd, int fdebugcmd) { printf("IPMI LAN is not supported under DOS.\n"); return(-1); } int ipmi_close_lan(char *node) { printf("IPMI LAN is not supported under DOS.\n"); return(-1); } int ipmi_cmd_lan(char *node, ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { printf("IPMI LAN is not supported under DOS.\n"); return(-1); } int ipmi_cmdraw_lan(char *node, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { printf("IPMI LAN is not supported under DOS.\n"); return(-1); } int ipmicmd_lan(char *node, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { printf("IPMI LAN is not supported under DOS.\n"); return(-1); } #else /* All other OSs can support IPMI LAN */ /* * These variables pertain to ipmilan, for the node given at open time. * The assumption here is that these are utilities, so no more than one * node will be open at a given time. * See also gnode, guser, gpswd in ipmicmd.c */ typedef struct { int connect_state; /*=CONN_STATE_INIT*/ SockType sockfd; int finsession; uint32 session_id; uint32 in_seq; /*=1*/ uint32 start_out_seq; /*=1*/ uchar fMsgAuth; /*0=AuthNone 1=PerMsgAuth 2=UserLevelAuth*/ uchar auth_type; /*=AUTHTYPE_INIT*/ } LAN_CONN; /*see also IPMI_HDR below*/ // static int connect_state = CONN_STATE_INIT; // static int sockfd = 0; // static int finsession = 0; // static uint32 session_id = 0; // static uint32 in_seq = 0x01; /* inbound sequence num */ // static uint32 start_out_seq = 0x01; /* initial outbound sequence num */ // static uchar fMsgAuth = 1; static uchar auth_type = AUTHTYPE_INIT; /*initial value, not set*/ static char nodename[SZGNODE+1] = ""; static char gnodename[SZGNODE+1] = ""; /*nodename returned after connection*/ #if defined(AI_NUMERICSERV) static int my_ai_flags = AI_NUMERICSERV; /*0x0400 Dont use name resolution NEW*/ // static int my_ai_flags = AI_NUMERICHOST; /*0x0004 Dont use name resolution*/ #else #undef HAVE_IPV6 #endif #ifdef HAVE_IPV6 #define SOCKADDR_T struct sockaddr_storage #else #define SOCKADDR_T struct sockaddr_in static char _dest_ip[INET_ADDRSTRLEN+1]; // static char _dest[MAXHOSTNAMELEN+1]; #endif static SOCKADDR_T _srcaddr; static SOCKADDR_T _destaddr; static int _destaddr_len = 0; #ifdef TEST_LAN static int fdebuglan = 3; #else static int fdebuglan = 0; #endif static int fdoping = 0; /* =1 do ping first, set to 0 b/c no added value*/ static int fdopoke1 = 0; static int fdopoke2 = 0; static int frequireping = 0; /*=1 if ping is required, =0 ignore ping error */ static LAN_CONN conn = {CONN_STATE_INIT,0,0,0,1,1,1}; static LAN_CONN *pconn = &conn; static char *authcode = NULL; static int authcode_len = 0; static int ping_timeout = 1; /* timeout: 1 sec */ static int ipmi_timeout = 2; /* timeout: 10 sec -> 2 sec */ static int ipmi_try = 4; /* retries: 4 */ static uchar bridgePossible = 0; static char *conn_state_str[6] = { "init state", "socket complete", "bind complete", "ping sent", "pong received", "session activated" }; int lasterr = 0; static uchar sol_op = 0x80; /* encrypted/not */ static uchar sol_snd_seq = 0; /* valid if non-zero*/ static uchar sol_rcv_seq = 0; static uchar sol_rcv_cnt = 0; static uchar sol_rcv_ctl = 0x00; // static uchar sol_offset = 0; static uchar sol_seed_cnt = 0x01; /* set after activate response */ static char sol_Encryption = 0; /*for SOL 1.5*/ static uint32 g_Seed[ 16 ]; /*for SOL 1.5*/ static uchar g_Cipher[ 16 ][ 16 ]; /*SeedCount x CipherHash for SOL 1.5*/ #define BUSY_MAX 10 /*for Dell FS12-TY Node Busy errors*/ #ifdef WIN32 int econnrefused = WSAECONNREFUSED; /*=10061.*/ int econnreset = WSAECONNRESET; /*=10054.*/ #else int econnrefused = ECONNREFUSED; /*=111. from Linux asm/errno.h */ int econnreset = ECONNRESET; /*=104.*/ #endif #ifdef WIN32 WSADATA lan_ws; /* See http://msdn2.microsoft.com/en-us/library/ms740668.aspx * or doc/winsockerr.txt */ #define NWINERRS 21 static struct { int err; char *desc; } winerrs[NWINERRS] = { WSAEINTR /*10004*/, "Interrupted function call", WSAEBADF /*10009*/, "File handle is not valid", WSAEACCES /*10013*/, "Permission denied", WSAEFAULT /*10014*/, "Bad address", WSAEINVAL /*10022*/, "Invalid argument", WSAEMFILE /*10024*/, "Too many open files", WSAENOTSOCK /*10038*/, "Socket operation on nonsocket", WSAEDESTADDRREQ /*10039*/, "Destination address required", WSAEMSGSIZE /*10040*/, "Message too long", WSAEOPNOTSUPP /*10045*/, "Operation not supported", WSAEADDRINUSE /*10048*/, "Address already in use", WSAEADDRNOTAVAIL /*10049*/, "Cannot assign requested address", WSAENETDOWN /*10050*/, "Network is down", WSAENETUNREACH /*10051*/, "Network is unreachable", WSAENETRESET /*10052*/, "Network dropped connection on reset", WSAECONNABORTED /*10053*/, "Software caused connection abort", WSAECONNRESET /*10054*/, "Connection reset by peer", WSAENOTCONN /*10057*/, "Socket is not connected", WSAECONNREFUSED /*10061*/, "Connection refused", WSAEHOSTDOWN /*10064*/, "Host is down", WSAEHOSTUNREACH /*10065*/, "No route to host" }; char * strlasterr(int rv) { char *desc; int i; for (i = 0; i < NWINERRS; i++) { if (winerrs[i].err == rv) { desc = winerrs[i].desc; break; } } if (i >= NWINERRS) desc = ""; return(desc); } #endif #ifdef MD2OK extern void md2_sum(uchar *string, int len, uchar *mda); /*from md2.c*/ #endif extern void md5_sum(uchar *string, int len, uchar *mda); /*from md5.c*/ int _ipmilan_cmd(SockType s, struct sockaddr *to, int tolen, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *sdata, int slen, uchar *rdata, int *rlen, int fdebugcmd); static int _send_lan_cmd(SockType s, uchar *pcmd, int scmd, uchar *presp, int *sresp, struct sockaddr *to, int tolen); static int ipmilan_open_session(SockType sfd, struct sockaddr *destaddr, int destaddr_len, uchar auth_type, char *username, char *authcode, int authcode_len, uchar priv_level, uint32 init_out_seqnum, uint32 *session_seqnum, uint32 *session_id); static int ipmilan_close_session(SockType sfd, struct sockaddr *destaddr, int destaddr_len, uint32 session_id); uchar cksum(const uchar *buf, register int len); char *decode_rv(int rv); /*moved to ipmicmd.c*/ void show_LastError(char *tag, int err) { #ifdef WIN32 fprintf(fperr,"%s LastError = %d %s\n",tag,err,strlasterr(err)); #else char *s; s = strerror(err); if (s == NULL) s = "error"; fprintf(fperr,"%s errno = %d, %s\n",tag,err,s); #endif } int get_LastError( void ) { #ifdef WIN32 lasterr = WSAGetLastError(); #else lasterr = errno; #endif return(lasterr); } static void cc_challenge(int cc) { switch(cc) { case 0x81: printf("GetSessChallenge: Invalid user name\n"); break; case 0x82: printf("GetSessChallenge: Null user name not enabled\n"); break; default: printf("GetSessChallenge: %s\n",decode_cc((ushort)0,cc)); break; } } static void cc_session(int cc) { switch(cc) { case 0x81: printf("ActivateSession: No session slots available from BMC\n"); break; case 0x82: printf("ActivateSession: No sessions available for this user\n"); break; case 0x83: printf("ActivateSession: No sessions for this user/privilege\n"); break; case 0x84: printf("ActivateSession: Session sequence number out of range\n"); break; case 0x85: printf("ActivateSession: Invalid session ID in request\n"); break; case 0x86: printf("ActivateSession: Privilege level exceeds user/channel limit\n"); break; default: printf("%s\n",decode_cc((ushort)0,cc)); break; } return; } int StrIsIp(char *str) { int i, j, n; char ipchars[11] = "0123456789."; int ndot = 0; int rv = 0; /* checks if the string looks like an IP address. */ if (str == NULL) return(rv); n = (int)strlen(str); for (i = 0; i < n; i++) { for (j = 0; j < 11; j++) if (str[i] == ipchars[j]) break; if (j >= 11) break; /*some other char, not valid*/ if (str[i] == '.') ndot++; } if ((i == n) && (ndot == 3)) rv = 1; /*valid*/ return(rv); } void close_sockfd(SockType sfd); void close_sockfd(SockType sfd) { if (sfd == 0) return; #ifdef WIN32 // shutdown(sfd,SD_SEND); /*done sending*/ closesocket(sfd); /*close lan socket */ WSACleanup(); #else alarm(0); signal(SIGALRM,SIG_DFL); signal(SIGINT,SIG_DFL); close(sfd); /*close lan socket */ #endif pconn->sockfd = 0; /*set global to zero */ } int open_sockfd(char *node, int port, SockType *sfd, SOCKADDR_T *daddr, int *daddr_len, int foutput); int open_sockfd(char *node, int port, SockType *sfd, SOCKADDR_T *daddr, int *daddr_len, int foutput) { int rv = 0; SockType s, _sockfd = -1; #ifdef HAVE_IPV6 struct addrinfo hints; struct addrinfo *res, *res0; char service[NI_MAXSERV]; #else struct hostent *hptr; #endif #ifdef WIN32 DWORD rvl; if (sfd == NULL || daddr == NULL || daddr_len == NULL) return(-3); /* invalid pointer */ rvl = WSAStartup(0x0202,&lan_ws); if (rvl != 0) { fprintf(fperr,"lan, WSAStartup(2.2) error %ld, try 1.1\n", rvl); WSACleanup(); rvl = WSAStartup(0x0101,&lan_ws); if (rvl != 0) { fprintf(fperr,"lan, WSAStartup(1.1) error %ld\n", rvl); WSACleanup(); return((int)rvl); } } #else if (sfd == NULL || daddr == NULL || daddr_len == NULL) return(-3); /* invalid pointer */ #endif pconn->connect_state = CONN_STATE_INIT; #ifdef HAVE_IPV6 memset(&_srcaddr, 0, sizeof(_srcaddr)); memset(daddr, 0, sizeof(_destaddr)); sprintf(service, "%d", port); /* Obtain address(es) matching host/port */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = my_ai_flags; hints.ai_protocol = IPPROTO_UDP; /* */ rv = getaddrinfo(node, service, NULL, &res); if (rv != 0) { printf("Address lookup for %s failed, getaddrinfo error %d\n", node,rv); return rv; } /* getaddrinfo() returns a list of address structures. * Try each address until we successfully connect(2). * If socket(2) (or connect(2)) fails, we (close the socket * and) try the next address. */ for (res0 = res; res0 != NULL; res0 = res0->ai_next) { /* valid protocols are IPPROTO_UDP, IPPROTO_IPV6 */ if (res0->ai_protocol == IPPROTO_TCP) continue; /*IPMI != TCP*/ s = socket(res0->ai_family, res0->ai_socktype, res0->ai_protocol); if (s == SockInvalid) continue; else _sockfd = s; pconn->connect_state = CONN_STATE_SOCK; rv = connect(_sockfd, res0->ai_addr, res0->ai_addrlen); if (fdebuglan) printf("socket(%d,%d,%d), connect(%d) rv = %d\n", res0->ai_family, res0->ai_socktype, res0->ai_protocol, s,rv); if (rv != -1) { memcpy(daddr, res0->ai_addr, res0->ai_addrlen); *daddr_len = res0->ai_addrlen; break; /* Success */ } close_sockfd(_sockfd); _sockfd = -1; } freeaddrinfo(res); /* Done with addrinfo */ if (_sockfd < 0) { printf("Connect to %s failed\n", node); // ipmi_close_(); rv = -1; } #else /* Open lan interface (ipv4 method) */ s = socket(AF_INET, SOCK_DGRAM, 0); if (s == SockInvalid) return (-1); else _sockfd = s; pconn->connect_state = CONN_STATE_SOCK; memset(&_srcaddr, 0, sizeof(_srcaddr)); _srcaddr.sin_family = AF_INET; _srcaddr.sin_port = htons(0); _srcaddr.sin_addr.s_addr = htonl(INADDR_ANY); rv = bind(_sockfd, (struct sockaddr *)&_srcaddr, sizeof(_srcaddr)); if (rv < 0) { close_sockfd(_sockfd); return (rv); } memset(daddr, 0, sizeof(SOCKADDR_T)); daddr->sin_family = AF_INET; daddr->sin_port = htons(port); /*RMCP_PRI_RMCP_PORT 0x26f = 623.*/ if (StrIsIp(node)) { /* the node string is an IP address */ uchar in_ip[4]; atoip(in_ip,node); memcpy(&daddr->sin_addr.s_addr,in_ip,4); if ((hptr = xgethostbyname(node)) == NULL) /*gethost error*/ strncpy(gnodename,node,SZGNODE); /*but not fatal*/ else strncpy(gnodename,hptr->h_name,SZGNODE); } else if ((hptr = xgethostbyname(node)) == NULL) { if (foutput) { #ifdef WIN32 fprintf(fperr,"lan, gethostbyname(%s): errno=%d\n", node,get_errno()); #elif SOLARIS fprintf(fperr,"lan, gethostbyname(%s): errno=%d\n", node,get_errno()); #elif defined(HPUX) /*added by ugene */ fprintf(fperr,"lan, gethostbyname(%s): errno=%d\n", node,errno); #else fprintf(fperr,"lan, gethostbyname(%s): %s\n", node,hstrerror(errno)); #endif } close_sockfd(_sockfd); return(LAN_ERR_HOSTNAME); } else { /*gethostbyname(name) succeeded*/ daddr->sin_addr = *((struct in_addr *)hptr->h_addr); strncpy(gnodename,hptr->h_name,SZGNODE); } *daddr_len = sizeof(SOCKADDR_T); #endif *sfd = _sockfd; return(rv); } static void sig_timeout(int sig) { #ifndef WIN32 alarm(0); signal(SIGALRM,SIG_DFL); #endif fprintf(fpdbg,"ipmilan_cmd timeout, after %s\n",conn_state_str[pconn->connect_state]); _exit(LAN_ERR_TIMEOUT); /*timeout signal*/ } static void sig_abort(int sig) { static int sig_aborting = 0; int rv; if (sig_aborting == 0) { sig_aborting = 1; if (pconn->sockfd != 0) { /* socket is open */ if (pconn->session_id != 0) { /* session is open */ // cmd_rs = buf_rs; rv = ipmilan_close_session(pconn->sockfd, (struct sockaddr *)&_destaddr, _destaddr_len, ipmi_hdr.sess_id); } close_sockfd(pconn->sockfd); } signal(SIGINT,SIG_DFL); fprintf(fpdbg,"ipmilan_cmd interrupt, after %s\n", conn_state_str[pconn->connect_state]); _exit(LAN_ERR_ABORT); /*abort signal*/ } /*endif*/ } /*end sig_abort*/ int fd_wait(SockType fd, int nsec, int usec) { fd_set readfds; struct timeval tv; int rv; FD_ZERO(&readfds); FD_SET(fd, &readfds); tv.tv_sec = nsec; tv.tv_usec = usec; rv = select((int)(fd+1), &readfds, NULL, NULL, &tv); if (rv <= 0 || !FD_ISSET(fd,&readfds)) return(-1); else return(0); } #ifndef WIN32 /* LINUX, Solaris, BSD */ /* do_sleep() is currently unused. */ /* signal handlers + sleep(3) is a bad idea */ int do_sleep(unsigned int sleep_len) { struct timeval tv; if (sleep_len == 0) return 0; tv.tv_sec = sleep_len; tv.tv_usec = 0; if (select(1, NULL, NULL, NULL, &tv) < 0) { if (errno != EINTR) return(errno); } return 0; } #endif static void h2net(uint h, uchar *net, int n) { int i = 0; net[i++] = h & 0xff; net[i++] = (h >> 8) & 0xff; if (n == 2) return; net[i++] = (h >> 16) & 0xff; net[i++] = (h >> 24) & 0xff; return; } static void net2h(uint32 *h, uchar *net, int n) { uint32 v; v = (net[1] << 8) | net[0]; if (n == 2) { *h = v; return; } v |= (uint32)(net[3] << 24) | (net[2] << 16); *h = v; return; } /* * _ipmilan_cmd * local routine to send & receive each command. * called by global ipmicmd_lan() */ int _ipmilan_cmd(SockType sockfd, struct sockaddr *hostaddr, int hostaddr_len, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *sdata, int slen, uchar *rdata, int *rlen, int fdebugcmd) { uchar cmd_rq[RQ_LEN_MAX+SZ_CMD_HDR]; uchar cmd_rs[RS_LEN_MAX+SZ_CMD_HDR+1]; int rv = 0; int rs_len; int clen; uchar cc = 0; #ifndef TEST_LAN fdebuglan = fdebugcmd; #endif if (sockfd == 0 || hostaddr == NULL || sdata == NULL || rdata == NULL) return(LAN_ERR_INVPARAM);; if (fdebuglan > 2) dbglog("_ipmilan_cmd(%02x,%02x,%02x,%02x,%02x)\n", cmd,netfn,lun,sa,bus); clen = SZ_CMD_HDR; cmd_rq[0] = cmd; cmd_rq[1] = (netfn << 2) + (lun & 0x03); cmd_rq[2] = sa; cmd_rq[3] = bus; memcpy(&cmd_rq[clen],sdata,slen); rs_len = sizeof(cmd_rs); memset(cmd_rs, 0, rs_len); rv = _send_lan_cmd(sockfd, cmd_rq, slen+clen, cmd_rs, &rs_len, hostaddr, hostaddr_len); if (rv == 0 && rs_len == 0) cc = 0; else cc = cmd_rs[0]; if (fdebugcmd) fprintf(fpdbg,"_ipmilan_cmd[%02x]: rv = %d, cc=%x rs_len=%d\n", cmd_rq[0],rv,cc,rs_len); if (rv == 0 && cc != 0) { /* completion code error */ if (fdebugcmd) { dump_buf("cmd_rq",cmd_rq,slen+clen,0); dump_buf("cmd_rs",cmd_rs,rs_len,0); } } if (rv == 0) { if (rs_len < 0) rs_len = 0; if (*rlen <= 0) *rlen = 1; /*failsafe*/ if (rs_len > 0) { if (rs_len > *rlen) rs_len = *rlen; memcpy(rdata,&cmd_rs[0],rs_len); } else { /*(rs_len == 0)*/ rv = LAN_ERR_TOO_SHORT; /*no completion code returned*/ } } else { rdata[0] = cc; if (rs_len < 1) rs_len = 1; } *rlen = rs_len; return (rv); } /*end _ipmilan_cmd()*/ static void hash(uchar *pwd, uchar *id, uchar *chaldata, int chlen, uint32 seq, uchar *mda, uchar md) { uchar pbuf[80]; /* 16 + 4 + 16 + 4 + 16 = 56 */ int blen, n, i; blen = 0; n = 16; memcpy(&pbuf[blen], pwd,n); /* password */ blen += n; n = 4; memcpy(&pbuf[blen],id,n); /* session id */ blen += n; memcpy(&pbuf[blen],chaldata,chlen); /* ipmi msg data, incl challenge */ blen += chlen; n = 4; h2net(seq,&pbuf[blen],n); /* in_seq num */ blen += n; n = 16; memcpy(&pbuf[blen],pwd,n); /* password */ blen += n; if (md == IPMI_SESSION_AUTHTYPE_MD2) i = 2; else i = 5; #ifdef TEST_AUTH if (fdebuglan) { fprintf(fpdbg,"hash: calling md%d_sum with seq %u\n",i,seq); dump_buf("pbuf",pbuf,blen,0); } #endif #ifdef MD2OK if (md == IPMI_SESSION_AUTHTYPE_MD2) md2_sum(pbuf,blen,mda); else /* assume md5 */ #endif md5_sum(pbuf,blen,mda); #ifdef TEST_AUTH if (fdebuglan) { fprintf(fpdbg,"Hashed MD%d AuthCode: \n",i); dump_buf("AuthCode",mda,16,0); } #endif } /* end hash() */ static void hash_special(uchar *pwd, uchar *chaldata, uchar *mda) { uchar md_pwd[16]; uchar challenge[16]; int i; /* Only used by SuperMidro, must be MD5 auth_type */ memset(md_pwd, 0, 16); md5_sum(pwd,16,md_pwd); memset(challenge, 0, 16); for (i = 0; i < 16; i++) challenge[i] = chaldata[i] ^ md_pwd[i]; memset(mda, 0, 16); md5_sum(challenge,16,mda); } static int ipmilan_sendto(SockType s, const void *msg, size_t len, int flags, const struct sockaddr *to, int tolen) { int fusepad = 0; int n; if (fdebuglan > 2) { dbg_dump("ipmilan_sendto",(uchar *)msg,(int)len,0); } /* Check whether we need a pad byte */ /* Note from Table 12-8, RMCP Packet for IPMI via Ethernet footnote. */ if (len == 56 || len == 84 || len == 112 || len == 128 || len == 156) { /* include pad byte at end, require input buffer to have one extra */ fusepad = 1; len += 1; } n = (int)sendto(s,msg,len,flags,to,(socklen_t)tolen); if (fusepad && (n > 0)) n--; return(n); } static int ipmilan_recvfrom(SockType s, void *buf, size_t len, int flags, struct sockaddr *from, int *fromlen) { int rv; rv = (int)recvfrom(s,buf,len,flags,from,(socklen_t *)fromlen); #ifdef OLD /* Sometimes the OS sends an ECONNREFUSED error, but * retrying will catch the BMC's reply packet. */ if (rv < 0) { int err; err = get_LastError(); if (err == econnrefused) { if (fdebuglan) fprintf(fpdbg,"ipmilan_recvfrom rv=%d econnrefused, retry\n",rv); rv = recvfrom(s,buf,len,flags,from,(socklen_t *)fromlen); } } #endif return(rv); } static int ipmilan_poke1(SockType sfd, struct sockaddr *destaddr, int destlen) { int rv; uchar asfpkt[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x20, 0x18, 0xc8, 0xc2, 0x01, 0x01, 0x3c }; if (fdebuglan) fprintf(fpdbg,"sending ipmilan poke1\n"); rv = ipmilan_sendto(sfd, asfpkt, 16, 0, destaddr, destlen); os_usleep(0,100); return rv; } static int ipmilan_poke2(SockType sfd, struct sockaddr *destaddr, int destlen) { int rv; uchar asfpkt[16] = "poke2"; /*any junk*/ if (fdebuglan) fprintf(fpdbg,"sending ipmilan poke2\n"); rv = ipmilan_sendto(sfd, asfpkt, 10, 0, destaddr, destlen); os_usleep(0,100); return rv; } static void do_hash(uchar *password, uchar *sessid, uchar *pdata, int sdata, uint32 seq_num, uchar auth_type, uchar *auth_out) { /* finish header with auth_code */ if (auth_type != IPMI_SESSION_AUTHTYPE_NONE) { /*fdoauth==1*/ if (auth_type == IPMI_SESSION_AUTHTYPE_MD5) hash(password, sessid, pdata, sdata, seq_num, auth_out,IPMI_SESSION_AUTHTYPE_MD5); #ifdef MD2OK else if (auth_type == IPMI_SESSION_AUTHTYPE_MD2) hash(password, sessid, pdata, sdata, seq_num, auth_out,IPMI_SESSION_AUTHTYPE_MD2); #endif else /* IPMI_SESSION_AUTHTYPE_PASSWORD */ memcpy(auth_out,password,16); } } static uint32 inc_seq_num(uint32 seq) { seq++; if (seq == 0) seq = 1; return(seq); } static int inc_sol_seq(int seq) { seq++; if (seq > 0x0f) seq = 1; /*limit to 4 bits*/ return(seq); } void ipmi_lan_set_timeout(int ipmito, int tries, int pingto) { ipmi_timeout = ipmito; /*default 2*/ ipmi_try = tries; /*default 4*/ ping_timeout = pingto; /*default 1*/ } /* * _send_lan_cmd * Internal routine called by local _ipmilan_cmd() and by * ipmilan_open_session(). * Writes the data to the lan socket in IPMI LAN format. * Authentication, sequence numbers, checksums are handled here. * * Input Parameters: * s = socket descriptor for this session * pcmd = buffer for the command and data * Arbitrary pcmd format: * cmd[0] = IPMI command * cmd[1] = NETFN/LUN byte * cmd[2] = Slave Address (usu 0x20) * cmd[3] = Bus (usu 0x00) * cmd[4-N] = command data * scmd = size of command buffer (3+sdata) * presp = pointer to existing response buffer * sresp = On input, size of response buffer, * On output, length of response data. * to = sockaddr structure for to/destination * tolen = length of to sockaddr */ static int _send_lan_cmd(SockType s, uchar *pcmd, int scmd, uchar *presp, int *sresp, struct sockaddr *to, int tolen) { uchar cbuf[SEND_BUF_SZ]; uchar rbuf[RECV_BUF_SZ]; // uint32 out_seq = 0; /* outbound */ int clen, rlen, hlen, msglen; int flags; int sz, n, i, j; int cs1, cs2, cs3 = 0, cs4 = 0; uchar *pdata; int sdata; IPMI_HDR *phdr; uchar *psessid; uchar iauth[16]; int fdoauth = 1; uint32 sess_id_tmp; int rv = 0; int itry; uchar fsentok; /* set up LAN req hdr */ phdr = &ipmi_hdr; hlen = RQ_HDR_LEN; /* phdr->bmc_addr set in open_session */ phdr->target_addr = pcmd[2]; phdr->target_chan = pcmd[3]; phdr->target_lun = (pcmd[1] & 0x03); phdr->target_netfn = (pcmd[1] >> 2); phdr->target_cmd = pcmd[0]; if (phdr->seq_num != 0) pconn->finsession = 1; if ( ((phdr->target_cmd == CMD_ACTIVATE_SESSION) || (phdr->target_cmd == CMD_SET_SESSION_PRIV)) && (phdr->target_netfn == NETFN_APP) ) { pconn->finsession = 1; /*so do seq_num*/ fdoauth = 1; /*use msg auth*/ } if (phdr->auth_type == IPMI_SESSION_AUTHTYPE_NONE) fdoauth = 0; else if (pconn->finsession && (pconn->fMsgAuth == 0)) { /* Forcing the type may be necessary with IBM eServer 360S. */ if (fauth_type_set) fdoauth = 1; /*user set it, so try anyway*/ else fdoauth = 0; /*auth not supported*/ } if (fdoauth == 0) hlen = RQ_HDR_LEN - 16; /* copy command */ if (scmd < SZ_CMD_HDR) return(LAN_ERR_INVPARAM); sdata = scmd - SZ_CMD_HDR; /* scmd = 4 + datalen */ msglen = 7 + sdata; if (fdebuglan > 2) { dbglog("_send_lan_cmd: cmd=%02x, hlen=%d, msglen=%02x, authtype=%02x\n", pcmd[0], hlen, msglen, phdr->auth_type); } clen = hlen + msglen; if (clen > sizeof(cbuf)) { fprintf(fpdbg,"message size %d > buffer size %lu\n",clen,sizeof(cbuf)); return(LAN_ERR_TOO_SHORT); } if ((phdr->target_cmd == SOL_DATA) && (phdr->target_netfn == NETFN_SOL) ) /*SOL 1.5 data packet*/ { hlen = SOL_HDR_LEN; /*RMCP header + 26 */ if (fdoauth == 0) hlen = SOL_HDR_LEN - 16; msglen = sdata; memcpy(&cbuf[0], phdr, 4); /* copy RMCP header to buffer */ pdata = &cbuf[4]; pdata[0] = phdr->auth_type; memcpy(&pdata[1],&phdr->seq_num,4); sess_id_tmp = phdr->sess_id | SOL_MSG; memcpy(&pdata[5],&sess_id_tmp,4); if (fdebuglan > 2) dbglog("auth_type=%x/%x fdoauth=%d hlen=%d seq_num=%x\n", /*SOL*/ phdr->auth_type,lanp.auth_type,fdoauth,hlen,phdr->seq_num); if (fdoauth) { psessid = (uchar *)&sess_id_tmp; do_hash(phdr->password, psessid, &cbuf[hlen],msglen, phdr->seq_num, phdr->auth_type, iauth); /* copy hashed authcode to header */ memcpy(&pdata[9],iauth,16); } // pdata[hlen-1] = msglen; pdata = &cbuf[hlen]; memcpy(pdata,&pcmd[SZ_CMD_HDR],msglen); /*copy the data*/ clen = hlen + msglen; if (fdebuglan > 2) dbg_dump("sol data, before",pdata,sdata,1); /*SOL TEST*/ } else { /*not SOL packet, normal IPMI packet*/ pdata = &cbuf[hlen]; j = cs1 = 0; if ((phdr->target_addr == phdr->bmc_addr) || !bridgePossible || (phdr->target_addr == SWID_REMOTE) || (phdr->target_addr == SWID_SMSOS)) { phdr->bridge_level = 0; msglen = sdata + 7; clen = hlen + msglen; } else { phdr->bridge_level = 1; if (phdr->transit_addr != 0 && phdr->transit_addr != phdr->bmc_addr) { msglen = sdata + 15 + 8; phdr->bridge_level++; } else { msglen = sdata + 15; } if (fdebuglan > 2) { dbglog("bridge_level=%d cmd=%02x target=%02x transit=%02x\n", phdr->bridge_level, phdr->target_cmd, phdr->target_addr, phdr->transit_addr); dbglog("bridge target_ch=%x transit_ch=%x\n", phdr->target_chan, phdr->transit_chan); } clen = hlen + msglen; pdata[j++] = bmc_sa; /*[0]=sa */ pdata[j++] = (NETFN_APP << 2); /*[1]=netfn/lun*/ pdata[j] = cksum(&pdata[cs1],j-cs1); /*[2]=cksum1*/ j++; cs3 = j; /*start for cksum3*/ pdata[j++] = phdr->swid; /*[3]=swid, usu SWID_REMOTE */ pdata[j++] = (phdr->swseq << 2); /*[4]=swseq/lun*/ pdata[j++] = CMD_SEND_MESSAGE; /*[5]=cmd*/ if (phdr->bridge_level == 1) { pdata[j++] = (0x40|phdr->target_chan); /*channel*/ } else { /*double bridge*/ pdata[j++] = (0x40|phdr->transit_chan); /*channel*/ cs1 = j; pdata[j++] = phdr->transit_addr; /*[0]=sa */ pdata[j++] = (NETFN_APP << 2); /*[1]=netfn/lun*/ pdata[j] = cksum(&pdata[cs1],j-cs1); /*[2]=cksum1*/ j++; cs4 = j; /*start for cksum4*/ pdata[j++] = bmc_sa; /*[3]=swid */ pdata[j++] = (phdr->swseq << 2); /*[4]=swseq/lun*/ pdata[j++] = CMD_SEND_MESSAGE; /*[5]=cmd*/ pdata[j++] = (0x40|phdr->target_chan); /*channel*/ } } /*end-else bridged*/ /* normal IPMI LAN commmand packet */ cs1 = j; /*start for cksum1*/ pdata[j++] = pcmd[2]; /*[0]=sa (phdr->target_addr)*/ pdata[j++] = pcmd[1]; /*[1]=netfn/lun*/ pdata[j] = cksum(&pdata[cs1],j-cs1); /*[2]=cksum1*/ j++; cs2 = j; /*start for cksum2*/ if (phdr->bridge_level == 0) pdata[j++] = phdr->swid; /*[3]=swid*/ else /*bridged message*/ pdata[j++] = phdr->bmc_addr; /*[3]=swid*/ pdata[j++] = (phdr->swseq << 2) + phdr->swlun; /*[4]=swseq/lun*/ pdata[j++] = phdr->target_cmd; /*[5]=cmd (pcmd[0])*/ if (sdata > 0) { memcpy(&pdata[j],&pcmd[SZ_CMD_HDR],sdata); /*[6]=data*/ j += sdata; } pdata[j] = cksum(&pdata[cs2],j-cs2); /*cksum2*/ j++; if (phdr->bridge_level > 0) { if (phdr->bridge_level > 1) { pdata[j] = cksum(&pdata[cs4],j-cs4); /*cksum4*/ j++; } pdata[j] = cksum(&pdata[cs3],j-cs3); /*cksum3*/ j++; } if (fdebuglan && (msglen != j)) fprintf(fpdbg,"warning: msglen(%d)!=j(%d), hlen=%d clen=%d\n", msglen,j,hlen,clen); if (fdoauth) { psessid = (uchar *)&phdr->sess_id; do_hash(phdr->password, psessid, &cbuf[hlen],msglen, phdr->seq_num, phdr->auth_type, iauth); /* copy hashed authcode to header */ memcpy(phdr->auth_code,iauth,16); } memcpy(&cbuf[0], phdr, hlen); /* copy header to buffer */ } /*end-else normal IPMI */ if (fdoauth == 0 && phdr->auth_type != IPMI_SESSION_AUTHTYPE_NONE) { /* force the packet auth type to NONE (0) */ IPMI_HDR *pchdr; pchdr = (IPMI_HDR *)&cbuf[0]; pchdr->auth_type = IPMI_SESSION_AUTHTYPE_NONE; // memset(phdr->auth_code,0,16); } cbuf[hlen-1] = (uchar)msglen; /* IPMI Message Length = 7 + data */ if (fdebuglan > 2) { if ((phdr->target_cmd == SOL_DATA) && (phdr->target_netfn == NETFN_SOL) ) { // phdr->sess_id = sess_id_sav; /*restore sess_id*/ if (fdebuglan) fprintf(fpdbg,"sending lan sol data (len=%d)\n",clen); } else { if (fdebuglan) fprintf(fpdbg,"sending ipmi lan data (len=%d)\n",clen); } } flags = 0; rlen = 0; if ((fdebuglan > 2) && (phdr->target_cmd == CMD_GET_CHAN_AUTH_CAP) && (phdr->target_netfn == NETFN_APP) ) dbg_dump("get_chan_auth_cap command",cbuf,clen,1); memset(rbuf,0,sizeof(rbuf)); fsentok = 0; for (itry = 0; (itry < ipmi_try) && (rlen == 0); itry++) { if (fdebuglan > 2) dbglog("ipmilan_cmd(seq=%x) fsentok=%d itry=%d\n", phdr->seq_num, fsentok, itry); if (fsentok == 0) { if (fdebuglan) fprintf(fpdbg,"ipmilan_sendto(seq=%x,clen=%d)\n", phdr->seq_num, clen); sz = ipmilan_sendto(s,cbuf,clen,flags,to,tolen); if (sz < 1) { lasterr = get_LastError(); if (fdebuglan) show_LastError("ipmilan_sendto",lasterr); rv = LAN_ERR_SEND_FAIL; os_usleep(0,5000); continue; /* retry */ } fsentok = 1; /*sent ok, no need to resend*/ } /* receive the response */ rv = fd_wait(s, ipmi_timeout,0); if (rv != 0) { if (fdebuglan) fprintf(fpdbg,"ipmilan_cmd timeout, after request, seq=%x itry=%d\n", phdr->seq_num, itry); rv = LAN_ERR_RECV_FAIL; if (fdopoke2) ipmilan_poke2(s, to, tolen); os_usleep(0,5000); continue; /* retry */ } flags = RECV_MSG_FLAGS; rlen = ipmilan_recvfrom(s,rbuf,sizeof(rbuf),flags,to,&tolen); if (rlen < 0) { lasterr = get_LastError(); if (fdebuglan) { fprintf(fpdbg,"ipmilan_recvfrom rlen=%d, err=%d iseq=%x itry=%d\n", rlen,lasterr,phdr->iseq_num,itry); show_LastError("ipmilan_recvfrom",lasterr); } rv = rlen; /* -3 = LAN_ERR_RECV_FAIL */ rlen = 0; *sresp = rlen; /* Sometimes the OS sends an ECONNREFUSED error, but * retrying will catch the BMC's reply packet. */ if (lasterr == econnrefused) continue; /*try again*/ else if (lasterr == econnreset) continue; /*try again*/ else break; /* goto EXIT; */ } else { /* successful receive */ net2h(&phdr->iseq_num,&rbuf[5],4); /*incoming seq_num from hdr*/ if (fdebuglan) { fprintf(fpdbg,"ipmilan_recvfrom rlen=%d, iseq=%x\n", rlen,phdr->iseq_num); if (fdebuglan > 2) dbg_dump("ipmilan_recvfrom", rbuf,rlen,1); } /* incoming auth_code may differ from request auth code, (Dell 1855)*/ if (rbuf[4] == IPMI_SESSION_AUTHTYPE_NONE) { /* if AUTH_NONE */ phdr->auth_type = IPMI_SESSION_AUTHTYPE_NONE; hlen = RQ_HDR_LEN - 16; /*RMCP header + 10*/ } else { hlen = RQ_HDR_LEN; /*RMCP header + 26 */ // memcpy(phdr->iauth_code,&rbuf[13],16); /*iauthcode*/ } i = hlen + 6; if (rlen <= i) rv = LAN_ERR_TOO_SHORT; else { /* successful */ n = rlen - i - 1; if (bridgePossible && (phdr->target_addr != bmc_sa)) { if (phdr->bridge_level && ((rbuf[hlen+1] >> 2) == (NETFN_APP + 1)) && /*0x07*/ rbuf[hlen+5] == CMD_SEND_MESSAGE) /*0x34*/ { phdr->bridge_level--; if (n <= 1) { /* no data, wait for next */ if (fdebuglan) fprintf(fpdbg,"bridged response empty, cc=%x\n",rbuf[i]); if (rbuf[i] == 0) { /* if sendmsg cc==0, recv again*/ rlen = 0; continue; } /*else done*/ } else { /* has data, copy it*/ //if (fdebuglan) fprintf(fpdbg,"bridged response, n=%d\n",n); // memmove(&rbuf[i-7],&rbuf[i],n); phdr->swseq = rbuf[i-3] >> 2; /*needed?*/ rbuf[i-8] -= 8; n -= 8; i -= 7; if (fdebuglan) dump_buf("bridged response",&rbuf[i],n,1); continue; /*recv again*/ } } } /*endif bridge*/ if (n > *sresp) n = *sresp; memcpy(presp,&rbuf[i],n); *sresp = n; rv = 0; } } /*end else success*/ } /*end for loop*/ // EXIT: #ifdef NOT /* do not increment sequence numbers for SEND_MESSAGE command */ if ((phdr->target_cmd == IPMB_SEND_MESSAGE) && (phdr->target_netfn == NETFN_APP) ) pconn->finsession = 0; #endif if (pconn->finsession) { /* increment seqnum - even if error */ phdr->seq_num = inc_seq_num( phdr->seq_num ); if (rlen > 0) pconn->in_seq = phdr->iseq_num; else pconn->in_seq = inc_seq_num(pconn->in_seq); phdr->swseq = (uchar)inc_seq_num(phdr->swseq); } return(rv); } /*end _send_lan_cmd*/ static char *auth_type_str(int authcode) { char *pstr; switch(authcode) { case IPMI_SESSION_AUTHTYPE_MD5: pstr = "MD5"; break; case IPMI_SESSION_AUTHTYPE_MD2: pstr = "MD2"; break; case IPMI_SESSION_AUTHTYPE_PASSWORD: pstr = "PSWD"; break; case IPMI_SESSION_AUTHTYPE_OEM: pstr = "OEM"; break; case IPMI_SESSION_AUTHTYPE_NONE: pstr = "NONE"; break; default: pstr = "Init"; break; /* AUTHTYPE_INIT, etc. */ } return (pstr); } #ifdef NOT_USED static uchar auth_type_mask(int authcode, uchar allowed) { uchar mask; switch(authcode) { case IPMI_SESSION_AUTHTYPE_MD5: mask = IPMI_MASK_AUTHTYPE_MD5; break; case IPMI_SESSION_AUTHTYPE_MD2: mask = IPMI_MASK_AUTHTYPE_MD2; break; case IPMI_SESSION_AUTHTYPE_PASSWORD: mask = IPMI_MASK_AUTHTYPE_PASSWORD; break; case IPMI_SESSION_AUTHTYPE_OEM: mask = IPMI_MASK_AUTHTYPE_OEM; break; case IPMI_SESSION_AUTHTYPE_NONE: mask = IPMI_MASK_AUTHTYPE_NONE; break; default: /* AUTHTYPE_INIT, etc. */ mask = 0; break; } return (mask); } #endif /* * ipmilan_open_session * Performs the various command/response sequence needed to * initiate an IPMI LAN session. */ static int ipmilan_open_session(SockType sfd, struct sockaddr *destaddr, int destaddr_len, uchar auth_type, char *username, char *authcode, int authcode_len, uchar priv_level, uint32 init_out_seqnum, uint32 *session_seqnum, uint32 *session_id) { int rv = 0; uchar ibuf[RQ_LEN_MAX+3]; uchar rbuf[RS_LEN_MAX+4]; uint32 iseqn; uchar ipasswd[16]; uchar iauthtype; uchar iauthcap, imsgauth; int rlen, ilen; IPMI_HDR *phdr; uchar cc; int busy_tries = 0; if (fdebuglan) fprintf(fpdbg,"ipmilan_open_session(%d,%02x,%s,%02x,%x) called\n", sfd,auth_type,username,priv_level,init_out_seqnum); if (sfd == 0 || destaddr == NULL) return LAN_ERR_INVPARAM; phdr = &ipmi_hdr; /* Initialize ipmi_hdr fields */ memset(phdr,0,sizeof(ipmi_hdr)); phdr->rmcp_ver = 0x06; phdr->rmcp_res = 0x00; phdr->rmcp_seq = 0xFF; phdr->rmcp_type = 0x07; phdr->swid = sms_swid; phdr->swseq = 1; phdr->priv_level = priv_level; /* Get Channel Authentication */ phdr->auth_type = IPMI_SESSION_AUTHTYPE_NONE; /*use none(0) at first*/ ibuf[0] = 0x0e; /*this channel*/ ibuf[1] = phdr->priv_level; rlen = sizeof(rbuf); if (fdebuglan) fprintf(fpdbg,"GetChanAuth(sock %x, level %x) called\n",sfd,ibuf[1]); rv = _ipmilan_cmd(sfd, destaddr, destaddr_len, CMD_GET_CHAN_AUTH_CAP, NETFN_APP,BMC_LUN,bmc_sa, PUBLIC_BUS, ibuf,2, rbuf,&rlen, fdebuglan); if (rv != 0) { /*retry if error*/ rv = _ipmilan_cmd(sfd, destaddr, destaddr_len, CMD_GET_CHAN_AUTH_CAP, NETFN_APP,BMC_LUN,bmc_sa, PUBLIC_BUS, ibuf,2, rbuf,&rlen, fdebuglan); } cc = rbuf[0]; if (fdebuglan) fprintf(fpdbg,"GetChanAuth rv = %d, cc=%x rbuf: %02x %02x %02x " "%02x %02x %02x %02x\n", rv, rbuf[0],rbuf[1],rbuf[2],rbuf[3], rbuf[4],rbuf[5],rbuf[6],rbuf[7]); if (rv != 0 || cc != 0) goto ERREXIT; /* Check Channel Auth params */ if ((rbuf[2] & 0x80) != 0) { /*have IPMI 2.0 extended capab*/ if ( ((rbuf[4]&0x02) != 0) && ((rbuf[4]&0x01) == 0) ) { if (fdebuglan) fprintf(fpdbg,"GetChanAuth reports only v2 capability\n"); rv = LAN_ERR_V2; /*try v2 instead*/ goto ERREXIT; } else { /* Always switch to IPMI LAN 2.0 if detected. */ /* This avoids errors from Dell & Huawei firmware */ if (fdebuglan) fprintf(fpdbg,"GetChanAuth detected v2, so switch to v2\n"); rv = LAN_ERR_V2; /*use v2 instead*/ goto ERREXIT; } } /* Check authentication support */ imsgauth = rbuf[3]; if ((imsgauth & 0x10) == 0) pconn->fMsgAuth = 1; /*per-message auth*/ else if ((imsgauth & 0x08) == 0) pconn->fMsgAuth = 2; /*user-level auth*/ else pconn->fMsgAuth = 0; /*no auth support*/ iauthcap = rbuf[2] & 0x3f; if (fauth_type_set) { iauthtype = (uchar)lanp.auth_type; // set by user auth_type = iauthtype; } else { iauthtype = AUTHTYPE_INIT; /*initial value, not set*/ } if (auth_type != iauthtype) { /* default of MD5 is preferred, but try what BMC allows */ if (iauthcap & IPMI_MASK_AUTHTYPE_MD5) { iauthtype = IPMI_SESSION_AUTHTYPE_MD5; auth_type = iauthtype; #ifdef MD2OK } else if (iauthcap & IPMI_MASK_AUTHTYPE_MD2) { iauthtype = IPMI_SESSION_AUTHTYPE_MD2; auth_type = iauthtype; if (fdebuglan) fprintf(fpdbg,"auth_type set to MD2 (%02x)\n",iauthtype); #endif } else if (iauthcap & IPMI_MASK_AUTHTYPE_PASSWORD) { iauthtype = IPMI_SESSION_AUTHTYPE_PASSWORD; auth_type = iauthtype; if (fdebuglan) fprintf(fpdbg,"auth_type set to Password (%02x)\n",iauthtype); } else { if (fdebuglan) fprintf(fpdbg, "auth_type set to %02x, using None\n",auth_type); iauthtype = IPMI_SESSION_AUTHTYPE_NONE; auth_type = iauthtype; } } if (fdebuglan) fprintf(fpdbg, "auth_type=%02x(%s) allow=%02x iauthtype=%02x msgAuth=%d(%02x)\n", auth_type,auth_type_str(auth_type),iauthcap,iauthtype, pconn->fMsgAuth,imsgauth); /* get session challenge */ phdr->auth_type = IPMI_SESSION_AUTHTYPE_NONE; memset(ibuf,0,17); ibuf[0] = iauthtype; if (username != NULL) strncpy(&ibuf[1],username,16); while (busy_tries < BUSY_MAX) { rlen = sizeof(rbuf); rv = _ipmilan_cmd(sfd, destaddr,destaddr_len, CMD_GET_SESSION_CHALLENGE, NETFN_APP,BMC_LUN,bmc_sa, PUBLIC_BUS, ibuf,17, rbuf,&rlen, fdebuglan); cc = rbuf[0]; if (rv != 0) break; else if (cc == 0xc0) busy_tries++; else break; } if (fdebuglan) { if ((rv == 0) && (cc == 0)) dump_buf("GetSessionChallenge rv=0, rbuf",rbuf,rlen,0); else fprintf(fpdbg,"GetSessionChallenge rv=%d cc=%x rlen=%d tries=%d\n", rv, cc, rlen,busy_tries); } if (rv != 0) goto ERREXIT; else if (cc != 0) { cc_challenge(cc); goto ERREXIT; } /* save challenge response data */ memcpy(&phdr->sess_id, &rbuf[1], 4); memcpy(phdr->challenge, &rbuf[5], 16); /* Save authtype/authcode in ipmi_hdr for later use in _send_lan_cmd. */ phdr->bmc_addr = bmc_sa; phdr->auth_type = iauthtype; if (authcode_len > 16 || authcode_len < 0) authcode_len = 16; memset(&ipasswd,0,16); if (authcode != NULL && authcode_len > 0) memcpy(&ipasswd,(uchar *)authcode,authcode_len); /* AuthCode=passwd */ memcpy(phdr->password,&ipasswd,16); /* save password */ /* ActivateSession request */ ibuf[0] = phdr->auth_type; ibuf[1] = phdr->priv_level; if (vend_id == VENDOR_SUPERMICRO) { /* if supermicro, do special auth logic here */ hash_special(phdr->password, phdr->challenge, ipasswd); memcpy(phdr->password,ipasswd,16); memset(&ibuf[2],0,16); /*zero challenge string here*/ if (fdebuglan) printf("Using supermicro OEM challenge\n"); } else { memcpy(&ibuf[2],phdr->challenge,16); /*copy challenge string to data*/ } phdr->seq_num = 0; iseqn = init_out_seqnum; h2net(iseqn,&ibuf[18],4); /* write iseqn to buffer */ ilen = 22; if (fdebuglan) dump_buf("ActivateSession req",ibuf,ilen,0); rlen = sizeof(rbuf); rv = _ipmilan_cmd(sfd,destaddr,destaddr_len,CMD_ACTIVATE_SESSION, NETFN_APP,BMC_LUN,bmc_sa, PUBLIC_BUS, ibuf, ilen, rbuf, &rlen, fdebuglan); cc = rbuf[0]; if (fdebuglan) { if (rv > 0) fprintf(fpdbg,"ActivateSession rv = 0x%02x\n",rv); /*cc*/ else fprintf(fpdbg,"ActivateSession rv = %d\n",rv); } if (rv != 0) goto ERREXIT; else if (cc != 0) { cc_session(cc); goto ERREXIT; } if (pconn->fMsgAuth == 2) /*user-level auth*/ phdr->auth_type = IPMI_SESSION_AUTHTYPE_NONE; memcpy(&phdr->sess_id,&rbuf[2],4); /* save new session id */ net2h(&iseqn, &rbuf[6],4); /* save returned out_seq_num */ if (iseqn == 0) iseqn = inc_seq_num(iseqn); /* was ++iseqn */ phdr->seq_num = iseqn; /* new session seqn */ if (fdebuglan) fprintf(fpdbg,"sess_id=%x seq_num=%x priv_allow=%x priv_req=%x\n", phdr->sess_id,phdr->seq_num,rbuf[10],phdr->priv_level); /* set session privileges (set_session_privilege_level) */ ibuf[0] = phdr->priv_level; rlen = sizeof(rbuf); rv = _ipmilan_cmd(sfd, destaddr, destaddr_len, CMD_SET_SESSION_PRIV, NETFN_APP,BMC_LUN,bmc_sa, PUBLIC_BUS, ibuf,1, rbuf,&rlen, fdebuglan); cc = rbuf[0]; if (fdebuglan) fprintf(fpdbg,"SetSessionPriv(%x) rv = %d\n",ibuf[0], rv); bridgePossible = 1; *session_id = phdr->sess_id; *session_seqnum = phdr->seq_num; ERREXIT: if (rv == 0 && cc != 0) rv = cc; return(rv); } /*end ipmilan_open_session*/ /* * ipmilan_close_session */ static int ipmilan_close_session(SockType sfd, struct sockaddr *destaddr, int destaddr_len, uint32 session_id) { uchar ibuf[RQ_LEN_MAX+3]; uchar rbuf[RS_LEN_MAX+4]; int rlen; int rv = 0; if (session_id == 0) return(0); /* send close session command */ memcpy(ibuf,&session_id,4); rlen = sizeof(rbuf); bridgePossible = 0; rv = _ipmilan_cmd(sfd, destaddr, destaddr_len, CMD_CLOSE_SESSION, NETFN_APP,BMC_LUN,bmc_sa,PUBLIC_BUS, ibuf,4, rbuf,&rlen, fdebuglan); if (fdebuglan) fprintf(fpdbg,"CloseSession rv = %d, cc = %02x\n", rv, rbuf[0]); if (rbuf[0] != 0) rv = rbuf[0]; /*comp code*/ if (rv == 0) pconn->session_id = 0; ipmi_hdr.seq_num = 0; ipmi_hdr.swseq = 1; ipmi_hdr.iseq_num = 0; ipmi_hdr.sess_id = 0; pconn->finsession = 0; return(rv); } int rmcp_ping(SockType sfd, struct sockaddr *saddr, int saddr_len, int foutput) { /* The ASF spec says to use network byte order */ uchar asf_pkt[40] = {06,0,0xFF,06,0x00,0x00,0x11,0xBE,0x80,0,0,0 }; struct sockaddr from_addr; int from_len; int rv; int iana; /* Send RMCP ASF ping to verify IPMI LAN connection. */ asf_pkt[9] = 1; /*tag*/ rv = ipmilan_sendto(sfd, asf_pkt, 12, 0, saddr, saddr_len); if (foutput) fprintf(fpdbg,"ipmilan ping, sendto len=%d\n",rv); if (rv < 0) return(LAN_ERR_PING); pconn->connect_state = CONN_STATE_PING; /*ping was sent ok*/ from_len = sizeof(struct sockaddr); rv = fd_wait(sfd,ping_timeout,0); if (rv != 0) { fprintf(fpdbg,"ping timeout, after %s\n", conn_state_str[pconn->connect_state]); rv = LAN_ERR_CONNECT; } else { rv = ipmilan_recvfrom(sfd, asf_pkt, sizeof(asf_pkt), 0, &from_addr,&from_len); if (foutput) { fprintf(fpdbg,"ipmilan pong, recvfrom len=%d\n", rv); if (rv > 0) { iana = asf_pkt[15] + (asf_pkt[14] << 8) + (asf_pkt[13] << 16) + (asf_pkt[12] << 24); dump_buf("ping response",asf_pkt, rv,0); printf("ping IANA = %d (%s)\n",iana,get_iana_str(iana)); } } if (rv < 0) return(LAN_ERR_CONNECT); } return(0); } int ping_bmc(char *node, int fdebugcmd) { SOCKADDR_T toaddr; int toaddr_len; SockType sfd; int rv; rv = open_sockfd(node, RMCP_PRI_RMCP_PORT, &sfd, &toaddr, &toaddr_len, fdebugcmd); if (rv != 0) return(rv); rv = rmcp_ping(sfd, (struct sockaddr *)&toaddr,toaddr_len, fdebugcmd); close_sockfd(sfd); return(rv); } static int get_rand(void *data, int len) { int rv = 0; int fd; #if defined(LINUX) fd = open("/dev/urandom", O_RDONLY); if (fd < 0 || len < 0) return errno; rv = read(fd, data, len); close(fd); #else fd = rand(); if (fd == 0) fd = 1; if (len > sizeof(int)) len = sizeof(int); memcpy(data,&fd,len); #endif return rv; } /* * ipmi_open_lan */ int ipmi_open_lan(char *node, int port, char *user, char *pswd, int fdebugcmd) { char *username; uchar priv_level; int rv = -1; #ifndef HAVE_IPV6 char *temp; #endif #ifndef TEST_LAN fdebuglan = fdebugcmd; if (fdebugcmd) fprintf(fpdbg,"ipmi_open_lan: fdebug = %d\n",fdebugcmd); #endif if (fdebugcmd > 2) fdoping = 1; get_mfgid(&vend_id,&prod_id); if (nodeislocal(node)) { fprintf(fpdbg,"ipmi_open_lan: node %s is local!\n",node); rv = LAN_ERR_INVPARAM; goto EXIT; } else { if (fdebugcmd) fprintf(fpdbg,"Opening lan connection to node %s ...\n",node); /* save nodename for sig_abort later */ if (strlen(node) > SZGNODE) { strncpy(nodename, node, SZGNODE); nodename[SZGNODE] = 0; } else strcpy(nodename, node); rv = open_sockfd(node, port, &(pconn->sockfd), &_destaddr, &_destaddr_len, 1); if (fdebugcmd) printf("open_sockfd returned %d, fd=%d\n", rv, pconn->sockfd); if (rv != 0) goto EXIT; #ifdef HAVE_IPV6 strcpy(gnodename,nodename); if (fdebugcmd) fprintf(fpdbg,"Connecting to node %s\n",gnodename); #else #ifdef WIN32 /* check for ws2_32.lib(getnameinfo) resolution */ gnodename[0] = 0; /* int getnameinfo( const struct sockaddr * sa, socklen_t salen, char * host, DWORD hostlen, char * serv, DWORD servlen, int flags); rv = getnameinfo((SOCKADDR *)&_destaddr, _destaddr_len, gnodename,SZGNODE, NULL,0,0); */ #else rv = getnameinfo((struct sockaddr *)&_destaddr, _destaddr_len, gnodename,SZGNODE, NULL,0,0); #endif if (rv != 0) { if (fdebugcmd) fprintf(fpdbg,"ipmi_open_lan: getnameinfo rv = %d\n",rv); gnodename[0] = 0; } temp = inet_ntoa(_destaddr.sin_addr); fprintf(fpdbg,"Connecting to node %s %s\n",gnodename, temp); strncpy(_dest_ip, temp, INET_ADDRSTRLEN); _dest_ip[INET_ADDRSTRLEN] = 0; #endif #ifndef WIN32 /* Linux: Set up signals to handle errors & timeouts. */ signal(SIGINT,sig_abort); signal(SIGALRM,sig_timeout); #endif pconn->connect_state = CONN_STATE_BIND; if (fdoping) { rv = rmcp_ping(pconn->sockfd,(struct sockaddr *)&_destaddr, _destaddr_len, fdebugcmd); if (fdopoke1 && rv != 0) { /* May sometimes need a poke to free up the BMC (cant hurt) */ ipmilan_poke1(pconn->sockfd,(struct sockaddr *)&_destaddr, _destaddr_len); } if (rv != 0) { if (rv == LAN_ERR_CONNECT && frequireping == 0) { /* keep going even if ping/pong failure */ rv = 0; } else { close_sockfd(pconn->sockfd); rv = LAN_ERR_CONNECT; goto EXIT; } } pconn->connect_state = CONN_STATE_PONG; } { auth_type = (uchar)lanp.auth_type; priv_level = (uchar)lanp.priv; username = user; authcode = pswd; authcode_len = (pswd) ? strlen_(authcode) : 0; if ((vend_id == VENDOR_INTEL) || (vend_id == VENDOR_IBM)) pconn->start_out_seq = 1; else { if (fdebugcmd) printf("calling get_rand(%d)\n", pconn->start_out_seq); get_rand(&pconn->start_out_seq,sizeof(pconn->start_out_seq)); } } rv = ipmilan_open_session(pconn->sockfd, (struct sockaddr *)&_destaddr, _destaddr_len, auth_type, username, authcode, authcode_len,priv_level, pconn->start_out_seq, &pconn->in_seq, &pconn->session_id); if (rv == 0) { /* successful (session active) */ pconn->connect_state = CONN_STATE_ACTIVE; /*set connection state to active*/ } else { /* open_session rv != 0 */ if ((gshutdown==0) || fdebugcmd) { if (rv < 0) fprintf(fpdbg,"ipmilan_open_session error, rv = %d\n",rv); else fprintf(fpdbg,"ipmilan_open_session error, rv = 0x%x\n",rv); } close_sockfd(pconn->sockfd); } } EXIT: if (rv != 0) { // if ((gshutdown==0) || fdebugcmd) printf("ipmilan %s\n",decode_rv(rv)); if (rv == -1 && lasterr != 0) show_LastError("ipmilan",lasterr); } return(rv); } int ipmi_flush_lan(char *node) { int rv = 0; /* could match node via pconn = find_conn(node); */ if (!nodeislocal(node)) { /* ipmilan, need to close & cleanup */ if (pconn->sockfd != 0) close_sockfd(pconn->sockfd); } else { /* kcs cleanup */ #ifndef WIN32 alarm(0); signal(SIGALRM,SIG_DFL); #endif } /* endif */ pconn->connect_state = CONN_STATE_INIT; pconn->finsession = 0; pconn->session_id = 0; pconn->sockfd = 0; pconn->in_seq = 1; pconn->start_out_seq = 1; pconn->fMsgAuth = 1; /*1=PerMsgAuth*/ pconn->auth_type = AUTHTYPE_INIT; return (rv); } int ipmi_close_lan(char *node) { int rv = 0; /* could match node via pconn = find_conn(node); */ if (fdebuglan) fprintf(fpdbg,"ipmi_close_lan(%s) entry, sockfd=%d\n", node,pconn->sockfd); if (!nodeislocal(node)) { /* ipmilan, need to close & cleanup */ if (pconn->sockfd != 0) { /* socket is open */ if (gshutdown) pconn->session_id = 0; if (pconn->session_id != 0) { /* session is open */ // cmd_rs = buf_rs; rv = ipmilan_close_session(pconn->sockfd, (struct sockaddr *)&_destaddr, _destaddr_len, ipmi_hdr.sess_id); /* flush session_id even if error, let it time out */ pconn->session_id = 0; } close_sockfd(pconn->sockfd); pconn->sockfd = 0; } pconn->connect_state = CONN_STATE_INIT; pconn->finsession = 0; } else { /* kcs cleanup */ #ifndef WIN32 alarm(0); signal(SIGALRM,SIG_DFL); #endif } /* endif */ if (fdebuglan) fprintf(fpdbg,"ipmi_close_lan(%s) rv=%d sockfd=%d\n", node,rv,pconn->sockfd); return (rv); } /* * ipmicmd_lan * This is called by ipmi_cmd_lan, all commands come through here. */ int ipmicmd_lan(char *node, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { uchar rq_data[RQ_LEN_MAX+3]; uchar cmd_rs[RS_LEN_MAX+4]; uchar cc = 0; int rlen; int rv = -1; #ifndef TEST_LAN fdebuglan = fdebugcmd; #endif /* check sdata/sresp against MAX_ */ if (sdata > RQ_LEN_MAX) { if (fdebugcmd) printf("cmd %x sdata(%d) > RQ_LEN_MAX(%d)\n", cmd,sdata,RQ_LEN_MAX); return(LAN_ERR_BADLENGTH); } if (*sresp > RS_LEN_MAX) { if (fdebugcmd) printf("cmd %x sresp(%d) > RS_LEN_MAX(%d), use less\n", cmd,*sresp,RS_LEN_MAX); /* This is ok, just receive up to the max. */ *sresp = RS_LEN_MAX; } if (pdata == NULL) { pdata = rq_data; sdata = 0; } rlen = *sresp; if (nodeislocal(node)) { /*local, use kcs*/ fprintf(fpdbg,"ipmicmd_lan: node %s is local", node); goto EXIT; } else { /* ipmilan */ if (pconn->sockfd == 0) { /* closed, do re-open */ if (fdebugcmd) fprintf(fpdbg,"sockfd==0, node %s needs re-open\n",node); rv = ipmi_open_lan(lanp.node, lanp.port, lanp.user, lanp.pswd, fdebugcmd); if (rv != 0) goto EXIT; } if (fdebugcmd) { fprintf(fpdbg,"lan_cmd(seq=%x) %02x %02x %02x %02x, (dlen=%d): ", ipmi_hdr.seq_num, cmd,netfn,lun,sa,sdata); dump_buf("cmd data",pdata,sdata,0); } if (fdebuglan > 2) dbglog("calling _ipmilan_cmd(%02x,%02x)\n",cmd,netfn); rlen = sizeof(cmd_rs); rv = _ipmilan_cmd(pconn->sockfd, (struct sockaddr *)&_destaddr, _destaddr_len, cmd, netfn, lun, sa, bus, pdata, sdata, cmd_rs, &rlen, fdebugcmd); } cc = cmd_rs[0]; if (rv == 0 && cc == 0) { /* success */ if (fdebugcmd) { fprintf(fpdbg,"lan_rsp rv=0 cc=0 (rlen=%d): ",rlen); dump_buf("cmd rsp",cmd_rs,rlen,0); } rlen--; if (rlen > *sresp) { /*received data > receive buffer*/ if (fdebugcmd) printf("rlen(%d) > sresp(%d), truncated\n",rlen,*sresp); rlen = *sresp; } memcpy(presp,&cmd_rs[1],rlen); *sresp = rlen; } else { /* error */ if (fdebugcmd) fprintf(fpdbg,"ipmicmd_lan: cmd=%02x rv=%d, cc=%02x, rlen=%d\n", cmd,rv,cc,rlen); presp[0] = 0; /*memset(presp,0,*sresp);*/ *sresp = 0; } EXIT: *pcc = cc; return(rv); } /*end ipmicmd_lan()*/ /* * ipmi_cmd_lan * This is the entry point, called from ipmicmd.c */ int ipmi_cmd_lan(char *node, ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rc, i; uchar mycmd; for (i = 0; i < NCMDS; i++) { if (ipmi_cmds[i].cmdtyp == cmd) break; } if (i >= NCMDS) { fprintf(fperr, "ipmi_cmd_lan: Unknown command %x\n",cmd); return(-1); } if (cmd >= CMDMASK) mycmd = (uchar)(cmd & CMDMASK); /* unmask it */ else mycmd = (uchar)cmd; if (fdebuglan > 2) dbglog("ipmi_cmd_lan: cmd=%04x, mycmd=%02x\n",cmd,mycmd); rc = ipmicmd_lan(node,mycmd,ipmi_cmds[i].netfn,ipmi_cmds[i].lun, ipmi_cmds[i].sa, ipmi_cmds[i].bus, pdata,sdata,presp,sresp,pcc,fdebugcmd); return (rc); } int ipmi_cmdraw_lan(char *node, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rc; if (fdebuglan > 2) dbglog("ipmi_cmdraw_lan: cmd=%02x, netfn=%02x\n",cmd,netfn); /* bus is not used for lan */ rc = ipmicmd_lan(node, cmd, netfn, lun, sa, bus, pdata,sdata,presp,sresp,pcc,fdebugcmd); return (rc); } SockType lan_get_fd(void) { return(pconn->sockfd); } /* static SOL v1.5 encryption routines */ static void sol15_cipherinit( uchar SeedCount, char *password, uint32 out_seq) { uchar temp[ 40 ]; /* 16 + 4 + 8 + 4 = 32 bytes */ int i; i = SeedCount & 0x0f; srand((unsigned int)time(NULL)); g_Seed[i] = (int32_t)rand(); if (password == NULL) memset(&temp[0], 0, 16); else memcpy(&temp[0], password,16); /*16-byte password*/ h2net(g_Seed[i],&temp[16],4); /*4-byte seed */ memset(&temp[20], 0, 8 ); /*8-byte pad*/ h2net(out_seq,&temp[28],4); /*4-byte seq num */ md5_sum(temp,32, g_Cipher[i]); } #ifdef NOT_USED static void sol15_encrypt( uchar *dst, uchar *src, int len, uchar SeedCount ) { uchar cipher; unsigned int val; int i; SeedCount &= 0x0f; if ( sol_Encryption ) { for (i = 0; i < len; i++, dst++, src++) { cipher = g_Cipher[ SeedCount ][ (i & 0x0f) ]; val = (*src) << (cipher & 0x07); *dst = (uchar)((val | (val >> 8)) ^ cipher); } } else { memcpy( dst, src, len ); } } static void sol15_decrypt( uchar *dst, uchar *src, int len, uchar SeedCount ) { uchar cipher; unsigned int val; int i; SeedCount &= 0x0f; if ( sol_Encryption ) { for (i = 0; i < len; i++, dst++, src++) { cipher = g_Cipher[ SeedCount ][ (i & 0x0f) ]; val = ((*src) ^ cipher) << 8; val >>= (cipher & 0x07); *dst = (uchar)((val >> 8) | val); } } else { memcpy( dst, src, len ); } } #endif /* * lan_get_sol_data * Called before ACTIVATE_SOL1 command */ void lan_get_sol_data(uchar fEnc, uchar seed_cnt, uint32 *seed) { if (seed_cnt != sol_seed_cnt && (seed_cnt < 16)) sol_seed_cnt = seed_cnt; pconn->start_out_seq = ipmi_hdr.seq_num; sol_snd_seq = (uchar)pconn->start_out_seq; sol15_cipherinit(sol_seed_cnt, lanp.pswd, pconn->start_out_seq); *seed = g_Seed[sol_seed_cnt]; if (fdebuglan > 2) dbglog("lan_get_sol_data: %02x %02x %02x\n", /*SOL*/ fEnc, seed_cnt, ipmi_hdr.seq_num); } /* * lan_set_sol_data * Called after ACTIVATE_SOL1 response received */ void lan_set_sol_data(uchar fenc, uchar auth, uchar seed_cnt, int insize, int outsize) { if (fdebuglan > 2) dbglog("lan_set_sol_data: %02x %02x %02x %02x\n", /*SOL*/ auth,seed_cnt,insize,outsize); if (fenc || (auth & 0x07) == 1) { sol_op = 0x80; /*OEM encryption*/ sol_Encryption = 1; } else { sol_op = 0x00; /*no encryption*/ sol_Encryption = 0; } if (seed_cnt != sol_seed_cnt && (seed_cnt < 16)) { /* if seed count changed, re-init the cipher. */ sol_seed_cnt = seed_cnt; sol15_cipherinit(sol_seed_cnt, lanp.pswd, pconn->start_out_seq); } } /* * lan_send_sol * buffer contains characters entered at console. * build an SOL data frame, which ends up * calling _send_lan_cmd(). * * SOL 1.5 Message Format * 0 : Packet Sequence Number * 1 : Packet ack/nak seq num (recvd) * 2 : Character offset (of recvd) * 3 : Seed count * 4 : Operation/Status */ int lan_send_sol( uchar *buffer, int len, SOL_RSP_PKT *rsp) { int rv = -1; int ilen; uchar idata[IPMI_REQBUF_SIZE]; /*=80 bytes*/ uchar *pdata; int hlen, msglen; int sz; IPMI_HDR *phdr; int fdoauth = 1; uchar iauth[16]; uint32 sess_id_tmp; uchar *psessid; int flags; phdr = &ipmi_hdr; hlen = 4 + 10 + 16; // was SOL_HLEN (14); pdata = &idata[0]; memset(pdata,0,hlen); memcpy(&pdata[0], phdr, 4); /* copy RMCP header to buffer */ if (phdr->auth_type == IPMI_SESSION_AUTHTYPE_NONE) fdoauth = 0; else fdoauth = 1; if (fdoauth == 0 && phdr->auth_type != IPMI_SESSION_AUTHTYPE_NONE) pdata[4] = IPMI_SESSION_AUTHTYPE_NONE; else pdata[4] = phdr->auth_type; memcpy(&pdata[5],&phdr->seq_num,4); /*session sequence number*/ sess_id_tmp = phdr->sess_id | SOL_MSG; memcpy(&pdata[9],&sess_id_tmp,4); /*session id*/ if (fdoauth == 0) hlen -= 16; pdata = &idata[hlen]; if (len == 0) { pdata[0] = 0x00; /*ack for keepalive*/ } else { sol_snd_seq = (uchar)inc_sol_seq(sol_snd_seq); pdata[0] = sol_snd_seq; // sol15_encrypt(&pdata[5],buffer,len, sol_seed_cnt); memcpy(&pdata[5],buffer,len); } pdata[1] = sol_rcv_seq; /* seq to ack*/ pdata[2] = sol_rcv_cnt; /* num bytes ack'd */ pdata[3] = sol_seed_cnt; pdata[4] = 0x00; /*Operation/Status*/ msglen = len + 5; { if (fdebuglan > 2) { /*SOL*/ dbg_dump("lan_send_sol input", buffer,len,1); dbglog("auth_type=%x/%x fdoauth=%d hlen=%d seq_num=%x enc=%d\n", phdr->auth_type,lanp.auth_type,fdoauth,hlen,phdr->seq_num, sol_Encryption); dbg_dump("send_sol buf", pdata,msglen,1); } if (fdoauth) { psessid = (uchar *)&sess_id_tmp; do_hash(phdr->password, psessid, &idata[hlen],msglen, phdr->seq_num, phdr->auth_type, iauth); /* copy hashed authcode to header */ memcpy(&pdata[13],iauth,16); } } idata[hlen-1] = (uchar)msglen; ilen = hlen + msglen; // rlen = sizeof(rdata);; if (fdebuglan > 2) dbg_dump("lan_send_sol sendto",idata,ilen,1); flags = 0; sz = ipmilan_sendto(pconn->sockfd,idata,ilen,flags, (struct sockaddr *)&_destaddr,_destaddr_len); if (fdebuglan) dbglog("lan_send_sol, sent %d bytes\n",sz); if (sz < 1) { lasterr = get_LastError(); if (fdebuglan) show_LastError("lan_send_sol",lasterr); rv = LAN_ERR_SEND_FAIL; os_usleep(0,5000); } else { phdr->seq_num = inc_seq_num( phdr->seq_num ); rv = 0; } if (rsp != NULL) { rsp->len = 0; #ifdef RCV_EXTRA if (rv == 0) { /*send was ok, try to receive*/ rv = lan_recv_sol( rsp ); if (fdebuglan) printf("lan_recv_sol ret = %d, len = %d\n",rv,rsp->len); } #endif } return(rv); } int lan_keepalive( uchar bType ) { int rv = 0; #ifdef KAL_OK if (bType == 2) { /* don't try if no data sent yet */ if (sol_snd_seq == 0) return(rv); /* use lan_send_sol, but with 0 length data */ rv = lan_send_sol(NULL,0,NULL); } else #endif { uchar devrec[16]; rv = ipmi_getdeviceid(devrec,16,0); } return(rv); } int lan_recv_sol( SOL_RSP_PKT *rsp ) { static uchar rsdata[MAX_BUFFER_SIZE]; /*LANplus allows 1024*/ uchar rdata[MAX_BUFFER_SIZE]; int rlen, hlen; IPMI_HDR *phdr; uchar *pdata; int itry; int flags; int rv = -1; phdr = &ipmi_hdr; rsp->data = rsdata; hlen = SOL_HLEN; rlen = 0; if (fdebuglan) printf("lan_recv_sol, fdebug=%d, fpdbg=%p\n",fdebuglan,fpdbg); // for (itry = 0; (itry < ipmi_try) && (rlen == 0); itry++) for (itry = 0; (itry < 1) && (rlen == 0); itry++) { /* receive the response */ rv = fd_wait(pconn->sockfd, ipmi_timeout,0); if (rv != 0) { if (fdebuglan) fprintf(fpdbg,"lan_recv_sol timeout\n"); rv = LAN_ERR_RECV_FAIL; os_usleep(0,5000); continue; /* ok to retry */ } flags = RECV_MSG_FLAGS; rlen = ipmilan_recvfrom(pconn->sockfd,rdata,sizeof(rdata),flags, (struct sockaddr *)&_destaddr,&_destaddr_len); if (rlen < 0) { lasterr = get_LastError(); if (fdebuglan) show_LastError("ipmilan_recvfrom",lasterr); rv = rlen; /* -3 = LAN_ERR_RECV_FAIL */ rlen = 0; rsp->len = rlen; if (lasterr == econnrefused) continue; /*try again*/ else break; /* goto EXIT; */ } else { /* successful receive */ rv = 0; if (fdebuglan) { dump_buf("lan_recv_sol rdata",rdata,rlen,1); /*SOL*/ } if (rdata[4] == IPMI_SESSION_AUTHTYPE_NONE) { /* if AUTH_NONE */ /* may have tried with auth, but denied, Dell 1855 */ phdr->auth_type = IPMI_SESSION_AUTHTYPE_NONE; hlen = SOL_HLEN; } net2h(&phdr->iseq_num,&rdata[5],4); /*incoming seq_num from hdr*/ if (rlen >= hlen) { pdata = &rdata[hlen]; if (fdebuglan) dump_buf("lan_recv_sol rsp",rdata,rlen,1); /*SOL*/ rlen -= hlen; if (rlen >= 5) { /*have some data*/ /* 0=seq, 1=ack, 2=cnt, 3=ctl, 4=rsv */ sol_rcv_seq = pdata[0]; sol_rcv_ctl = pdata[3]; pdata = &rdata[hlen+5]; rlen -= 5; /* rlen should match rdata[hlen-1] */ sol_rcv_cnt = (uchar)rlen; } rsp->type = PAYLOAD_TYPE_SOL; rsp->len = rlen; // sol15_decrypt(rsp->data,pdata,rlen, sol_seed_cnt); memcpy(rsp->data,pdata,rlen); } else { if (fdebuglan) printf("lan_recv_sol rlen %d < %d\n",rlen,hlen); /*fpdbg*/ rsp->type = PAYLOAD_TYPE_SOL; rsp->len = 0; } break; } } /*end for*/ return(rv); } #endif uchar cksum(const uchar *buf, register int len) { register uchar csum; register int i; /* 8-bit 2s compliment checksum */ csum = 0; for (i = 0; i < len; i++) csum = (csum + buf[i]) % 256; csum = -csum; return(csum); } /* * ipmi_cmd_ipmb() * This is an entry point for IPMB indirect commands. * Embed the command withn a SendMessage command. * * The iseq value needs to be the same as ipmi_hdr.swseq if * the session is ipmilan, so this routine was moved here. * However, ipmi_cmd_ipmb will also work ok via ipmi_cmdraw * for local commands. */ int ipmi_cmd_ipmb(uchar cmd, uchar netfn, uchar sa, uchar bus, uchar lun, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rc, i, j; uchar idata[IPMI_REQBUF_SIZE]; uchar rdata[MAX_BUFFER_SIZE]; uchar ilen; int rlen; uchar iseq; IPMI_HDR *phdr; char *pstr; uchar fneedclear = 0; uchar cc; if (fdebugcmd) printf("ipmi_cmd_ipmb(%02x,%02x,%02x,%02x,%02x) sdata=%d\n", cmd,netfn,sa,bus,lun,sdata); phdr = &ipmi_hdr; iseq = phdr->swseq; i = 0; idata[i++] = bus; j = i; idata[i++] = sa; /*rsAddr (target)*/ idata[i++] = (netfn << 2) | (lun & 0x03); /*metFm/rsLUN*/ idata[i++] = cksum(&idata[j],2); j = i; idata[i++] = bmc_sa; /* rqAddr (main sa) */ idata[i++] = (iseq << 2) | SMS_LUN; /*rqSeq num, SMS Message LUN = 0x02*/ idata[i++] = cmd; if (sdata > 0) { memcpy(&idata[i],pdata,sdata); i += sdata; } idata[i] = cksum(&idata[j],(i - j)); ilen = ++i; rlen = sizeof(rdata); rc = ipmi_cmdraw(IPMB_SEND_MESSAGE,NETFN_APP, bmc_sa,PUBLIC_BUS,BMC_LUN, idata, ilen, rdata, &rlen, pcc, fdebugcmd); if (rc == 0x83 || *pcc == 0x83) { /*retry*/ rlen = sizeof(rdata); rc = ipmi_cmdraw(IPMB_SEND_MESSAGE,NETFN_APP, bmc_sa,PUBLIC_BUS,BMC_LUN, idata, ilen, rdata, &rlen, pcc, fdebugcmd); } if (fdebugcmd) { if (rc == 0 && *pcc == 0) dump_buf("ipmb sendmsg ok",rdata,rlen,0); else { if (*pcc == 0x80) { pstr = "Invalid session handle"; } else if (*pcc == 0x81) pstr = "Lost Arbitration"; else if (*pcc == 0x82) pstr = "Bus Error"; else if (*pcc == 0x83) pstr = "NAK on Write"; else pstr = ""; fprintf(fpdbg,"ipmb sendmsg error %d, cc %x %s\n",rc,*pcc,pstr); } } if (presp == NULL || sresp == NULL) return(LAN_ERR_INVPARAM); if (rc != 0 || *pcc != 0) { *sresp = 0; return(rc); } if (*sresp < 0) return(LAN_ERR_TOO_SHORT); /* sent ok, now issue a GET_MESSAGE command to get the response. */ for (i = 0; i < 10; i++) { rlen = sizeof(rdata); rc = ipmi_cmdraw(IPMB_GET_MESSAGE,NETFN_APP, bmc_sa,PUBLIC_BUS,BMC_LUN, idata, 0, rdata, &rlen, pcc, fdebugcmd); if (fdebugcmd) printf("ipmb get_message rc=%d cc=%x\n",rc,*pcc); if (rc == 0x80 || *pcc == 0x80) /*empty, so retry*/; else if (rc == 0x83 || *pcc == 0x83) /*busy, so retry*/; else break; /* done w success or error */ #ifdef DOS ; /*short wait*/ #else fd_wait(0,0,10); /* wait 1 msec before retry */ #endif /* will retry up to 10 msec for a get_message response on ipmb */ } if (rc == 0 && *pcc == 0) { if (fdebugcmd) dump_buf("ipmb getmsg ok",rdata,rlen,0); i = 0; if (rlen >= 8) { /* strip out the getmsg header */ *pcc = rdata[6]; rlen -= 8; i = 7; } /* copy the data */ if (rlen > *sresp) rlen = *sresp; memcpy(presp,&rdata[i],rlen); } else { if (*pcc == 0x80) pstr = "buffer empty"; else { fneedclear = 1; pstr = ""; } if (fdebugcmd) fprintf(fpdbg,"ipmb getmsg[%d] error %d, cc %x %s\n",i,rc,*pcc,pstr); if (fneedclear) { /* Clear pending message flags */ idata[0] = 0x03; /* clear EvtMsgBuf & RecvMsgQueue */ rlen = 16; rc = ipmi_cmdraw(IPMB_CLEAR_MSGF, NETFN_APP, bmc_sa, PUBLIC_BUS,BMC_LUN, idata, 1, rdata, &rlen, &cc, fdebugcmd); } rlen = 0; } *sresp = rlen; return(rc); } /* end ipmilan.c */ ipmiutil-3.1.5/util/iconfig.c0000644000076400007640000025764713566765324016242 0ustar mgportalloggers/*--------------------------------------------------------------------------- * Filename: iconfig.c (was bmcconfig.c) * * Author: arcress at users.sourceforge.net * Copyright (c) 2009 Kontron America, Inc. * * Abstract: * This tool saves and restores the BMC Configuration parameters. * This includes BMC PEF, LAN, Serial, User, Channel, and SOL parameters. * * ----------- Change History ----------------------------------------------- * 08/18/08 Andy Cress - created from pefconfig.c */ /*M* *--------------------------------------------------------------------------- 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 Kontron 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*/ #ifdef WIN32 #include #include #include #include #include #include #include "getopt.h" #elif defined(DOS) #include #include #include #include #include "getopt.h" #else #include #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #include #include #include #include #include #endif #ifdef SOLARIS #include #define SIOCGIFHWADDR SIOCGENADDR #define ifr_netmask ifr_ifru.ifru_addr #elif defined(BSD) #include #define SIOCGIFHWADDR SIOCGIFMAC #define ifr_netmask ifr_ifru.ifru_addr #elif defined(MACOS) #include // #define SIOCGIFHWADDR SIOCGIFMAC #define ifr_netmask ifr_ifru.ifru_addr #endif #include "ipmicmd.h" #include "oem_intel.h" #include "oem_supermicro.h" extern int find_ifname(char *ifname); /*see idiscover.c*/ /* atoip was moved to subs.c, defined in ipmicmd.h */ #define SELprintf printf #define RTF_UP 0x0001 /* route usable */ #define SOL_ENABLE_FLAG 0x01 #define SOL_DISABLE_FLAG 0x00 #define SOL_PRIVILEGE_LEVEL_USER 0x02 #define SOL_PREFERRED_BAUD_RATE 0x07 /*19.2k*/ /* For IPMI 1.5, use Intel SOL commands & subfunctions */ #define SOL_ENABLE_PARAM 0x01 #define SOL_AUTHENTICATION_PARAM 0x02 #define SOL_ACC_INTERVAL_PARAM 0x03 #define SOL_RETRY_PARAM 0x04 #define SOL_BAUD_RATE_PARAM 0x05 /*non-volatile*/ #define SOL_VOL_BAUD_RATE_PARAM 0x06 /*volatile*/ /* For IPMI 2.0, use IPMI SOL commands & subfunctions */ #define SOL_ENABLE_PARAM2 0x08 #define SOL_AUTHENTICATION_PARAM2 0x09 #define SOL_BAUD_RATE_PARAM2 0x11 /* IPMI 2.0 SOL PAYLOAD commands */ #define SET_PAYLOAD_ACCESS 0x4C #define GET_PAYLOAD_ACCESS 0x4D #define GET_PAYLOAD_SUPPORT 0x4E /* Channel Access values */ #define CHAN_ACC_DISABLE 0x20 /* PEF off, disabled*/ #define CHAN_ACC_PEFON 0x02 /* PEF on, always avail */ #define CHAN_ACC_PEFOFF 0x22 /* PEF off, always avail*/ /* special channel access values for ia64 */ #define CHAN_ACC_PEFON64 0x0A /* PEF on, always avail, UserLevelAuth=off */ #define CHAN_ACC_PEFOFF64 0x2A /* PEF off, always avail, UserLevelAuth=off */ /* TSRLT2/TIGPR2U Channels: 0=IPMB, 1=Serial/EMP, 6=LAN2, 7=LAN1 */ /* S5000/other Channels: 1=LAN1, 2=LAN2, 3=LAN3, 4=Serial, 6=pci, 7=sys */ #define LAN_CH 1 #define SER_CH 4 #define MAXCHAN 12 /*was 16, reduced for gnu ipmi_lan*/ #define NUM_DEVICES_TO_CHECK 32 /*for GetBmcEthDevice()*/ #define MAC_LEN 6 /*length of MAC Address*/ #define PSW_LEN 16 /*see also PSW_MAX=20 in ipmicmd.h*/ #define MAXPEF 41 /* max pefnum offset = 40 (41 entries) */ /* IP address source values */ #define SRC_STATIC 0x01 #define SRC_DHCP 0x02 /* BMC running DHCP */ #define SRC_BIOS 0x03 /* BIOS, sometimes DHCP */ #define SRC_OTHER 0x04 /* PEF event severities */ #define PEF_SEV_UNSPEC 0x00 #define PEF_SEV_MON 0x01 #define PEF_SEV_INFO 0x02 #define PEF_SEV_OK 0x04 #define PEF_SEV_WARN 0x08 #define PEF_SEV_CRIT 0x10 #define PEF_SEV_NORECOV 0x20 typedef struct { /* See IPMI Table 15-2 */ uchar rec_id; uchar fconfig; uchar action; uchar policy; uchar severity; uchar genid1; uchar genid2; uchar sensor_type; uchar sensor_no; uchar event_trigger; uchar data1; uchar mask1; uchar res[9]; } PEF_RECORD; /* * Global variables */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil config"; #else static char * progver = "3.08"; static char * progname = "iconfig"; #endif static char fdebug = 0; static char fipmilan = 0; static FILE * fd_bmc = NULL; static char fIPMI10 = 0; /* =1 if IPMI v1.0 or less */ static char fIPMI20 = 0; /* =1 if IPMI v2.0 or greater */ static char fSOL20 = 1; /* =1 if SOL v2.0 is ok */ static char freadonly = 1; /* =1 to only read LAN & PEF parameters */ static char func = 'd'; /* function: display, save, restore */ static char fdomac = 0; /* =1 to restore MAC also */ static char fpassword = 0; /* =1 user-specified a password, so set it. */ static uchar fmBMC = 0; static uchar fiBMC = 0; static uchar fRomley = 0; static uchar fGrantley = 0; static char fipv6 = 0; static char fcanonical = 0; static char fchan2wart = 0; /* =1 if need wart to skip channel 2 */ static char bdelim = BCOLON; /*':' as default*/ static char bcomment = BCOMMENT; /* '#' */ static char pefmax = MAXPEF; /* 20 for Sahalee, 30 for miniBMC */ static int nerrs = 0; static int ngood = 0; static int lasterr = 0; static uchar nusers = 5; static uchar max_users = 5; static uchar enabled_users = 0; static uchar last_user_enable = 0; /* last user enabled */ static uchar passwordData[16]; static uchar fsetifn = 0; static ushort setsolcmd; static ushort getsolcmd; static uchar sol_bchan = 0; static uchar authmask = 0; static uchar lan_access = 0x04; /* see SetPassword*/ static uchar pefnum = 12; static uchar fsharedMAC = 0; //static uchar alertnum = 1; //static uchar rgdestip[4]; static uchar rgdestmac[6]; static uchar rggwymac[6]; #ifdef WIN32 static uchar rggwyip[4] = {0,0,0,0}; static uchar rgmyip [4] = {0,0,0,0}; /*WIN32*/ static uchar rgmymac[6] = {0xFF,0,0,0,0,0}; /*WIN32*/ static uchar rgsubnet[4] = {0,0,0,0}; /*WIN32*/ static uchar osmyip[4] = {0,0,0,0}; static uchar osmymac[6] = {0xff,0,0,0,0,0}; #endif static uchar bmcmyip[4] = {0,0,0,0}; static uchar bmcdestip[4] = {0,0,0,0}; static uchar bmcmymac[6] = {0xFF,0,0,0,0,0}; static char ifname[16] = "eth0"; /* interface name */ static char ifname0[16] = "eth0"; /* first interface name */ static char ifpattn[14] = "eth"; /* default, discovered via find_ifname */ static int vend_id; static int prod_id; static uchar ser_ch = 0; /*was SER_CH==4*/ static uchar lan_ch = LAN_CH; static uchar lan_ch_parm = 0xff; static uchar lan_ch_sav = 0xff; static uchar gcm_ch = 0; static uchar SessInfo[16]; static uchar chan_type[MAXCHAN]; static int nlans = 0; #define MAX_PEFPARAMS 14 /* max pef params = 14 */ static char **pefdesc; static char *pefdesc1[MAXPEF] = { /* for Sahalee BMC */ /* 0 0x00 */ "", /* 1 0x01 */ "Temperature Sensor", /* 2 0x02 */ "Voltage Sensor", /* 3 0x04 */ "Fan Failure", /* 4 0x05 */ "Chassis Intrusion", /* 5 0x08 */ "Power Supply Fault", /* 6 0x0c */ "Memory ECC Error", /* 7 0x0f */ "FRB Failure", /* 8 0x07 */ "BIOS POST Error", /* 9 0x13 */ "Fatal NMI", /*10 0x23 */ "Watchdog Timer Reset", /*11 0x12 */ "System Restart", /*12 0x20 */ "OS Critical Stop", /*13 0x09 */ "Power Redundancy Lost", /*14 0x00 */ "reserved", /*15 0x00 */ "reserved", /*16 0x00 */ "reserved", /*17 */ "reserved", /*18 */ "reserved", /*19 */ "reserved", /*20 */ "reserved", /*21 */ "reserved", /*22 */ "reserved", /*23 */ "reserved", /*24 */ "reserved", /*25 */ "reserved", /*26 */ "reserved", /*27 */ "reserved", /*28 */ "reserved", /*29 */ "unused", /*30 */ "unused" }; static char *pefdesc2[MAXPEF] = { /* for NSC miniBMC */ /* 0 */ "", /* 1 0x02*/ "Voltage Sensor Assert", /* 2 0x23*/ "Watchdog FRB Timeout", /* was "Proc FRB Thermal", */ /* 3 0x02*/ "Voltage Sensor Deassert", /* 4 0x07*/ "Proc1 IERR", /* 5 0xff*/ "Digital Sensor OK", /* 6 0x14*/ "Chassis Identify", /* 7 0x13*/ "NMI Button", /* 8 0x14*/ "Clear CMOS via Panel", /* 9 0x0f*/ "OS Load POST Code", /*10 0x20*/ "OS Critical Stop", /*11 0x09 */ "Power Redundancy Lost", /*12 0x00*/ "reserved", /*13 */ "reserved", /*14 */ "reserved", /*15 */ "reserved", /*16 */ "reserved", /*17 */ "reserved", /*18 */ "reserved", /*19 */ "reserved", /*20 */ "reserved", /*21 */ "reserved", /*22 */ "reserved", /*23 */ "reserved", /*24 */ "reserved", /*25 */ "reserved", /*26 0x05*/ "Chassis Intrusion", /*27 0x0f*/ "POST Code Error", /*28 0x02*/ "Voltage Failure", /*29 0x04*/ "Fan Failure", /*30 0x01*/ "Temperature Failure"}; #define NLAN 39 static struct { int cmd; int sz; char desc[28]; } lanparams[NLAN] = { /* see IPMI Table 19-4 */ /* 0 */ { 0, 1, "Set in progress"}, /* 1 */ { 1, 1, "Auth type support"}, /* 2 */ { 2, 5, "Auth type enables"}, /* 3 */ { 3, 4, "IP address"}, /* 4 */ { 4, 1, "IP addr src"}, /* (DHCP/Static) */ /* 5 */ { 5, 6, "MAC addr"}, /* 6 */ { 6, 4, "Subnet mask"}, /* 7 */ { 7, 3, "IPv4 header"}, /* 8 */ { 8, 2, "Prim RMCP port"}, /* 9 */ { 9, 2, "Sec RMCP port"}, /* 10 */ {10, 1, "BMC grat ARP"}, /* 11 */ {11, 1, "grat ARP interval"}, /* 12 */ {12, 4, "Def gateway IP"}, /* 13 */ {13, 6, "Def gateway MAC"}, /* 14 */ {14, 4, "Sec gateway IP"}, /* 15 */ {15, 6, "Sec gateway MAC"}, /* 16 */ {16,18, "Community string"}, /* 17 */ {17, 1, "Num dest"}, /* 18 */ {18, 5, "Dest type"}, /* 19 */ {19, 13, "Dest address"}, /* 20 */ {20, 2, "VLAN ID"}, /* 21 */ {21, 1, "VLAN Priority"}, /* 22 */ {22, 1, "Cipher Suite Support"}, /* 23 */ {23,17, "Cipher Suites"}, /* 24 */ {24, 9, "Cipher Suite Privilege"}, /* 25 */ {25, 4, "VLAN Dest Tag"}, /* 26 */ {96, 28, "OEM Alert String"}, /* 27 */ {97, 1, "Alert Retry Algorithm"}, /* 28 */ {98, 3, "UTC Offset"}, /* 29 */ {102, 1, "IPv6 Enable"}, /* 30 */ {103, 1, "IPv6 Addr Source"}, /* 31 */ {104,16, "IPv6 Address"}, /* 32 */ {105, 1, "IPv6 Prefix Len"}, /* 33 */ {106,16, "IPv6 Default Gateway"}, /* 34 */ {108,17, "IPv6 Dest address"}, /* 35 */ {192, 4, "DHCP Server IP"}, /* 36 */ {193, 6, "DHCP MAC Address"}, /* 37 */ {194, 1, "DHCP Enable"}, /* 38 */ {201, 2, "Channel Access Mode(Lan)"} }; #define NSER 22 /* max=32 */ static struct { int cmd; int sz; char desc[28]; } serparams[NSER] = { /* see IPMI Table 20-4 */ /* 0 */ { 0, 1, "Set in progress"}, /* 1 */ { 1, 1, "Auth type support"}, /* 2 */ { 2, 5, "Auth type enables"}, /* 3 */ { 3, 1, "Connection Mode"}, /* 4 */ { 4, 1, "Sess Inactiv Timeout"}, /* 5 */ { 5, 5, "Channel Callback"}, /* 6 */ { 6, 1, "Session Termination"}, /* 7 */ { 7, 2, "IPMI Msg Comm"}, /* 8 */ { 8, 2, "Mux Switch"}, /* 9 */ { 9, 2, "Modem Ring Time"}, /* 10 */ {10,17, "Modem Init String"}, /* 11 */ {11, 5, "Modem Escape Seq"}, /* 12 */ {12, 8, "Modem Hangup Seq"}, /* 13 */ {13, 8, "Modem Dial Command"}, /* 14 */ {14, 1, "Page Blackout Interval"}, /* 15 */ {15,18, "Community String"}, /* 16 */ {16, 1, "Num of Alert Dest"}, /* 17 */ {17, 5, "Destination Info"}, /* 18 */ {18, 1, "Call Retry Interval"}, /* 19 */ {19, 3, "Destination Comm Settings"}, /* 20 */ {29, 2, "Terminal Mode Config"}, /* 21 */ {201, 2,"Channel Access Mode (Ser)"} }; #define NSYS 6 /* num SystemParam */ #define CHAS_RESTORE 0x00 /*chassis power restore policy*/ #define SYS_INFO 0x01 /*System Info (1,2,3,4) */ #define LAN_FAILOVER 0x02 /*Intel LAN Failover*/ /* TODO: Future DCMI 1.5 params */ #define DCMI_POWER 0x03 /*DCMI Power limit*/ #define DCMI_THERMAL 0x04 /*DCMI Thermal params*/ #define DCMI_CONFIG 0x05 /*DCMI Config params*/ static int GetDeviceID(uchar *pLanRecord) { /*See also ipmi_getdeviceid( pLanRecord, sizeof(LAN_RECORD),fdebug); */ uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar inputData[24]; uchar completionCode; if (pLanRecord == NULL) return(-1); status = ipmi_cmd(GET_DEVICE_ID, inputData, 0, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { SELprintf("GetDeviceID: completion code=%x\n", completionCode); status = completionCode; } else { memcpy(pLanRecord,&responseData[0],responseLength); set_mfgid(&responseData[0],responseLength); return(0); // successful, done } } /* endif */ /* if get here, error */ return(status); } /*end GetDeviceID() */ static int GetChanAcc(uchar chan, uchar parm, uchar *pLanRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar inputData[24]; uchar completionCode; if (pLanRecord == NULL) return(-1); responseLength = 3; inputData[0] = chan; inputData[1] = parm; /* 0x80 = active, 0x40 = non-volatile */ responseLength = sizeof(responseData); status = ipmi_cmd(GET_CHANNEL_ACC, inputData, 2, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { SELprintf("%c GetChanAcc: completion code=%x\n", bcomment,completionCode); status = completionCode; } else { // dont copy first byte (Parameter revision, usu 0x11) memcpy(pLanRecord,&responseData[0],responseLength); return(0); // successful, done } } /* endif */ /* if get here, error */ return(status); } /*GetChanAcc()*/ static int SetChanAcc(uchar chan, uchar parm, uchar val, uchar access) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar inputData[24]; uchar completionCode; if (fmBMC) return(0); /* mBMC doesn't support this */ /* parm: 0x80 = active, 0x40 = set non-vol*/ responseLength = 1; inputData[0] = chan; /* channel */ inputData[1] = (parm & 0xc0) | (val & 0x3F); inputData[2] = (parm & 0xc0) | access; /* set priv level */ responseLength = sizeof(responseData); status = ipmi_cmd(SET_CHANNEL_ACC, inputData, 3, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { SELprintf("SetChanAcc: completion code=%x\n", completionCode); status = completionCode; } else { return(0); // successful, done } } /* endif */ /* if get here, error */ return(status); } /*SetChanAcc()*/ static int GetUser(int user_num) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status, i; uchar completionCode; char inputData[24]; inputData[0] = lan_ch; inputData[1] = (uchar)user_num; /* usually = 1 for BMC LAN */ responseLength = sizeof(responseData); status = ipmi_cmd(GET_USER_ACCESS, inputData, 2, responseData, &responseLength, &completionCode, fdebug); if (status == 0 && completionCode == 0) { uchar c; if (user_num == 1) { max_users = responseData[0] & 0x3f; enabled_users = responseData[1] & 0x3f; if (enabled_users > nusers) nusers = enabled_users; } fprintf(fd_bmc,"UserAccess %d,%d%c %02x %02x %02x %02x \n", lan_ch,user_num,bdelim,responseData[0],responseData[1], responseData[2], responseData[3]); c = responseData[3]; inputData[0] = (uchar)user_num; /* usually = 1 for BMC LAN */ responseLength = sizeof(responseData); status = ipmi_cmd(GET_USER_NAME, inputData, 1, responseData, &responseLength, &completionCode, fdebug); if (status != 0 || completionCode != 0) responseData[0] = 0; else { fprintf(fd_bmc,"UserName %d%c",user_num,bdelim); for (i=0; i< responseLength; i++) fprintf(fd_bmc," %02x",responseData[i]); fprintf(fd_bmc,"\n"); fprintf(fd_bmc,"%c UserPassword %d%c",bcomment,user_num,bdelim); for (i=0; i< PSW_LEN; i++) fprintf(fd_bmc," 00"); fprintf(fd_bmc,"\n"); } } else printf("%c GetUserAccess(%d,%d), status=%x, ccode=%x\n", bcomment,lan_ch,user_num, status, completionCode); return(status); } /*end GetUser()*/ static int GetSerEntry(uchar subfunc, uchar bset, uchar *pLanRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; uchar chan; if (pLanRecord == NULL) { if (fdebug) printf("GetSerEntry(%d): error, output buffer is NULL\n",subfunc); return (-1); } chan = ser_ch; /* 1=EMP, 0=IPMB, 6=LAN2, 7=LAN1 */ inputData[0] = chan; // flags, channel 3:0 (1=EMP) inputData[1] = subfunc; // Param selector inputData[2] = bset; // Set selector inputData[3] = 0; // Block selector if (subfunc == 10) { inputData[2] = 0; inputData[3] = 1; } status = ipmi_cmd(GET_SER_CONFIG, inputData, 4, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { if (fdebug) SELprintf("GetSerEntry(%d,%d): completion code=%x\n", chan,subfunc,completionCode); status = completionCode; } else { // dont copy first byte (Parameter revision, usu 0x11) memcpy(pLanRecord,&responseData[1],responseLength-1); pLanRecord[responseLength-1] = 0; //successful, done return(0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) SELprintf("GetSerEntry(%d,%d): ipmi_cmd status=%x ccode=%x\n", chan,subfunc,status,completionCode); return status; } static int SetSerEntry(uchar subfunc, uchar *pSerRecord, int reqlen) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; if (pSerRecord == NULL) { if (fdebug) printf("SetSerEntry(%d): error, input buffer is NULL\n", subfunc); return (-1); } inputData[0] = ser_ch; // flags, channel 3:0 (EMP) inputData[1] = subfunc; // Param selector memcpy(&inputData[2],pSerRecord,reqlen); status = ipmi_cmd(SET_SER_CONFIG, inputData, (uchar)(reqlen+2), responseData, &responseLength, &completionCode, fdebug); if (fdebug) printf("SetSerEntry: ipmi_cmd status=%d, completion code=%d\n", status,completionCode); if (status == ACCESS_OK) { if( completionCode ) { status = completionCode; if (completionCode == 0x80) printf("SetSerEntry(%d): Parameter not supported\n", subfunc); else printf("SetSerEntry(%d): completion code=%x\n", subfunc, completionCode); } // else successful, done } return status; } /* end SetSerEntry() */ static int GetLanEntry(uchar subfunc, uchar bset, uchar *pLanRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status, n; uchar completionCode; uchar chan; if (pLanRecord == NULL) { if (fdebug) printf("GetLanEntry: error, output buffer is NULL\n"); return (-1); } chan = lan_ch; /* LAN 1 = 7 */ inputData[0] = chan; // flags, channel 3:0 (LAN 1) inputData[1] = subfunc; // Param selector (3 = ip addr) inputData[2] = bset; // Set selector inputData[3] = 0; // Block selector status = ipmi_cmd(GET_LAN_CONFIG, inputData, 4, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { if (fdebug) SELprintf("GetLanEntry(%d,%d): completion code=%x\n", chan,subfunc,completionCode); status = completionCode; } else { // dont copy first byte (Parameter revision, usu 0x11) if (responseLength > 0) { n = responseLength-1; memcpy(pLanRecord,&responseData[1],n); } else n = 0; pLanRecord[n] = 0; //successful, done return(0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) SELprintf("GetLanEntry(%d,%d): status=%d completionCode=%x\n", chan,subfunc,status,completionCode); return (status); } /* end GetLanEntry() */ static int SetLanEntry(uchar subfunc, uchar *pLanRecord, int reqlen) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; if (pLanRecord == NULL) { if (fdebug) printf("SetLanEntry(%d): error, input buffer is NULL\n",subfunc); return (-1); } if ((vend_id == VENDOR_SUPERMICROX) || (vend_id == VENDOR_SUPERMICRO)) { /* SUPERMICRO cannot set grat arp or grat arp interval */ if (subfunc == 10 || subfunc == 11) return(0); } inputData[0] = lan_ch; // flags, channel 3:0 (LAN 1) inputData[1] = subfunc; // Param selector (3 = ip addr) memcpy(&inputData[2],pLanRecord,reqlen); status = ipmi_cmd(SET_LAN_CONFIG, inputData, (uchar)(reqlen+2), responseData, &responseLength,&completionCode,fdebug); if (status == ACCESS_OK) { if( completionCode ) { if (fdebug) SELprintf("SetLanEntry(%d,%d): completion code=%x\n", lan_ch,subfunc,completionCode); return(completionCode); } else { //successful, done return(0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) SELprintf("SetLanEntry(%d,%d): ipmi_cmd status=%d ccode=%x\n", lan_ch,subfunc,status,completionCode); return (status); } /* end SetLanEntry() */ static int GetPefEntry(uchar subfunc, ushort rec_id, PEF_RECORD *pPefRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status, n; uchar completionCode; if (pPefRecord == NULL) { if (fdebug) printf("GetPefEntry(%d): error, output buffer is NULL\n",subfunc); return (-1); } inputData[0] = subfunc; // Parameter = Evt Filter Table inputData[1] = (uchar)rec_id; inputData[2] = 0; status = ipmi_cmd(GET_PEF_CONFIG, inputData, 3, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { if (fdebug) SELprintf("GetPefEntry(%d/%d): completion code=%x\n", subfunc,rec_id,completionCode); status = completionCode; } else { /* expect PEF record to be >=21 bytes */ if (responseLength > 1) n = responseLength-1; else n = 0; if (n > 21) n = 21; // dont copy first byte (Parameter revision, usu 0x11) if (n == 0) memset(pPefRecord,0,21); else memcpy(pPefRecord,&responseData[1],n); //successful, done return(0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) SELprintf("GetPefEntry: ipmi_cmd status=%x completionCode=%x\n", status, completionCode); return status; } /* end GetPefEntry() */ static int SetPefEntry(PEF_RECORD *pPefRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; /* sizeof(PEF_RECORD) = 21 +1=22 */ int status; uchar completionCode; uchar subfunc; subfunc = 0x06; // Parameter = Evt Filter Table if (pPefRecord == NULL) { if (fdebug) printf("SetPefEntry: error, output buffer is NULL\n"); return (-1); } // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 // 06 0c 80 01 01 00 ff ff 20 ff 6f ff 00 00 00 00 00 00 00 00 00 00 // memset(&inputData[0],0,requestData.dataLength); inputData[0] = subfunc; memcpy(&inputData[1],pPefRecord,sizeof(PEF_RECORD)); status = ipmi_cmd(SET_PEF_CONFIG, inputData, sizeof(PEF_RECORD)+1, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { if (fdebug) SELprintf("SetPefEntry: completion code=%x\n", completionCode); // responseData[0]); status = completionCode; } else { //successful, done return(0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) SELprintf("SetPefEntry: ipmi_cmd status=%d ccode=%x\n", status,completionCode); return(status); } /* end SetPefEntry() */ static int MacIsValid(uchar *mac) { int fvalid = 0; int i; /* check for initial invalid value of FF:00:... */ if (mac[0] == 0xFF && mac[1] == 0x00) /* marked as invalid */ return(fvalid); /* check for all zeros */ for (i = 0; i < MAC_LEN; i++) if (mac[i] != 0) { /* not all zeros */ fvalid = 1; break; } return(fvalid); } static int IpIsValid(uchar *ipadr) { int fvalid = 1; if (ipadr[0] == 0) fvalid = 0; return(fvalid); } static int SubnetIsValid(uchar *subnet) { int fvalid = 0; /* if masking off at least one bit, say valid */ if ((subnet[0] & 0x80) == 0x80) fvalid = 1; return(fvalid); } #ifdef WIN32 /* * Obtain network adapter information (Windows). */ static PIP_ADAPTER_ADDRESSES GetAdapters() { PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL; ULONG OutBufferLength = 0; ULONG RetVal = 0, i; // The size of the buffer can be different // between consecutive API calls. // In most cases, i < 2 is sufficient; // One call to get the size and one call to get the actual parameters. // But if one more interface is added or addresses are added, // the call again fails with BUFFER_OVERFLOW. // So the number is picked slightly greater than 2. // We use i <5 in the example for (i = 0; i < 5; i++) { RetVal = GetAdaptersAddresses( AF_INET, 0, NULL, AdapterAddresses, &OutBufferLength); if (RetVal != ERROR_BUFFER_OVERFLOW) { break; } if (AdapterAddresses != NULL) { free(AdapterAddresses); } AdapterAddresses = (PIP_ADAPTER_ADDRESSES) malloc(OutBufferLength); if (AdapterAddresses == NULL) { RetVal = GetLastError(); break; } } if (RetVal == NO_ERROR) { // If successful, return pointer to structure return AdapterAddresses; } else { LPVOID MsgBuf; printf("Call to GetAdaptersAddresses failed.\n"); if (FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, RetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &MsgBuf, 0, NULL )) { printf("\tError: %s", MsgBuf); } LocalFree(MsgBuf); } return NULL; } /* * Set BMC MAC corresponding to current BMC IP address (Windows). */ static int GetLocalMACByIP() { PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL; PIP_ADAPTER_ADDRESSES AdapterList; int result = 0; struct sockaddr_in *si; AdapterAddresses = GetAdapters(); AdapterList = AdapterAddresses; while (AdapterList) { PIP_ADAPTER_UNICAST_ADDRESS addr; addr = AdapterList->FirstUnicastAddress; if (addr == NULL) si = NULL; else si = (struct sockaddr_in*)addr->Address.lpSockaddr; if (si != NULL) { if(memcmp(&si->sin_addr.s_addr, rgmyip, 4) == 0) { memcpy(rgmymac, AdapterList->PhysicalAddress, MAC_LEN); result = 1; break; } } AdapterList = AdapterList->Next; } if (AdapterAddresses != NULL) { free(AdapterAddresses); } return result; } /* * Set BMC MAC corresponding to current BMC IP address (Windows). */ static int GetLocalIPByMAC(uchar *macadr) { PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL; PIP_ADAPTER_ADDRESSES AdapterList; int result = 0; struct sockaddr_in *si; AdapterAddresses = GetAdapters(); AdapterList = AdapterAddresses; while (AdapterList) { PIP_ADAPTER_UNICAST_ADDRESS addr; if(memcmp(AdapterList->PhysicalAddress, macadr, MAC_LEN) == 0) { addr = AdapterList->FirstUnicastAddress; si = (struct sockaddr_in*)addr->Address.lpSockaddr; if (fdebug) { uchar *psaddr; psaddr = (uchar *)&si->sin_addr.s_addr; printf("mac match: rgmyip=%d.%d.%d.%d s_addr=%d.%d.%d.%d\n", rgmyip[0], rgmyip[1], rgmyip[2], rgmyip[3], psaddr[0], psaddr[1], psaddr[2], psaddr[3]); } if (!IpIsValid(rgmyip) && (fsharedMAC==1)) /*not specified, shared*/ memcpy(rgmyip, &si->sin_addr.s_addr, 4); memcpy(osmyip, &si->sin_addr.s_addr, 4); memcpy(osmymac, AdapterList->PhysicalAddress, MAC_LEN); wcstombs(ifname,AdapterList->FriendlyName, sizeof(ifname)); result = 1; break; } AdapterList = AdapterList->Next; } if (AdapterAddresses != NULL) { free(AdapterAddresses); } return result; } /* * Set MAC and IP address from given interface name (Windows). */ static int GetLocalDataByIface() { PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL; PIP_ADAPTER_ADDRESSES AdapterList; int result = 0; size_t origsize, newsize, convertedChars; wchar_t* wcstring; struct sockaddr_in *si; AdapterAddresses = GetAdapters(); AdapterList = AdapterAddresses; origsize = strlen(ifname) + 1; newsize = origsize; convertedChars = 0; wcstring = (wchar_t*) malloc(sizeof(wchar_t) * newsize) ; if (wcstring == NULL) AdapterList = NULL; /*skip loop, do free*/ else mbstowcs(wcstring, ifname, origsize ); while (AdapterList) { PIP_ADAPTER_UNICAST_ADDRESS addr; if(wcsstr(AdapterList->FriendlyName, wcstring)) { printf("Using interface: %S\n", AdapterList->FriendlyName); printf("\t%S\n", AdapterList->Description); addr = AdapterList->FirstUnicastAddress; si = (struct sockaddr_in*)addr->Address.lpSockaddr; memcpy(rgmyip, &si->sin_addr.s_addr, 4); memcpy(rgmymac, AdapterList->PhysicalAddress, MAC_LEN); result = 1; break; } AdapterList = AdapterList->Next; } if (AdapterAddresses != NULL) { free(AdapterAddresses); } return result; } static int FindEthNum(uchar *macadrin) { int i; uchar macadr[MAC_LEN]; memcpy(macadr,macadrin,MAC_LEN); if (fsharedMAC == 0 && vend_id == VENDOR_INTEL) { /* Intel factory assigns them this way, so use that to compare */ macadr[MAC_LEN-1] -= 2; /*OS MAC = BMC MAC - 2*/ } i = GetLocalIPByMAC(macadr); if (fdebug) /* show the local OS eth if and MAC */ printf("FindEth: OS %s IP=%d.%d.%d.%d MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", ifname, rgmyip[0], rgmyip[1], rgmyip[2], rgmyip[3], rgmymac[0], rgmymac[1], rgmymac[2], rgmymac[3], rgmymac[4], rgmymac[5]); /* The actual Windows ethernet interface is determined * in Get_IPMac_Addr using ipconfig, so * init eth interface number as eth0 for Windows. */ return(i); } #elif defined(HPUX) static int FindEthNum(uchar *macadrin) { return(0); } #else /* Linux, BSD, Solaris */ static char *get_ifreq_mac(struct ifreq *ifrq) { char *ptr; #ifdef SOLARIS ptr = (char *)&ifrq->ifr_ifru.ifru_enaddr[0]; #elif BSD ptr = (char *)&ifrq->ifr_ifru.ifru_addr.sa_data[0]; #elif MACOS static uchar mactmp[MAC_LEN]; ptr = &mactmp[0]; MacSetInvalid(ptr); #else ptr = (char *)&ifrq->ifr_hwaddr.sa_data[0]; #endif return (ptr); } static int FindEthNum(uchar *macadrin) { /*only used for Linux*/ struct ifreq ifr; int skfd; int nCurDevice; uchar macadr[MAC_LEN]; char szDeviceName[ 16 ]; /* sizeof(ifpattn), MAX_DEVICE_NAME_LENGTH + 1 */ int devnum = -1; int n; memcpy(macadr,macadrin,MAC_LEN); if (fsharedMAC == 0 && vend_id == VENDOR_INTEL) { /* Intel factory assigns them this way, so use that to compare */ macadr[MAC_LEN-1] -= 2; /*OS MAC = BMC MAC - 2*/ } n = find_ifname(szDeviceName); if (n >= 0) { n = strlen_(szDeviceName); if (n < sizeof(ifpattn)) { strcpy(ifname0,szDeviceName); strcpy(ifpattn,szDeviceName); ifpattn[n - 1] = 0; /*truncate last digit*/ } if (fdebug) printf("found ifname %s, pattern %s\n",szDeviceName,ifpattn); } if ( ( skfd = socket(AF_INET, SOCK_DGRAM, 0 ) ) < 0) { if ( fdebug ) { perror("socket"); return devnum; } } for( nCurDevice = 0 ; (nCurDevice < NUM_DEVICES_TO_CHECK) && (devnum == -1); nCurDevice++ ) { sprintf( szDeviceName, "%s%d", ifpattn, nCurDevice ); strcpy(ifr.ifr_name, szDeviceName ); #ifdef SIOCGIFHWADDR if (ioctl(skfd, SIOCGIFHWADDR, &ifr) > 0) { if ( fdebug ) printf("FindEthNum: Could not get MAC address for %s\n", szDeviceName); } else #endif { if (memcmp(get_ifreq_mac(&ifr), macadr, MAC_LEN) == 0) { devnum = nCurDevice; break; } } } close(skfd); return(devnum); } #endif /* * GetBmcEthDevice * Attempt to auto-detect the BMC LAN channel and matching OS eth port. * INPUT: lan_parm = lan channel from user -L option, 0xFF if not specified * OUTPUT: lan_ch is set to BMC LAN channel number * if success, returns index of OS eth port (0, 1, ...). * if no lan channels found, returns -2. * if other error, returns -1. */ static int GetBmcEthDevice(uchar lan_parm) { uchar LanRecord[30]; int devnum = -1; int ret; uchar bmcMacAddress[ MAC_LEN ]; /*MAC_LEN = 6*/ int rlen; uchar iData[2]; uchar rData[10]; uchar cc; int i = 0; int j, jstart, jend, jlan; uchar mtype; uchar *pb; int fchgmac; /* Find the LAN channel(s) via Channel Info */ if (lan_parm < MAXCHAN) { /* try user-specified channel only */ lan_ch = lan_parm; jstart = lan_parm; jend = lan_parm+1; } else { jstart = 1; jend = MAXCHAN; for (j = 0; j < MAXCHAN; j++) chan_type[j] = 0; } memset(bmcMacAddress,0xff,sizeof(bmcMacAddress)); /*initialize to invalid*/ for (j = jstart; j < jend; j++) { rlen = sizeof(rData); iData[0] = (uchar)j; /*channel #*/ memset(rData,0,9); /*initialize recv data*/ ret = ipmi_cmd(GET_CHANNEL_INFO, iData, 1, rData, &rlen, &cc, fdebug); if (ret == 0xcc || cc == 0xcc) /* special case for ipmi_lan */ continue; if (ret != 0) { if (fdebug) printf("get_chan_info rc = %x\n",ret); break; } mtype = rData[1]; /* channel medium type */ chan_type[j] = mtype; if (mtype == 4) { /* 802.3 LAN type*/ if (fdebug) printf("chan[%d] = lan\n",j); jlan = lan_ch; /*save prev lan chan */ /* Get BMC MAC for this LAN channel. */ /* Note: BMC MAC may not be valid yet. */ lan_ch = (uchar)j; /*set lan channel for GetLanEntry()*/ ret = GetLanEntry( 5 /*MAC_ADDRESS_LAN_PARAM*/,0, LanRecord); if ( ret < 0 ) { lan_ch = (uchar)jlan; /*restore lan_ch*/ printf( "GetBmcEthDevice: GetLanEntry failed\n" ); return devnum; } pb = &LanRecord[0]; if (fdebug) printf("chan[%d] BMC MAC %x:%x:%x:%x:%x:%x\n",j, pb[0], pb[1], pb[2], pb[3], pb[4], pb[5] ); fchgmac = 0; if (!MacIsValid(bmcMacAddress)) /* old MAC not valid */ fchgmac = 1; else if (MacIsValid(pb) && /* new MAC is valid and */ (memcmp(bmcMacAddress,pb, sizeof(bmcMacAddress)) > 0)) fchgmac = 1; /* new MAC lower */ if (fchgmac) { /* use lowest valid MAC */ memcpy(bmcMacAddress,pb,sizeof(bmcMacAddress)); lan_ch = (uchar)j; } else lan_ch = (uchar)jlan; /* restore prev lan chan */ i++; /* i = num lan channels found */ } else if (mtype == 5) { /* serial type*/ if (fdebug) printf("chan[%d] = serial\n",j); ser_ch = (uchar)j; /* set to last serial channel */ } else if (mtype == 7) { /* PCI SMBus */ if (fdebug) printf("chan[%d] = pci_smbus\n",j); } else if (mtype == 12) { /* system interface */ if (fdebug) printf("chan[%d] = system_interface\n",j); } else /* other channel medium types, see IPMI 1.5 Table 6-3 */ if (fdebug) printf("chan[%d] = %d\n",j,mtype); } nlans = i; if (i == 0) return(-2); /* no lan channels found */ if (fdebug) printf("lan_ch detected = %d\n",lan_ch); devnum = FindEthNum(bmcMacAddress); if ( fdebug ) printf("GetBmcEthDevice: channel %d, %s%d\n",lan_ch,ifpattn,devnum); return devnum; } /* * atomac - converts ASCII string to binary MAC address (array). * Accepts input formatted as 11:22:33:44:55:66 or 11-22-33-44-55-66. */ static void atomac(uchar *array, char *instr) { int i,j,n; char *pi; j = 0; pi = instr; n = strlen_(instr); for (i = 0; i <= n; i++) { if (instr[i] == ':') { array[j++] = htoi(pi); pi = &instr[i+1]; } else if (instr[i] == '-') { array[j++] = htoi(pi); pi = &instr[i+1]; } else if (instr[i] == 0) { array[j++] = htoi(pi); } if (j >= MAC_LEN) break; /*safety valve*/ } if (fdebug) printf("atomac: %02x %02x %02x %02x %02x %02x\n", array[0],array[1],array[2],array[3], array[4],array[5]); } /*end atomac()*/ /* file_grep/findmatch no longer used here, see ievents.c */ /* * Get_Mac * This routine finds a MAC address from a given IP address. * Usually for the Alert destination. * It uses ARP cache to do this. */ #ifdef WIN32 static int Get_Mac(uchar *ipadr,uchar *macadr) { DWORD dwRetVal; IPAddr DestIp = 0; IPAddr SrcIp = 0; /* default for src ip */ ULONG MacAddr[2]; /* for 6-byte hardware addresses */ ULONG PhysAddrLen = MAC_LEN; /* default to length of six bytes */ BYTE *bPhysAddr; memcpy(&DestIp, ipadr, 4); /* invoke system ARP query */ dwRetVal = SendARP(DestIp, SrcIp, MacAddr, &PhysAddrLen); if (dwRetVal == NO_ERROR) { /* no error - get the MAC */ bPhysAddr = (BYTE *) & MacAddr; if (PhysAddrLen) { memcpy(macadr, bPhysAddr, MAC_LEN); } else printf("Warning: SendArp completed successfully, but returned length=0\n"); } else if (dwRetVal == ERROR_GEN_FAILURE) { /* MAC not available in this netowork - get gateway MAC */ memcpy(macadr, rggwymac, MAC_LEN); } else { /* other errors */ printf("Error: SendArp failed with error: %d", dwRetVal); switch (dwRetVal) { case ERROR_INVALID_PARAMETER: printf(" (ERROR_INVALID_PARAMETER)\n"); break; case ERROR_INVALID_USER_BUFFER: printf(" (ERROR_INVALID_USER_BUFFER)\n"); break; case ERROR_BAD_NET_NAME: printf(" (ERROR_GEN_FAILURE)\n"); break; case ERROR_BUFFER_OVERFLOW: printf(" (ERROR_BUFFER_OVERFLOW)\n"); break; case ERROR_NOT_FOUND: printf(" (ERROR_NOT_FOUND)\n"); break; default: printf("\n"); break; } return 1; } return 0; } /* end Get_Mac()*/ /*endif WIN32 */ #else /*else Linux */ static int Get_Mac(uchar *ipadr,uchar *macadr) { FILE *fparp; char buff[1024]; /* char arpfile[] = "/proc/net/arp"; */ char alertfile[] = "/tmp/dest.arping"; char arping_cmd[128]; char *pb, *pm, *px; int num, i; int foundit = 0; int ret = 0; char *_ifname; if (strcmp(ifname,"gcm") == 0) _ifname = ifname0; else _ifname = ifname; /* Get a MAC address for a given IP address */ if (ipadr[0] != 0) { /* if valid IP address */ /* make sure the destination is in the arp cache */ sprintf(arping_cmd, "arping -I %s -c 2 %d.%d.%d.%d |grep reply |tail -n1 >%s\n", _ifname,ipadr[0],ipadr[1],ipadr[2],ipadr[3],alertfile); if (fdebug) printf("%s", arping_cmd); i = system(arping_cmd); fparp = fopen(alertfile,"r"); if (fparp == NULL) { fprintf(stdout,"Get_Mac: Cannot open %s, errno = %d\n", alertfile,get_errno()); ret = -1; } else { while (fgets(buff, 1023, fparp)) { /* should only run through loop once */ num = strcspn(buff," \t"); /* skip 1st word ("Unicast") */ i = strspn(&buff[num]," \t"); pb = &buff[num+i]; if (strncmp(pb,"reply",5) == 0) { /* valid output */ /* Find the ip address */ pb += 6 + 5; /* skip "reply from " */ num = strcspn(pb," \t"); pb[num] = 0; if (fdebug) printf("Alert ip=%s\n",pb); /* IP address should already match input param */ /* if (rgdestip[0] == 0) atoip(rgdestip,pb); */ /* Now find the mac address */ pm = strchr(&pb[num+1],'['); if (pm == NULL) pm = &pb[num+2]; /* just in case */ pm++; px = strchr(pm,']'); if (px == NULL) px = pm + 17; /* just in case */ px[0] = 0; if (fdebug) printf("Alert mac=%s\n",pm); foundit = 1; if (!MacIsValid(macadr)) atomac(macadr,pm); break; } } /*end while*/ fclose(fparp); } /*end else file opened*/ } /*endif valid IP */ else ret = -1; if (ret == -1 || foundit == 0) { /* couldn't get it */ if (MacIsValid(rggwymac) && !MacIsValid(rgdestmac)) memcpy(rgdestmac,rggwymac,6); /* get to it from the default gateway */ } return(ret); } /* end Get_Mac()*/ /*end else Linux*/ #endif #ifdef WIN32 /* * Set subnet mask based on current IP address (Windows). */ static int SetSubnetMask() { PMIB_IPADDRTABLE pIPAddrTable; unsigned int i; DWORD dwSize = 0, dwRetVal; LPVOID lpMsgBuf; pIPAddrTable = (MIB_IPADDRTABLE*) malloc( sizeof( MIB_IPADDRTABLE) ); if ( pIPAddrTable ) { // Make an initial call to GetIpAddrTable to get the // necessary size into the dwSize variable if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { free( pIPAddrTable ); pIPAddrTable = (MIB_IPADDRTABLE *) malloc ( dwSize ); } } else printf("Memory allocation failed.\n"); if ( pIPAddrTable ) { // Make a second call to GetIpAddrTable to get the // actual data we want if ( (dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 )) == NO_ERROR ) { for(i = 0; i < pIPAddrTable->dwNumEntries; ++i) { if(memcmp(&(pIPAddrTable->table[i].dwAddr), rgmyip, 4) == 0) { memcpy(rgsubnet, &(pIPAddrTable->table[i].dwMask), 4); free( pIPAddrTable ); return 1; } } } else { if (FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL )) { printf("\tError: %s", lpMsgBuf); } printf("Call to GetIpAddrTable failed.\n"); } } if ( pIPAddrTable ) free( pIPAddrTable ); return 0; } /* * Extract gateway address from routing table (Windows). */ static int SetDefaultGateway() { PMIB_IPFORWARDTABLE pIpForwardTable; DWORD dwRetVal, dwSize; unsigned int nord_mask; unsigned int nord_ip; unsigned int nord_net; unsigned int i; nord_mask = *((unsigned int *)rgsubnet); nord_ip = *((unsigned int *)rgmyip); nord_net = nord_ip & nord_mask; pIpForwardTable = (MIB_IPFORWARDTABLE*) malloc(sizeof(MIB_IPFORWARDTABLE)); if (pIpForwardTable == NULL) { printf("Error allocating memory\n"); return 0; } dwSize = 0; if (GetIpForwardTable(pIpForwardTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { free(pIpForwardTable); pIpForwardTable = (MIB_IPFORWARDTABLE*) malloc(dwSize); if (pIpForwardTable == NULL) { printf("Error allocating memory\n"); return 0; } } /* * Note that the IPv4 addresses returned in * GetIpForwardTable entries are in network byte order */ if ((dwRetVal = GetIpForwardTable(pIpForwardTable, &dwSize, 0)) == NO_ERROR) { for (i = 0; i < (int) pIpForwardTable->dwNumEntries; i++) { unsigned int gwaddr = pIpForwardTable->table[i].dwForwardNextHop; if(nord_net == (gwaddr & nord_mask) && nord_ip != gwaddr) { /* searching for gateways from our network with different address than ours */ memcpy(rggwyip, &gwaddr, 4); return 0; } } free(pIpForwardTable); return 1; } else { printf("\tGetIpForwardTable failed.\n"); free(pIpForwardTable); return 0; } } /*endif WIN32*/ #endif static int ShowChanAcc(uchar bchan) { uchar LanRecord[30]; int ret = 0; ret = GetChanAcc(bchan, 0x40, LanRecord); if (fdebug) printf(" GetChanAcc(%d) ret = %d, data = %02x %02x\n", bchan,ret, LanRecord[0], LanRecord[1]); if (ret == 0) fprintf(fd_bmc,"ChannelAccess %d%c %02x %02x \n", bchan,bdelim,LanRecord[0],LanRecord[1]); return(ret); } static int GetSerialOverLan( uchar chan, uchar bset, uchar block ) { uchar requestData[24]; uchar rData[MAX_BUFFER_SIZE]; int rlen; int status, i; uchar ccode; uchar enable_parm, auth_parm, baud_parm; uchar user; if (fIPMI20 && fSOL20) { getsolcmd = GET_SOL_CONFIG2; enable_parm = SOL_ENABLE_PARAM; auth_parm = SOL_AUTHENTICATION_PARAM; baud_parm = SOL_BAUD_RATE_PARAM; } else { getsolcmd = GET_SOL_CONFIG; enable_parm = SOL_ENABLE_PARAM; auth_parm = SOL_AUTHENTICATION_PARAM; baud_parm = SOL_BAUD_RATE_PARAM; chan = 0; /*override chan for IPMI 1.5*/ } printf("%c## %s, GetSOL for channel %d ...\n",bcomment,progname,chan); requestData[0] = chan; /*channel*/ requestData[1] = enable_parm; requestData[2] = bset; /*set*/ requestData[3] = block; /*block*/ rlen = sizeof(rData); status = ipmi_cmd(getsolcmd, requestData,4, rData, &rlen,&ccode,fdebug); if (status != 0) return(status); if (ccode) { if (ccode == 0xC1) { /* unsupported command */ printf("%c Serial-Over-Lan not available on this platform\n", bcomment); return(status); } else { printf("%c SOL Enable ccode = %x\n",bcomment,ccode); status = ccode; } } else { /*success*/ fprintf(fd_bmc,"SOLParam %d,%d,%d%c",chan,enable_parm,bset,bdelim); for (i = 1; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]); fprintf(fd_bmc,"\n"); } requestData[0] = chan; requestData[1] = auth_parm; requestData[2] = bset; // selector requestData[3] = block; // block rlen = sizeof(rData); status = ipmi_cmd(getsolcmd, requestData,4,rData, &rlen,&ccode,fdebug); if (status != 0) return(status); if (ccode) { printf("%c SOL Auth ccode = %x\n",bcomment,ccode); status = ccode; } else { /*success*/ fprintf(fd_bmc,"SOLParam %d,%d,%d%c",chan,auth_parm,bset,bdelim); for (i = 1; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]); fprintf(fd_bmc,"\n"); } requestData[0] = chan; requestData[1] = SOL_ACC_INTERVAL_PARAM; requestData[2] = bset; requestData[3] = block; rlen = sizeof(rData); status = ipmi_cmd(getsolcmd, requestData,4,rData, &rlen,&ccode,fdebug); if (status != 0) return(status); if (ccode) { printf("%c SOL Accum Interval ccode = %x\n",bcomment,ccode); status = ccode; } else { /*success*/ fprintf(fd_bmc,"SOLParam %d,%d,%d%c",chan,SOL_ACC_INTERVAL_PARAM,bset,bdelim); for (i = 1; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]); fprintf(fd_bmc,"\n"); } requestData[0] = chan; requestData[1] = SOL_RETRY_PARAM; requestData[2] = bset; requestData[3] = block; rlen = sizeof(rData); status = ipmi_cmd(getsolcmd, requestData,4,rData, &rlen,&ccode,fdebug); if (status != 0) return(status); if (ccode) { printf("%c SOL Retry ccode = %x\n",bcomment,ccode); status = ccode; } else { /*success*/ fprintf(fd_bmc,"SOLParam %d,%d,%d%c",chan,SOL_RETRY_PARAM,bset,bdelim); for (i = 1; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]); fprintf(fd_bmc,"\n"); } if (!fRomley) { requestData[0] = chan; requestData[1] = baud_parm; requestData[2] = bset; requestData[3] = block; rlen = sizeof(rData); status = ipmi_cmd(getsolcmd,requestData,4,rData,&rlen,&ccode,fdebug); if (status != 0) return(status); if (ccode) { printf("%c SOL nvol Baud ccode = %x\n",bcomment,ccode); status = ccode; } else { /*success*/ fprintf(fd_bmc,"SOLParam %d,%d,%d%c",chan,baud_parm,bset,bdelim); for (i = 1; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]); fprintf(fd_bmc,"\n"); } requestData[0] = chan; requestData[1] = SOL_VOL_BAUD_RATE_PARAM; /*0x06*/ requestData[2] = bset; requestData[3] = block; rlen = sizeof(rData); status = ipmi_cmd(getsolcmd,requestData,4,rData,&rlen,&ccode,fdebug); if (status != 0) return(status); if (ccode) { printf("%c SOL vol Baud ccode = %x\n",bcomment,ccode); status = ccode; } else { /*success*/ fprintf(fd_bmc,"SOLParam %d,%d,%d%c",chan,SOL_VOL_BAUD_RATE_PARAM,bset,bdelim); for (i = 1; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]); fprintf(fd_bmc,"\n"); } } if (fIPMI20) { requestData[0] = chan; rlen = sizeof(rData); status = ipmi_cmdraw(GET_PAYLOAD_SUPPORT, NETFN_APP, BMC_SA,PUBLIC_BUS,BMC_LUN, requestData,1,rData, &rlen, &ccode, fdebug); if ((status != 0) || (ccode != 0)) { printf("%c SOL Payload Support(%d) error %d, ccode = %x\n", bcomment,chan,status,ccode); if (status == 0) status = ccode; } else { /*success*/ fprintf(fd_bmc,"SOLPayloadSupport %d%c",chan,bdelim); for (i = 1; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]); fprintf(fd_bmc,"\n"); } /* get Payload Access for nusers, not just lan_user */ for (user = 1; user <= nusers; user++) { /* IPMI 2.0 nusers >= 4 users */ requestData[0] = chan; requestData[1] = user; rlen = sizeof(rData); status = ipmi_cmdraw(GET_PAYLOAD_ACCESS, NETFN_APP, BMC_SA,PUBLIC_BUS,BMC_LUN, requestData,2,rData, &rlen, &ccode, fdebug); if ((status != 0) || (ccode != 0)) { printf("%c SOL Payload Access(%d,%d) error %d, ccode = %x\n", bcomment,chan,user,status,ccode); if (status == 0) status = ccode; } else { /*success*/ fprintf(fd_bmc,"SOLPayloadAccess %d,%d%c",chan,user,bdelim); for (i = 0; i < rlen; i++) fprintf(fd_bmc," %02x",rData[i]); fprintf(fd_bmc,"\n"); } } /*end user loop*/ } return(status); } /*end GetSerialOverLan */ static char *PefDesc(int idx, uchar stype) { char *pdesc; if (pefdesc == NULL) pdesc = "reserved"; else pdesc = pefdesc[idx]; if ((stype != 0) && (strcmp(pdesc,"reserved") == 0)) { /* pefdesc may not match on some non-Intel systems. */ /* so use sensor type */ switch(stype) { case 0x01: pdesc = "Temperature"; break; case 0x02: pdesc = "Voltage"; break; case 0x04: pdesc = "Fan"; break; case 0x05: pdesc = "Chassis"; break; case 0x07: pdesc = "BIOS"; break; case 0x08: pdesc = "Power Supply"; break; case 0x09: pdesc = "Power Unit"; break; case 0x0c: pdesc = "Memory"; break; case 0x0f: pdesc = "Boot"; break; case 0x12: pdesc = "System Restart"; break; case 0x13: pdesc = "NMI"; break; case 0x23: pdesc = "Watchdog"; break; case 0x20: pdesc = "OS Critical Stop"; break; default: pdesc = "Other"; break; } } return(pdesc); } static int GetSessionInfo(uchar *rData, int sz) { int rv, rlen; uchar ccode; uchar iData[5]; iData[0] = 0x00; /*get data for this session*/ rlen = sz; rv = ipmi_cmdraw(CMD_GET_SESSION_INFO,NETFN_APP, BMC_SA,PUBLIC_BUS,BMC_LUN, iData,1,rData, &rlen, &ccode, fdebug); if ((rv == 0) && (ccode != 0)) rv = ccode; return(rv); } static int GetPefCapabilities(uchar *bmax) { int rv, rlen; uchar ccode; uchar rData[MAX_BUFFER_SIZE]; rlen = sizeof(rData); rv = ipmi_cmdraw(0x10, NETFN_SEVT, BMC_SA,PUBLIC_BUS,BMC_LUN, NULL,0,rData, &rlen, &ccode, fdebug); if ((rv == 0) && (ccode != 0)) rv = ccode; if ((rv == 0) && (bmax != NULL)) *bmax = rData[2]; /*max num PEF table entries*/ return(rv); } int WaitForSetComplete(int limit) { int rv = 0; int i; uchar bdata[4]; for (i = 0; i < limit; i++) { rv = GetLanEntry(0, 0, bdata); if (fdebug) printf("WaitForSetComplete(%d): i=%d rv=%d val=%x\n", limit,i,rv,bdata[1]); if ((rv == 0) && (bdata[1] == 0)) break; else os_usleep(0,100); } return(rv); } int SerialIsOptional(int bparam) { /* These Serial Parameters are for optional Modem/Callback functions. */ int optvals[9] = { 5, 9, 10, 11, 12, 13, 14, 20, 21 }; int rv = 0; int i; for (i = 0; i < (sizeof(optvals) / sizeof(int)); i++) { if (optvals[i] == bparam) { rv = 1; break; } } return(rv); } static int parse_line(char *line, char *keyret, char *value) { char *eol; char *key; char *val; int i, n; key = &line[0]; eol = &line[strlen(line)]; while( *key < 0x21 && key < eol ) key++; /*remove leading whitespace */ if( key[0] == bcomment ) return 2; /*skip comments */ /* * find the value set, delimited by bdelim (':' or '|') */ val = strchr( line, bdelim ); if( val == NULL ) return 1; /* skip if empty or no delimeter */ val[0] = 0; /*stringify the key*/ val++; while( val[0] < 0x21 && val < eol ) val++; /*remove leading whitespace */ /* * truncate trailing newline/whitespace after last word */ n = strlen_( val ); for( i = n; i >= 0; i-- ) /*decrease from end*/ if( val[i] >= 0x21 ) break; /*found last valid char */ if (i < n) val[i + 1] = 0; strcpy(keyret, key); /*has keyword and params*/ strcpy(value, val); /*has list of hex values*/ return 0; } #ifdef METACOMMAND int i_config(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int ret; PEF_RECORD *pPefRecord; PEF_RECORD PefRecord; uchar LanRecord[64]; uchar bParams[5]; char filename[80] = ""; int i, j, c, n; uchar idx; // char *pstr; uchar bset = 0; int ndest = 4; int idest; // char mystr[80]; uchar * pc; int sz; char line[240]; /* hdr(18) + data(192 = 64 * 3) + '\0' = 211 */ char key[40]; char value[100]; uchar rData[50]; int rlen; uchar cc; uchar chan; char *pk; char fpefok = 1; char fignore_err; // progname = argv[0]; printf("%s ver %s \n",progname,progver); func = 'l'; freadonly = 1; /*list is default*/ while ((c = getopt(argc, argv,"cdmlr:s:xL:T:V:J:EYF:P:N:R:U:Z:?")) != EOF) switch(c) { case 'c': fcanonical = 1; bdelim = BDELIM; break; case 'd': func = 'd'; freadonly = 0; break; /*set Defaults*/ case 'l': func = 'l'; freadonly = 1; break; /*list*/ case 'm': fdomac = 1; break; /*restore mac*/ case 'r': func = 'r'; freadonly = 0; /*restore*/ sz = strlen_(optarg); if (sz > sizeof(filename)) sz = sizeof(filename); strncpy(filename,optarg,sz); break; case 's': func = 's'; freadonly = 1; /*save*/ sz = strlen_(optarg); if (sz > sizeof(filename)) sz = sizeof(filename); strncpy(filename,optarg,sz); break; case 'x': fdebug = 1; break; case 'p': /* password to set */ fpassword = 1; if (strlen_(optarg) > 16) optarg[16] = 0; strcpy(passwordData,optarg); if (fdebug) printf("Password = %s\n",passwordData); /* Hide password from 'ps' */ memset(optarg, ' ', strlen_(optarg)); break; case 'L': lan_ch_parm = atob(optarg); if (lan_ch_parm >= MAXCHAN) lan_ch_parm = 0xff; /*invalid*/ break; case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: printf("Usage: %s [-clmpxLNUPREFTJVY -r -s ]\n", progname); printf("where -l Lists BMC configuration parameters\n"); printf(" -r Restores BMC configuration from \n"); printf(" -s Saves BMC configuration to \n"); printf(" -c canonical output with delimiter '%c'\n",BDELIM); printf(" -m Set BMC MAC during restore\n"); printf(" -x show eXtra debug messages\n"); printf(" -p specify a user password to set\n"); printf(" -L 3 specify lan channel number 3\n"); print_lan_opt_usage(0); ret = ERR_USAGE; goto do_exit; } switch(func) { case 'l': fd_bmc = stdout; break; case 'r': fd_bmc = fopen(filename,"r"); break; case 's': fd_bmc = fopen(filename,"w"); break; default: break; } if (fd_bmc == NULL) { printf("Error: cannot open %s\n",filename); ret = ERR_FILE_OPEN; fd_bmc = stdout; goto do_exit; } fipmilan = is_remote(); if (fipmilan) parse_lan_options('V',"4",0); ret = GetDeviceID( LanRecord); if (ret != 0) { goto do_exit; } else { /* success */ uchar ipmi_maj, ipmi_min; ipmi_maj = LanRecord[4] & 0x0f; ipmi_min = LanRecord[4] >> 4; show_devid( LanRecord[2], LanRecord[3], ipmi_maj, ipmi_min); if (ipmi_maj == 0) fIPMI10 = 1; else if (ipmi_maj == 1 && ipmi_min < 5) fIPMI10 = 1; else fIPMI10 = 0; /* >= IPMI 1.5 is ok */ if (ipmi_maj >= 2) fIPMI20 = 1; /* nusers can be up to 15 max */ if (fIPMI20) nusers = 5; else nusers = 3; if (fIPMI10) { printf("%c This IPMI v%d.%d system does not support PEF records.\n", bcomment,ipmi_maj,ipmi_min); /* Wont handle PEF, but continue and look for BMC LAN anyway */ // fIPMI10 = 1; // ipmi_close_(); // exit(1); } prod_id = LanRecord[9] + (LanRecord[10] << 8); vend_id = LanRecord[6] + (LanRecord[7] << 8) + (LanRecord[8] << 16); /* check Device ID response for Manufacturer ID = 0x0322 (NSC) */ if (vend_id == VENDOR_NSC) { /* NSC = 0x000322 */ fmBMC = 1; /*NSC miniBMC*/ if (pefnum == 12) pefnum = 10; /* change CritStop pefnum to 0x0a */ pefdesc = &pefdesc2[0]; pefmax = 30; fsharedMAC = 1; /*LAN1 shares MAC with OS*/ } else if (vend_id == VENDOR_LMC) { /* LMC (on SuperMicro) = 0x000878 */ fmBMC = 0; pefdesc = NULL; /* unknown, see PefDesc() */ if (pefnum == 12) pefnum = 15; /* change CritStop pefnum */ pefmax = 16; fsharedMAC = 0; /* not-shared BMC LAN port */ } else if (vend_id == VENDOR_INTEL) { /* Intel = 0x000157 */ pefdesc = &pefdesc1[0]; /*Intel defaults*/ pefmax = 20; /*Intel default pefmax = 20*/ switch(prod_id) { case 0x4311: /* Intel NSI2U*/ fmBMC = 1; /* Intel miniBMC*/ if (pefnum == 12) pefnum = 14; /* change CritStop pefnum */ pefdesc = &pefdesc2[0]; pefmax = 30; fsharedMAC = 1; /*LAN1 shares MAC with OS*/ break; case 0x0026: case 0x0028: case 0x0811: /* Alcolu & TIGW1U */ fmBMC = 0; /* Intel Sahalee BMC*/ fsharedMAC = 0; /* not-shared BMC LAN port, separate MAC */ gcm_ch = 3; break; case 0x003E: /*NSN2U or CG2100 Urbanna*/ fiBMC = 1; /* Intel iBMC */ fsharedMAC = 0; /* not-shared BMC LAN port, separate MAC */ set_max_kcs_loops(URNLOOPS); /*longer for SetLan cmds (default 300)*/ break; case 0x0107: /* Intel Caneland*/ fsharedMAC = 0; /* not-shared BMC LAN port, separate MAC */ gcm_ch = 3; break; case 0x0022: /* Intel TIGI2U*/ fsharedMAC = 1; /*LAN1 shares MAC with OS*/ gcm_ch = 3; nusers = 4; break; default: /* else other Intel */ if (fIPMI20) fsharedMAC = 0; /* recent, not-shared BMC MAC */ else fsharedMAC = 1; /* usu IPMI 1.x has shared BMC MAC */ #ifdef TEST /* also check for ia64, and set chan_pefon, chan_pefoff accordingly*/ if (prod_id == 0x0100) { /* Intel Tiger2, Itanium2 */ chan_pefon = CHAN_ACC_PEFON64; chan_pefoff = CHAN_ACC_PEFOFF64; } #endif break; } /*end switch*/ if (is_romley(vend_id,prod_id)) fRomley = 1; if (is_grantley(vend_id,prod_id)) fGrantley = 1; if (fRomley) { fiBMC = 1; /* Intel iBMC */ fsharedMAC = 0; /* not-shared BMC LAN port, separate MAC */ set_max_kcs_loops(URNLOOPS); /*longer for SetLan cmds */ fipv6 = 1; } } else if (vend_id == VENDOR_KONTRON) { //if (prod_id == 0x1590) fchan2wart = 1; /* KTC5520 chan2 wart */ fsharedMAC = 0; /* not-shared BMC MAC */ pefdesc = NULL; /* unknown, see PefDesc() */ if (pefnum == 12) pefnum = 15; /* change CritStop pefnum to 15 */ } else { /* else other vendors */ if (fIPMI20) fsharedMAC = 0; /* recent, not-shared BMC MAC */ else fsharedMAC = 1; /* usu IPMI 1.x has shared BMC MAC */ fmBMC = 0; pefdesc = NULL; /* unknown, see PefDesc() */ if (pefnum == 12) pefnum = 15; /* change CritStop pefnum to 15? */ pefmax = 20; } if (fmBMC) nusers = 1; } ret = GetPefCapabilities(&bset); if ((ret == 0) && (bset <= MAXPEF)) pefmax = bset; /* Get the BMC LAN channel & match it to an OS eth if. */ i = GetBmcEthDevice(lan_ch_parm); if (i == -2) { /* no lan channels */ printf("This system does not support BMC LAN channels.\n"); ret = ERR_NOT_ALLOWED; goto do_exit; } else if (i < 0) { /* mac not found, use platform defaults */ i = 0; /* default to eth0, lan_ch set already. */ if (vend_id == VENDOR_INTEL) { if ((prod_id == 0x001B) || (prod_id == 0x000c)) { /* Intel TIGPR2U or TSRLT2 defaults are special */ if (lan_ch_parm == 6) { i = 0; lan_ch = 6; } else { i = 1; lan_ch = 7; } ser_ch = 1; } } } if ((gcm_ch != 0) && (lan_ch_parm == 0xff)) { /* Has a GCM, and user didn't specify -L */ /* Need this to avoid picking channel 3, the IMM GCM channel. */ lan_ch = 1; /*default BMC LAN channel*/ // i = 1; /*default eth1*/ } if (fsetifn == 0) { if (lan_ch == gcm_ch) strcpy(ifname,"gcm"); else sprintf(ifname,"%s%d",ifpattn,i); } if (fdebug) printf("lan_ch = %d, ifname = %s\n",lan_ch,ifname); /* initialize the correct SOL command values */ if (fIPMI20 && fSOL20) { setsolcmd = SET_SOL_CONFIG2; getsolcmd = GET_SOL_CONFIG2; sol_bchan = lan_ch; } else { setsolcmd = SET_SOL_CONFIG; getsolcmd = GET_SOL_CONFIG; sol_bchan = 0x00; /*override chan for IPMI 1.5*/ } memset(SessInfo,0,sizeof(SessInfo)); ret = GetSessionInfo(SessInfo,sizeof(SessInfo)); // rlen = sizeof(SessInfo)); ret = get_session_info(0,0,SessInfo,&rlen); if (fdebug) printf("GetSessionInfo ret=%d, data: %02x %02x %02x %02x \n", ret,SessInfo[0],SessInfo[1],SessInfo[2],SessInfo[3]); if (!freadonly && fipmilan) { /* setting LAN params, and using IPMI LAN */ if (SessInfo[2] > 1) { /* another session is active also */ printf("Another session is also active, cannot change IPMI LAN settings now.\n"); ret = ERR_NOT_ALLOWED; goto do_exit; } } /* set the lan_user appropriately */ if (freadonly) { if (!fIPMI10) { printf("%c## %s, GetPefEntry ...\n",bcomment,progname); for (idx = 1; idx <= pefmax; idx++) { ret = GetPefEntry( 0x06, (ushort)idx, &PefRecord); if (ret == 0) { // Show the PEF record pc = (uchar *)&PefRecord; sz = 21; // sizeof(PEF_RECORD) = 21 printf("%c PefParam(%d): %s\n",bcomment,idx,PefDesc(idx,pc[7])); fprintf(fd_bmc,"PEFParam %d,%02d%c",6,idx,bdelim); for (i = 0; i < sz; i++) fprintf(fd_bmc," %02x",pc[i]); fprintf(fd_bmc,"\n"); } else { char *pstr; if (ret > 0) pstr = decode_cc(0,(uchar)ret); else pstr = ""; printf("%c GetPefEntry(%d): ret = %d %s\n",bcomment,idx,ret,pstr); if (ret == 0xC1) { fpefok = 0; ndest = 0; break; } } } if (fpefok) { ret = GetPefEntry(0x01, 0,(PEF_RECORD *)&LanRecord); if (ret == 0) { fprintf(fd_bmc,"PEFParam %d%c %02x\n",1,bdelim,LanRecord[0]); } ret = GetPefEntry(0x02, 0,(PEF_RECORD *)&LanRecord); if (ret == 0) { fprintf(fd_bmc,"PEFParam %d%c %02x\n",2,bdelim,LanRecord[0]); } ret = GetPefEntry(0x03, 0,(PEF_RECORD *)&LanRecord); if (ret == 0) fprintf(fd_bmc,"PEFParam %d%c %02x\n", 3,bdelim,LanRecord[0]); if (!fmBMC) { ret = GetPefEntry(0x04, 0,(PEF_RECORD *)&LanRecord); if (ret == 0) fprintf(fd_bmc,"PEFParam %d%c %02x\n",4,bdelim,LanRecord[0]); /* fmBMC gets cc=0x80 here */ } /* note that ndest should be read from lan param 17 below. */ for (i = 1; i <= ndest; i++) { ret = GetPefEntry(0x09, (ushort)i,(PEF_RECORD *)&LanRecord); if (ret == 0) { fprintf(fd_bmc,"PEFParam %d,%d%c %02x %02x %02x %02x \n",9,i,bdelim, LanRecord[0], LanRecord[1],LanRecord[2], LanRecord[3]); } } /*endfor ndest*/ } /*endif fpefok*/ } /*endif not fIPMI10*/ for (chan = lan_ch; chan < MAXCHAN; chan++ ) { if (chan_type[chan] != 4) continue; /*chan != LAN, skip it*/ lan_ch = chan; printf("%c## %s, GetLanEntry for channel %d ...\n",bcomment,progname,lan_ch); idest = 1; for (idx = 0; idx < NLAN; idx++) { int ival; if (idx == 8 || idx == 9) continue; /* not implemented */ ival = lanparams[idx].cmd; if (ival >= 96 && ival <= 98) continue; /* not implemented */ if (ival >= 102 && ival <= 108) { /*custom IPv6 parameters*/ if (fipv6 == 0) continue; /*skip these*/ } if (ival == 194 && vend_id == VENDOR_KONTRON) { /*oem hostname parm*/ lanparams[idx].sz = 36; strcpy(lanparams[idx].desc,"IPMI Hostname"); } else if (ival >= 192 && ival <= 194) { /*custom DHCP parameters*/ if (vend_id != VENDOR_INTEL) continue; if (fmBMC || fiBMC || fRomley || fcanonical) continue; /*skip*/ } /* VLAN params 20-25, fIPMI20 only*/ if (ival >= 20 && ival <= 25) { if (!fIPMI20) continue; } if (ival == 11) { /*grat arp interval*/ if (vend_id == VENDOR_SUPERMICROX) continue; if (vend_id == VENDOR_SUPERMICRO) continue; } if (ival == 14 || ival == 15) { /*secondary gateway is optional*/ if (vend_id == VENDOR_KONTRON) continue; } if (ival == 201) { /*Get Channel Access*/ ret = ShowChanAcc(lan_ch); } else { if (ival == 18 || ival == 19) { /*dest params*/ if (ndest == 0) continue; /*skip if none*/ bset = (uchar)idest; /* dest id = 1 thru n */ } else bset = 0; ret = GetLanEntry((uchar)ival, bset, LanRecord); } if (ret == 0) { // Show the LAN record pc = (uchar *)&LanRecord; sz = lanparams[idx].sz; if (ival == 201) ; /* ShowChanAcc(lan_ch) above */ else { fprintf(fd_bmc,"LanParam %d,%d,%d%c ",lan_ch,ival,bset,bdelim); for (i = 0; i < sz; i++) fprintf(fd_bmc," %02x",pc[i]); fprintf(fd_bmc,"\n"); if (ival == 3) printf("%c LanParam(%d,%d,%d) IP address: %d.%d.%d.%d\n", bcomment, lan_ch,ival,bset, pc[0], pc[1], pc[2], pc[3]); } if (ival == 1) { authmask = pc[0]; /* auth type support mask */ /* if (fmBMC) authmask is usually 0x15, else 0x14 */ } else if (ival == 3) { if (IpIsValid(pc)) memcpy(bmcmyip,pc,4); } else if (ival == 5) { if (MacIsValid(pc)) memcpy(bmcmymac,pc,MAC_LEN); } else if (ival == 17) { /* num dest */ ndest = pc[0]; /* save the number of destinations */ } else if (ival == 19) { /* dest addr */ if (IpIsValid(&pc[3])) memcpy(bmcdestip,&pc[3],4); } if (ival == 18 || ival == 19) { if (idest < ndest) { idest++; idx--; /* repeat this param*/ } else idest = 1; } } else { /* ret != 0 */ if (ival >= 20 && ival <= 25) ; else printf("%c GetLanEntry(%d,%d,%d), ret = %d\n",bcomment,lan_ch,ival,bset,ret); if (ival == 17) ndest = 0; /*error getting num dest*/ } } /*end for NLAN*/ if (!fIPMI10) { /* Get SOL params */ ret = GetSerialOverLan(lan_ch,0,0); if (ret != 0) printf("%c GetSOL error %d\n",bcomment,ret); } for (idx = 1; idx <= nusers; idx++) GetUser(idx); if (lan_ch_parm != 0xff) chan = MAXCHAN; } /*end-for chan*/ printf("%c## %s, GetSerEntry for channel %d ...\n",bcomment,progname,ser_ch); if (fmBMC || (ser_ch == 0)) { /* mBMC doesn't support serial */ printf("%cNo serial channel support on this platform\n", bcomment); } else { idest = 1; for (idx = 0; idx < NSER; idx++) { int ival; // if (idx == 9) continue; /* not implemented */ ival = serparams[idx].cmd; if (vend_id == VENDOR_SUPERMICRO && ival == 8) continue; if (ival == 201) { j = ShowChanAcc(ser_ch); } else { if (ival == 17 || ival == 19 || ival == 21 || ival == 23) bset = (uchar)idest; else bset = 0; /*default*/ ret = GetSerEntry((uchar)ival, bset, LanRecord); if (ret == 0) { // Show the SER record pc = (uchar *)&LanRecord; sz = serparams[idx].sz; fprintf(fd_bmc,"SerialParam %d,%d,%d%c", ser_ch,ival,bset,bdelim); for (i = 0; i < sz; i++) fprintf(fd_bmc," %02x",pc[i]); /* show in hex */ fprintf(fd_bmc,"\n"); if (ival == 16) ndest = pc[0]; } else { /*ret != 0, error*/ char *pstr; char *tag; if (SerialIsOptional(ival)) tag = "Optional"; else tag = ""; if (ret > 0) pstr = decode_cc(0,ret); else pstr = ""; printf("%c GetSerEntry(%d,%d): %s ret = %d %s\n", bcomment,ser_ch,ival,tag,ret,pstr); if (ival == 16) ndest = 0; if (ret == 0xC1) { ret = 0; break; /*not supported, exit for loop*/ } } } if (ival == 17 || ival == 19 || ival == 21 || ival == 23) { if (idest < ndest) { idest++; idx--; /* repeat this param*/ } else idest = 1; } } /*end for NSER*/ lan_ch_sav = lan_ch; lan_ch = ser_ch; /* use ser_ch for User functions now */ for (idx = 1; idx <= nusers; idx++) GetUser(idx); lan_ch = lan_ch_sav; } /*endif serial*/ printf("%c## %s, GetSystemParams ...\n",bcomment,progname); for (idx = 0; idx < NSYS; idx++) { /*Get System Params*/ switch(idx) { case 0: j = CHAS_RESTORE; bset = 0; break; case 1: j = SYS_INFO; bset = 1; break; case 2: j = SYS_INFO; bset = 2; break; case 3: j = SYS_INFO; bset = 3; break; case 4: j = SYS_INFO; bset = 4; break; case 5: default: j = LAN_FAILOVER; bset = 0; break; } fignore_err = 0; pc = (uchar *)&LanRecord; switch(j) { case CHAS_RESTORE: /* Chassis Status, Power Restore Policy */ sz = 0; rlen = sizeof(rData); ret = ipmi_cmdraw(CHASSIS_STATUS, NETFN_CHAS, BMC_SA,PUBLIC_BUS,BMC_LUN, pc,0,rData,&rlen,&cc,fdebug); if (ret == 0 && cc != 0) ret = cc; if (ret == 0) { sz = rlen; memcpy(pc,&rData,sz); /*should be 3 bytes*/ } break; case SYS_INFO: /* System Info */ if (! fIPMI20) continue; /*skip if not IPMI 2.0*/ rlen = sizeof(LanRecord); /* param from read */ ret = get_system_info(bset,LanRecord,&rlen); /* find actual string size (ends at first 0x00) */ for (i=0; i 0) pstr = decode_cc(0,ret); else pstr = ""; if (fdebug || !fignore_err) printf("%c GetSystemParam(%d,%d): ret = %d %s\n", bcomment,j,bset,ret,pstr); if (fignore_err) ret = 0; } } /*end-for System Params*/ } /*endif readonly*/ if (!freadonly) /* Set parameters via Restore */ { if (fipmilan) { /* Sets not valid via ipmi_lan if same channel. */ printf("\nWarning: Setting LAN %d params while using a LAN channel.\n", lan_ch); } GetUser(1); /*sets num enabled_users */ /* Set BMC parameters. (restore) */ /* read each record from the file */ while ( fgets( line, sizeof(line), fd_bmc) != NULL ) { ret = parse_line(line, key, value); if (ret != 0) { if (ret == 2) ret = 0; /*just skip comment*/ else if (fdebug) printf("parse error on line: %s\n",line); continue; } /* get parameters from key */ sz = sizeof(bParams); memset(bParams,0,sz); pk = strchr(key,' '); /*skip keyword, to first param*/ if (pk == NULL) { pk = &key[0]; } for (n=0; n= 22 && idx <= 24) continue; /*read-only Cipher*/ else if (idx >= 20 && idx <= 25) { /*VLAN*/ if (!fIPMI20) continue; } if (idx == 18) j--; /*one less byte for Set than from Get*/ lan_ch = chan; if (idx == 3) { /* 3 = IP address */ uchar bdata[2]; bdata[0] = 0x00; /*disable grat arp while setting IP*/ ret = SetLanEntry(10, &bdata[0], 1); if (fdebug) printf("SetLanEntry(%d,10,0), ret = %d\n",chan,ret); WaitForSetComplete(4); /*wait if it is a slow MC */ bdata[0] = SRC_STATIC; /*set src to static before setting IP*/ ret = SetLanEntry(4, &bdata[0], 1); if (fdebug) printf("SetLanEntry(%d,4,0), ret = %d\n",chan,ret); WaitForSetComplete(4); /*wait if it is a slow MC */ } else if ((idx == 6) || (idx == 12)) WaitForSetComplete(4); ret = SetLanEntry(idx, LanRecord, j); if ((ret != 0) && (idx >= 20 && idx <= 25)) ; /*VLAN optional*/ else { printf("SetLanEntry(%d,%d), ret = %d\n",chan,idx,ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } else if (strncasecmp(key,"PEFParam",8) == 0) { if (fpefok == 0) continue; idx = bParams[0]; bset = bParams[1]; if (idx == 6) { /*PEF table rules*/ pPefRecord = (PEF_RECORD *)&LanRecord[0]; if (pPefRecord->fconfig == 0xC0) { pPefRecord->fconfig = 0x80; /* enabled, software */ ret = SetPefEntry(pPefRecord); if (fdebug) printf("SetPefEntry(%d,%d/80) ret = %d\n",idx,bset,ret); pPefRecord->fconfig = 0xC0; } ret = SetPefEntry(pPefRecord); printf("SetPefEntry(%d,%d) ret = %d\n",idx,bset,ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } else { pc = (uchar *)&PefRecord; pc[0] = idx; for (i=0; i 1) && (ret != 0)); /*9=PEF Policy*/ else { printf("SetPefEntry(%d,%d) ret = %d\n",idx,bset,ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } if (ret == 0xC1) { fpefok = 0; ndest = 0; } } else if (strncasecmp(key,"SerialParam",11) == 0) { if (idx == 0) continue; /*skip Set in progress*/ if (idx == 1 || idx == 16) continue; /*read-only param*/ if (vend_id == VENDOR_PEPPERCON) { if ((idx >= 3) && (idx <= 6)) continue; } if ((vend_id == VENDOR_SUPERMICROX) || (vend_id == VENDOR_SUPERMICRO)) { if (idx == 3) continue; if ((idx >= 6) && (idx <= 8)) continue; if (idx == 29) continue; } if (fmBMC || (ser_ch == 0)) continue; /*doesn't support serial*/ ser_ch = chan; ret = SetSerEntry(idx, LanRecord, j); if ((ret != 0) && SerialIsOptional(idx)) ; /*ignore errors if opt*/ else { printf("SetSerEntry(%d,%d,%d), ret = %d\n",chan,idx,bset,ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } else if (strncasecmp(key,"ChannelAccess",13) == 0) { if (((vend_id == VENDOR_SUPERMICROX) || (vend_id == VENDOR_SUPERMICRO)) && chan == 3) ; /*skip serial*/ else { ret = SetChanAcc(chan, 0x80, LanRecord[0], LanRecord[1]); if (fdebug) printf("SetChanAcc(%d/active), ret = %d\n",chan,ret); ret = SetChanAcc(chan, 0x40, LanRecord[0], LanRecord[1]); printf("SetChanAcc(%d), ret = %d\n",chan,ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } else if (strncasecmp(key,"UserName",8) == 0) { if (fchan2wart && (lan_ch == 2)) continue; idx = bParams[0]; if (idx <= 1) ; /*skip if anonymous user 1*/ else if (idx == 2 && vend_id == VENDOR_SUPERMICROX) ; /*skip user2*/ else if (idx == 2 && vend_id == VENDOR_SUPERMICRO) ; /*skip user2*/ else { pc = (uchar *)&PefRecord; pc[0] = idx; /*user num*/ memcpy(&pc[1],&LanRecord[0],16); rlen = sizeof(rData); ret = ipmi_cmd(SET_USER_NAME,pc,17, rData,&rlen, &cc,fdebug); if (ret == 0 && cc != 0) ret = cc; if (ret == 0xCC) ; /*SetUserName matching previous gives this*/ else { printf("SetUserName(%d) ret = %d\n",idx,ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } if (fpassword) { pc = (uchar *)&PefRecord; pc[0] = idx; /*user num*/ pc[1] = 0x02; /*set password*/ memset(&pc[2],0, PSW_LEN); strcpy(&pc[2],passwordData); rlen = sizeof(rData); ret = ipmi_cmd(SET_USER_PASSWORD,pc,2+PSW_LEN,rData,&rlen, &cc,fdebug); printf("SetUserPassword(%d) ret = %d\n",idx,ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } else if (strncasecmp(key,"UserPassword",12) == 0) { if (fchan2wart && (lan_ch == 2)) continue; idx = bParams[0]; pc = (uchar *)&PefRecord; pc[0] = idx; /*user num*/ pc[1] = 0x02; /*set password*/ memset(&pc[2],0,PSW_LEN); strcpy(&pc[2],passwordData); rlen = sizeof(rData); ret = ipmi_cmd(SET_USER_PASSWORD,pc,2+PSW_LEN,rData,&rlen, &cc,fdebug); printf("SetUserPassword(%d) ret = %d\n",idx,ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } else if (strncasecmp(key,"UserAccess",10) == 0) { if ((idx > enabled_users) && ((LanRecord[3] & 0x10) == 0)) continue; if (vend_id == VENDOR_KONTRON) { if (idx == 1) continue; if (idx > enabled_users) continue; } if (ipmi_reserved_user(vend_id,idx) == 1) continue; if (fchan2wart && (lan_ch == 2)) continue; pc = (uchar *)&PefRecord;; pc[0] = 0x80 | (LanRecord[3] & 0x70) | chan; /*User Channel Access*/ pc[1] = idx; /*user id*/ pc[2] = (LanRecord[3] & 0x0F); /*User Privilege (Admin,User,Oper)*/ pc[3] = 0x00; /* User Session Limit, 0=not limited*/ rlen = sizeof(rData); ret = ipmi_cmd(SET_USER_ACCESS,pc,4, rData,&rlen, &cc,fdebug); if (ret == 0 && cc != 0) ret = cc; if (ret != 0xCC) { /*if invalid user, ignore errors*/ printf("SetUserAccess (%x %x %x %x) ret = %d\n", pc[0],pc[1],pc[2],pc[3],ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } if ((LanRecord[3] & 0x0f) != 0x0F) { /*not NoAccess, enable user*/ if (idx > last_user_enable) last_user_enable = idx; pc[0] = idx; /*user number, 1=null_user */ pc[1] = 0x01; /*enable user*/ rlen = sizeof(rData); ret = ipmi_cmd(SET_USER_PASSWORD,pc,2, rData,&rlen, &cc,fdebug); if (ret == 0 && cc != 0) ret = cc; printf("SetUserEnable (%x %x) ret = %d\n",pc[0],pc[1],ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } else if (strncasecmp(key,"SOLParam",8) == 0) { if (fchan2wart && (chan == 2)) continue; pc = (uchar *)&PefRecord;; pc[0] = chan; pc[1] = idx; /*sol parameter number*/ memcpy(&pc[2],&LanRecord,j); rlen = sizeof(rData); ret = ipmi_cmd(setsolcmd, pc, j+2, rData,&rlen, &cc,fdebug); if (ret == 0 && cc != 0) ret = cc; printf("SetSOLParam (%d,%d) ret = %d\n",chan,idx,ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } else if (strncasecmp(key,"SOLPayloadSupport",17) == 0) { ; /* Nothing to do, this is a read-only parameter */ } else if (strncasecmp(key,"SOLPayloadAccess",16) == 0) { if (fIPMI20) { if (ipmi_reserved_user(vend_id,idx) == 1) continue; pc = (uchar *)&PefRecord;; pc[0] = chan; pc[1] = idx; // lan_user memcpy(&pc[2],&LanRecord,j); rlen = sizeof(rData); ret = ipmi_cmdraw(SET_PAYLOAD_ACCESS,NETFN_APP, BMC_SA,PUBLIC_BUS,BMC_LUN, pc,j+2,rData,&rlen,&cc,fdebug); if (ret == 0 && cc != 0) ret = cc; printf("SetSOLPayloadAccess (%d,%d) ret = %d\n", chan,idx,ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } else if (strncasecmp(key,"SystemParam",11) == 0) { idx = bParams[0]; bset = bParams[1]; switch(idx) { case CHAS_RESTORE: /* Chassis Power Restore Policy*/ if (vend_id == VENDOR_KONTRON) continue; /*N/A, cannot set it*/ pc = (uchar *)&PefRecord;; i = (LanRecord[0] & 0x60); /*restore policy bits*/ if (i & 0x20) pc[0] = 0x01; /*last_state*/ else if (i & 0x40) pc[0] = 0x02; /*turn_on*/ else pc[0] = 0x00; /*stay_off*/ rlen = sizeof(rData); ret = ipmi_cmdraw(0x06 , NETFN_CHAS, BMC_SA,PUBLIC_BUS,BMC_LUN, pc,1,rData,&rlen,&cc,fdebug); if (ret == 0 && cc != 0) ret = cc; break; case SYS_INFO: /* System Info */ if (! fIPMI20) continue; /*skip if not IPMI 2.0*/ /* j = #bytes read into LanRecord */ ret = set_system_info(bset,(char *)LanRecord,j); break; case LAN_FAILOVER: /* Intel LAN Failover */ if (is_romley(vend_id,prod_id)) ret = lan_failover_intel(LanRecord[0],(uchar *)&i); else if ((vend_id == VENDOR_SUPERMICROX) || (vend_id == VENDOR_SUPERMICRO)) { ret = oem_supermicro_set_lan_port(LanRecord[0]); if (fdebug) printf("SMC set_lan_port(%d) = %d\n",LanRecord[0],ret); } else continue; /*skip if not Intel Romley*/ break; default: ret = LAN_ERR_NOTSUPPORT; } printf("SetSystemParam(%d,%d) ret = %d\n",idx,bset,ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } /*end-else*/ } /*end-while*/ /* Disable any users not enabled above */ for (i = last_user_enable+1; i < max_users; i++) { pc[0] = (uchar)i; /*user number, 1=null_user */ pc[1] = 0x00; /*disable user*/ rlen = sizeof(rData); ret = ipmi_cmd(SET_USER_PASSWORD,pc,2, rData,&rlen, &cc,fdebug); if (ret == 0 && cc != 0) ret = cc; printf("SetUserEnable (%x %x) ret = %d\n",pc[0],pc[1],ret); if (ret != 0) { nerrs++; lasterr = ret; } else ngood++; } } /*endif not readonly*/ do_exit: if (fd_bmc != stdout) fclose(fd_bmc); ipmi_close_(); if (nerrs > 0) { printf("Warning: %d ok, %d errors occurred, last error = %d\n",ngood,nerrs,lasterr); ret = lasterr; } // show_outcome(progname,ret); return(ret); } /* end main()*/ /* end iconfig.c */ ipmiutil-3.1.5/util/getopt.h-win320000644000076400007640000000340113566765324017044 0ustar mgportalloggers/* * getopt.h * * 07/13/07 ARCress - created. * Copyright (c) 2007 Andy Cress BSD-3-clause 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 Kontron, 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. */ #ifndef _GETOPT_H_ #define _GETOPT_H_ extern int getopt(int argc, char **argv, char *opts); extern int optind; extern int optopt; extern int opterr; extern char *optarg; #endif ipmiutil-3.1.5/util/ipmi_sample.c0000644000076400007640000002425313566765324017104 0ustar mgportalloggers/* * ipmi_sample.c * * A sample IPMI utility, to which more commands can be added. * * 02/27/06 Andy Cress - created * 02/25/11 Andy Cress - added get_chassis_status */ /*M* Copyright (c) 2007, 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 Kontron America, Inc. 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*/ #ifdef WIN32 #include #include #include "getopt.h" #else #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include #include "ipmicmd.h" #ifdef GET_SENSORS /* need to also include isensor.o, ievents.o when linking. */ #include "isensor.h" #endif #ifdef GET_FRU #include "ifru.h" #endif /* * Global variables */ static char * progname = "ipmi_sample"; static char * progver = "1.2"; static char fdebug = 0; static char fset_mc = 0; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static char *mytag = NULL; static char *sdrfile = NULL; static int get_chassis_status(uchar *rdata, int rlen) { uchar idata[4]; uchar ccode; int ret; ret = ipmi_cmdraw( CHASSIS_STATUS, NETFN_CHAS, g_sa,g_bus,g_lun, idata,0, rdata,&rlen,&ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; return(ret); } /*end get_chassis_status()*/ #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) { int ret = 0; char c; uchar devrec[16]; uchar chstatus[4]; char *s1; int loops = 1; int nsec = 10; char *nodefile = NULL; int done = 0; FILE *fp = NULL; char nod[40]; char usr[24]; char psw[24]; char drvtyp[10]; char biosstr[40]; int n; #ifdef GET_SENSORS uchar *sdrlist; #endif printf("%s ver %s\n", progname,progver); while ((c = getopt( argc, argv,"i:l:m:p:f:s:t:xEF:N:P:R:T:U:V:YZ:?")) != EOF ) switch(c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } fset_mc = 1; ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'f': nodefile = optarg; break; /* specific sensor tag */ case 'l': loops = atoi(optarg); break; case 'i': nsec = atoi(optarg); break; /*interval in sec*/ case 's': sdrfile = optarg; break; case 't': mytag = optarg; break; /* specific sensor tag */ case 'x': fdebug = 1; break; /* debug messages */ case 'p': /* port */ 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 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); if (c == 'F') strncpy(drvtyp,optarg,sizeof(drvtyp)); break; default: printf("Usage: %s [-filmstx -NUPREFTVY]\n", progname); printf(" where -x show eXtra debug messages\n"); printf(" -f File use list of remote nodes from File\n"); printf(" -i 10 interval for each loop in seconds\n"); printf(" -l 10 loops sensor readings 10 times\n"); printf(" -m002000 specific MC (bus 00,sa 20,lun 00)\n"); printf(" -s File loads SDRs from File\n"); printf(" -t tag search for 'tag' in SDRs\n"); print_lan_opt_usage(1); exit(1); } /* Rather than parse_lan_options above, the set_lan_options function * could be used if the program already knows the nodename, etc. */ ret = get_BiosVersion(biosstr); if (ret == 0) printf("BIOS Version: %s\n",biosstr); while(!done) { if (nodefile != NULL) { /* This will loop for each node in the file if -f was used. * The file should contain one line per node: * node1 user1 password1 * node2 user2 password2 */ if (fp == NULL) { fp = fopen(nodefile,"r"); if (fp == NULL) { printf("Cannot open file %s\n",nodefile); ret = ERR_FILE_OPEN; goto do_exit; } if (fdebug) printf("opened file %s ok\n",nodefile); } n = fscanf(fp,"%s %s %s", nod, usr, psw); if (fdebug) printf("fscanf returned %d \n",n); if (n == EOF || n <= 0) { fclose(fp); done = 1; goto do_exit; } printf("Using -N %s -U %s -P %s ...\n",nod,usr,psw); if (n > 0) parse_lan_options('N',nod,0); if (n > 1) parse_lan_options('U',usr,0); if (n > 2) parse_lan_options('P',psw,0); if (drvtyp != NULL) parse_lan_options('F',drvtyp,0); } ret = ipmi_getdeviceid(devrec,16,fdebug); if (ret != 0) { printf("Cannot do ipmi_getdeviceid, ret = %d\n",ret); goto do_exit; } else { /*success*/ uchar ipmi_maj, ipmi_min; ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); } ret = get_chassis_status(chstatus,4); if (ret == 0) { if (chstatus[0] & 0x01) s1 = "on"; else s1 = "off"; printf("Chassis Status = %02x (%s)\n",chstatus[0],s1); } #ifdef GET_FRU { uchar *fru_data = NULL; printf("Getting FRU ...\n"); ret = load_fru(0x20,0,0x07, &fru_data); if (ret == 0) ret = show_fru(0x20,0,0x07,fru_data); if (fru_data != NULL) free_fru(fru_data); } #endif #ifdef GET_SENSORS printf("Getting SDRs ...\n"); if (sdrfile != NULL) { ret = get_sdr_file(sdrfile,&sdrlist); } else { ret = get_sdr_cache(&sdrlist); } printf("get_sdr_cache ret = %d\n",ret); if (ret == 0) { uchar sdrbuf[SDR_SZ]; uchar reading[4]; uchar snum = 0; ushort id; double val; char *typestr; char tag[17]; int j; for (j = 0; j < loops; j++) { if (j > 0) { printf("loop %d: wait %d seconds ...\n",j,nsec); os_usleep(nsec,0); /*sleep 5 sec between loops*/ } id = 0; /* Get sensor readings for all full SDRs */ while(find_sdr_next(sdrbuf,sdrlist,id) == 0) { id = sdrbuf[0] + (sdrbuf[1] << 8); /*this SDR id*/ if (sdrbuf[3] != 0x01) continue; /*only type 1 full SDRs*/ strncpy(tag,&sdrbuf[48],16); tag[16] = 0; snum = sdrbuf[7]; ret = GetSensorReading(snum, sdrbuf, reading); if (ret == 0) { val = RawToFloat(reading[0], sdrbuf); typestr = get_unit_type( sdrbuf[20], sdrbuf[21], sdrbuf[22],0); } else { val = 0; typestr = "na"; printf("%04x: get sensor %x reading ret = %d\n",id,snum,ret); } printf("%04x: sensor %x %s \treading = %.2f %s\n", id,snum,tag,val,typestr); memset(sdrbuf,0,SDR_SZ); } /*end while*/ } /*end for(loops) */ /* Find a specific sensor by its tag and get a reading */ if (mytag != NULL) { /* see option -t, mytag = "System"; or "System Temp" */ memset(sdrbuf,0,SDR_SZ); ret = find_sdr_by_tag(sdrbuf, sdrlist, mytag, fdebug); printf("find_sdr_by_tag(%s) ret = %d\n",mytag,ret); strncpy(tag,&sdrbuf[48],16); /*assume full sdr tag offset*/ tag[16] = 0; snum = sdrbuf[7]; ret = GetSensorReading(snum, sdrbuf, reading); printf("get sensor %x reading ret = %d\n",snum,ret); if (sdrbuf[3] == 0x01) { /*full SDR*/ if (ret == 0) { val = RawToFloat(reading[0], sdrbuf); typestr = get_unit_type(sdrbuf[20],sdrbuf[21],sdrbuf[22],0); } else { val = 0; typestr = "na"; } printf("sensor %x %s reading = %.2f %s\n",snum,tag,val,typestr); } else printf("sensor %x type %x reading = %02x\n", snum,sdrbuf[3],reading[2]); } free_sdr_cache(sdrlist); } /*endif sdr_cache is valid*/ #endif ipmi_close_(); if (nodefile == NULL) done = 1; } /*end while not done */ do_exit: show_outcome(progname,ret); exit (ret); } /* end main()*/ /* end ipmi_sample.c */ ipmiutil-3.1.5/util/ipmi_port.c0000644000076400007640000000724113566765324016605 0ustar mgportalloggers/* * ipmi_port.c * Allocate the RMCP port (623.) with a bind so that port manager * does not try to reuse it. Only needed for Linux. * * Note that the Intel dpcproxy service also uses port 623 to listen * for incoming telnet/SOL clients, so we should not start ipmi_port * if dpcproxy is running. * * Changes: * 05/18/07 Andy Cress - created */ #include #include #include #include #include #include #include #include #include #ifdef TEST #include "ipmicmd.h" #endif #define RMCP_PORT 623 static char * progver = "1.4"; /* program version */ static char *progname = "ipmi_port"; /* program name */ static int sockfd = 0; static struct sockaddr_in _srcaddr; static int interval = 20; /* num sec to wait, was 60 */ static char fdebug = 0; static int mkdaemon(int fchdir, int fclose); static int mkdaemon(int fchdir, int fclose) { int fdlimit = sysconf(_SC_OPEN_MAX); /*fdlimit usu = 1024.*/ int fd = 0; int i; fdlimit = fileno(stderr); switch (fork()) { case 0: break; case -1: return -1; default: _exit(0); /* exit the original process */ } if (setsid() < 0) return -1; /* shouldn't fail */ switch (fork()) { case 0: break; case -1: return -1; default: _exit(0); } if (fchdir) i = chdir("/"); if (fclose) { /* Close stdin,stdout,stderr and replace them with /dev/null */ for (fd = 0; fd < fdlimit; fd++) close(fd); fd = open("/dev/null",O_RDWR); i = dup(0); i = dup(0); } return 0; } static int open_rmcp_port(int port); static int open_rmcp_port(int port) { int rv; /* Open a socket binding to the RMCP port */ rv = socket(AF_INET, SOCK_DGRAM, 0); if (rv < 0) return (rv); else sockfd = rv; memset(&_srcaddr, 0, sizeof(_srcaddr)); _srcaddr.sin_family = AF_INET; _srcaddr.sin_port = htons(port); _srcaddr.sin_addr.s_addr = htonl(INADDR_ANY); rv = bind(sockfd, (struct sockaddr *)&_srcaddr, sizeof(_srcaddr)); if (rv < 0) { printf("bind(%d,%d) error, rv = %d\n",port,INADDR_ANY,rv); close(sockfd); return (rv); } return(rv); } static void iport_cleanup(int sig) { if (sockfd != 0) close(sockfd); exit(EXIT_SUCCESS); } /*int ipmi_port(int argc, char **argv) */ int main(int argc, char **argv) { int rv; int c; int background = 0; struct sigaction sact; while ((c = getopt(argc, argv, "bx?")) != EOF) { switch (c) { case 'x': fdebug = 1; break; case 'b': background = 1; break; default: printf("Usage: %s [-xb] (-b means background)\n",progname); exit(1); } } if (!background) printf("%s ver %s\n", progname,progver); rv = open_rmcp_port(RMCP_PORT); if (rv != 0) { printf("open_rmcp_port(%d) failed, rv = %d\n",RMCP_PORT,rv); exit(1); } else if (!background) printf("open_rmcp_port(%d) succeeded, sleeping\n",RMCP_PORT); /* convert to a daemon if background */ if (background) { rv = mkdaemon(1,1); if (rv != 0) { printf("%s: Cannot become daemon, rv = %d\n", progname,rv); exit(1); } } /* handle signals for cleanup */ sact.sa_handler = iport_cleanup; sact.sa_flags = 0; sigemptyset(&sact.sa_mask); sigaction(SIGINT, &sact, NULL); sigaction(SIGQUIT, &sact, NULL); sigaction(SIGTERM, &sact, NULL); if (rv == 0) while(1) { sleep(interval); /*wait 60 seconds*/ } if (sockfd != 0) close(sockfd); return(rv); } /*end ipmi_port.c */ ipmiutil-3.1.5/util/ipmilanplus.c0000644000076400007640000006322413566765324017143 0ustar mgportalloggers/* * ipmilanplus.c * * Interface to call libintf_lanplus from ipmitool to do RMCP+ protocol. * * 01/09/07 Andy Cress - created * 02/22/07 Andy Cress - initialize cipher_suite to 3 (was 0) */ #include #include #include #include #if defined(LINUX) || defined(BSD) || defined(MACOS) #include #endif // #define DEBUG 1 int verbose = 0; char fdbglog = 0; #ifndef HAVE_LANPLUS #ifdef WIN32 #include extern int strncasecmp(char *s1, char *s2, int n); /*ipmicmd.c*/ #define snprintf _snprintf #define SockType SOCKET #else #define SockType int #endif /* No lanplus, so stub these functions returning errors. */ #define uchar unsigned char #define ushort unsigned short #define LAN_ERR_INVPARAM -8 #define LOG_MSG_LENGTH 1024 /*usu. ipmicmd.h*/ struct valstr { /*usually in ipmicmd.h*/ ushort val; char * str; }; struct oemvalstr { unsigned int oem; ushort val; const char * str; }; int ipmi_open_lan2(char *node, char *user, char *pswd, int fdebugcmd) { if (fdebugcmd) verbose = 1; return(LAN_ERR_INVPARAM); } int ipmi_close_lan2(char *node) { return(LAN_ERR_INVPARAM); } int ipmi_cmdraw_lan2(char *node, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { printf("lanplus not configured\n"); return(LAN_ERR_INVPARAM); } int ipmi_cmd_lan2(char *node, ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { return(LAN_ERR_INVPARAM); } int lan2_send_sol( uchar *payload, int len, void *rsp) { return(LAN_ERR_INVPARAM); } int lan2_recv_sol( void *rsp ) { return(LAN_ERR_INVPARAM); } int lan2_keepalive(int type, void *rsp) { return(LAN_ERR_INVPARAM); } void lan2_recv_handler( void *rs ) { return; } void lan2_set_sol_data(int insize, int outsize, int port, void *handler, char esc_char) { return; } SockType lan2_get_fd(void) { return(1); } void lanplus_set_recvdelay( int delay ) { return; } long lan2_get_latency( void ) { return(1); } int lan2_send_break( void *rsp) { return(LAN_ERR_INVPARAM); } int lan2_send_ctlaltdel( void *rsp) { return(LAN_ERR_INVPARAM); } #else /* else HAVE_LANPLUS is defined */ #include "ipmilanplus.h" #include "ipmicmd.h" void set_loglevel(int level); /*defined in subs.c*/ void lprintf(int level, const char * format, ...); // #define LOG_WARN 4 // #define LOG_INFO 6 #ifdef METACOMMAND extern void dbglog( char *pattn, ... ); /*from isolconsole.c*/ extern void sol_output_handler(void *rsp); /*from isolconsole.c*/ extern void dbg_dump(char *tag, uchar *pdata, int len, int fascii); #else static void dbglog( char *pattn, ... ) { return; } static void sol_output_handler(void *rsp) { return; } static void dbg_dump(char *tag, uchar *pdata, int len, int fascii) { return; } #endif int ipmi_close_lan2(char *node); /*prototype*/ extern LAN_OPT lanp; /* from ipmicmd.c */ //extern char *gnode; /* from ipmicmd.c */ //extern char *guser; /* from ipmicmd.c */ //extern char *gpswd; /* from ipmicmd.c */ //extern int gauth_type; /* from ipmicmd.c */ //extern int gpriv_level; /* from ipmicmd.c */ //extern int gcipher_suite; /*from ipmicmd.c, see table 22-19 IPMI 2.0 spec*/ extern int gshutdown; /* from ipmicmd.c */ extern FILE *fpdbg; /* == stdout, from ipmicmd.c */ extern FILE *fperr; /* == stderr, from ipmicmd.c */ extern FILE *fplog; /* from ipmicmd.c */ extern ipmi_cmd_t ipmi_cmds[]; /* from ipmicmd.c */ //extern char lan2_nodename[]; /*from lib/lanplus/lanplus.c */ extern struct ipmi_intf ipmi_lanplus_intf; /*from libintf_lanplus.a*/ typedef struct { int type; int len; char *data; } SOL_RSP_PKT; typedef struct { struct ipmi_intf *intf; SockType lan2_fd; uchar sol_seq; /*sending SOL sequence num, will call inc_sol_seq*/ uchar sol_len; /*sending SOL num chars */ uchar sol_seq_acked; /*last acked sent SOL sequence num*/ uchar sol_rseq; /*received SOL sequence num*/ uchar sol_rlen; /*received SOL num chans*/ } LAN2_CONN; /*see also IPMI_HDR below*/ static int loglvl = LOG_WARN; /*3=LOG_ERR 4=LOG_WARN 6=LOG_INFO 7=LOG_DEBUG*/ static LAN2_CONN conn = {NULL,0,0,0,0,0,0}; static LAN2_CONN *pconn = &conn; // static SockType lan2_fd = 0; // static struct ipmi_intf *intf = NULL; static uchar sol_seq = 0; /*sending SOL sequence num, will call inc_sol_seq*/ static uchar sol_len = 0; /*sending SOL num chars */ static uchar sol_seq_acked = 0; /*last acked sent SOL sequence num*/ static uchar sol_rseq = 0; /*received SOL sequence num*/ static uchar sol_rlen = 0; /*received SOL num chans*/ static uchar chars_to_resend = 0; static long lan2_latency = 0; // #define LAN_ERR_INVPARAM -8 #define PSWD_MAX 16 #if defined(WIN32) /* Windows does not have gettimeofday, so do it here */ #include #define UNIX_EPOCH_USEC 11644473600000000ULL struct timezone { int tz_minuteswest; int tz_dsttime; }; int gettimeofday(struct timeval *tv, struct timezone *tz) { FILETIME ft; unsigned __int64 nusec, tmpres = 0; static int tzflag = 0; if (tv != NULL) { GetSystemTimeAsFileTime(&ft); tmpres |= ft.dwHighDateTime; tmpres <<= 32; tmpres |= ft.dwLowDateTime; nusec = tmpres / 10; /*convert 100-nanosec into microseconds*/ nusec -= UNIX_EPOCH_USEC; /*windows -> unix epoch*/ tv->tv_sec = (long)(nusec / 1000000UL); tv->tv_usec = (long)(nusec % 1000000UL); } if (tz != NULL) { if (!tzflag) { _tzset(); tzflag++; } tz->tz_minuteswest = _timezone / 60; tz->tz_dsttime = _daylight; } return 0; } #endif #if defined(WIN32) || defined(SOLARIS) #ifdef OLD /* Now moved to lib/lanplus/lanplus.c */ void ipmilanplus_init(struct ipmi_intf *intf) { strcpy(intf->name,"lanplus"); intf->setup = ipmi_lanplus_setup; intf->open = ipmi_lanplus_open; intf->close = ipmi_lanplus_close; intf->sendrecv = ipmi_lanplus_send_ipmi_cmd; intf->recv_sol = ipmi_lanplus_recv_sol; intf->send_sol = ipmi_lanplus_send_sol; intf->keepalive = ipmi_lanplus_keepalive; intf->target_addr = IPMI_BMC_SLAVE_ADDR; /*0x20*/ intf->my_addr = IPMI_BMC_SLAVE_ADDR; /*0x20*/ } #else extern void ipmilanplus_init(struct ipmi_intf *intf); #endif #endif struct ipmi_intf * ipmi_intf_load(char * name) { if (strcmp(name,"lanplus") == 0) { #if defined(WIN32) || defined(SOLARIS) /* initialize the intf */ ipmilanplus_init(&ipmi_lanplus_intf); #endif return (&ipmi_lanplus_intf); } else return (NULL); } long lan2_get_latency(void) { return(lan2_latency); } static void set_latency( struct timeval *t1, struct timeval *t2, long *latency) { long nsec; nsec = t2->tv_sec - t1->tv_sec; if ((ulong)(nsec) > 1) nsec = 1; *latency = nsec*1000 + (t2->tv_usec - t1->tv_usec)/1000; } /* * ipmi_open_lan2 */ int ipmi_open_lan2(char *node, char *puser, char *pswd, int fdebugcmd) { char *user = ""; int rv = -1; size_t n; struct ipmi_intf *intf; if (puser != NULL) user = puser; #ifdef DEBUG if (fdbglog && fdebugcmd) fdebugcmd = 3; /*full debug*/ else if (fdbglog) fdebugcmd = 2; /*special log only from isolconsole.c*/ else if (fdebugcmd) fdebugcmd = 1; /*debug, no packets*/ if (fdebugcmd) fdebugcmd = 4; /*max debug*/ #endif switch (fdebugcmd) { case 4: /* max debug */ loglvl = 8; /* 8=(LOG_DEBUG=1, max), 7=LOG_DEBUG */ verbose = 8; /* usually 0 or 1, but max is 8. */ break; case 3: /* full debug */ loglvl = 7; /* 7=LOG_DEBUG; max=8 (LOG_DEBUG+1) */ verbose = 4; /* show packets */ break; case 2: /* debug log file only*/ loglvl = 6; /* 6=LOG_INFO, 4=LOG_WARN */ verbose = 1; /* usually 0 or 1, but could be up to 8. */ break; case 1: /* debug, no packets */ loglvl = 7; /* 7=LOG_DEBUG; max=8 (LOG_DEBUG+1) */ verbose = 1; /* usually 0 or 1, but could be up to 8. */ break; case 0: /* no debug*/ /* by default loglevel = 4; (4=LOG_WARN) verbose = 0; */ default: break; } if (fdbglog) dbglog("ipmi_open_lan2(%s,%s,%p,%d) verbose=%d loglevel=%d\n", node,user,pswd,fdebugcmd,verbose,loglvl); else if (fdebugcmd) fprintf(fpdbg,"ipmi_open_lan2(%s,%s,%p,%d) verbose=%d loglevel=%d\n", node,user,pswd,fdebugcmd,verbose,loglvl); set_loglevel(loglvl); intf = pconn->intf; if (nodeislocal(node)) { fprintf(fpdbg,"ipmi_open_lan2: node %s is local!\n",node); rv = LAN_ERR_INVPARAM; goto EXIT; } else { /* if attempting re-open to a new node, close the previous one. */ if (intf != NULL) { if ((intf->session != NULL) && (strcmp(intf->session->hostname,node) != 0)) { rv = ipmi_close_lan2(intf->session->hostname); } } if ((gshutdown==0) || fdebugcmd) fprintf(fpdbg,"Opening lanplus connection to node %s ...\n",node); rv = 0; if (intf == NULL) { /* fill in the intf structure */ intf = ipmi_intf_load("lanplus"); if (intf == NULL) return(-1); } if (intf->session == NULL && intf->opened == 0) { if (intf->setup == NULL) return(-1); rv = intf->setup(intf); /*allocates session struct*/ if (fdebugcmd) printf("lan2 intf setup returned %d\n",rv); } if (rv == 0) { if (intf->open == NULL) return(-1); if (intf->session == NULL) return(-1); intf->session->authtype_set = (uchar)lanp.auth_type; intf->session->privlvl = (uchar)lanp.priv; intf->session->cipher_suite_id = (uchar)lanp.cipher; if (node != NULL) { strcpy(intf->session->hostname,node); } if (user != NULL) { strcpy(intf->session->username,user); } if (pswd == NULL || pswd[0] == 0) intf->session->password = 0; else { intf->session->password = 1; n = strlen(pswd); if (n > PSWD_MAX) n = PSWD_MAX; memset(intf->session->authcode,0,PSWD_MAX); strncpy(intf->session->authcode, pswd, n); } rv = intf->open(intf); if (fdebugcmd) printf("lan2 open.intf(auth=%d,priv=%d,cipher=%d) returned %d\n", lanp.auth_type,lanp.priv,lanp.cipher, rv); if (rv != -1) { /*success is >= 0*/ sol_seq = 0; /*init new session, will call inc_sol_seq*/ sol_len = 0; sol_seq_acked = 0; pconn->lan2_fd = intf->fd; /*not same as rv if Windows*/ rv = 0; } } pconn->intf = intf; } EXIT: if (rv != 0) { if ((gshutdown == 0) || fdebugcmd) fprintf(fperr, "ipmi_open_lan2 error %d\n",rv); } return(rv); } int ipmi_close_lan2(char *node) { int rv = 0; struct ipmi_intf *intf; intf = pconn->intf; if (!nodeislocal(node)) { /* ipmilan, need to close & cleanup */ if (fdbglog) dbglog("ipmi_close_lan2(%s) intf=%p\n",node,intf); if (intf != NULL) { if (intf->opened > 0 && intf->close != NULL) { intf->close(intf); /* do the close */ intf->fd = -1; intf->opened = 0; } } pconn->lan2_fd = -1; sol_seq = 0; sol_len = 0; sol_rseq = 0; sol_rlen = 0; sol_seq_acked = 0; } return (rv); } int ipmi_cmdraw_lan2(char *node, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rc, n; struct ipmi_rq req; struct ipmi_rs *rsp; struct timeval t1, t2; struct ipmi_intf *intf = pconn->intf; if (fdebugcmd) verbose = 5; /* show packets */ #ifdef DEBUG if (fdebugcmd) verbose = 8; #endif if (intf == NULL || (intf->opened == 0)) { rc = ipmi_open_lan2(node,lanp.user,lanp.pswd,fdebugcmd); if (rc != 0) { if (fdebugcmd) fprintf(fperr, "ipmi_cmd_lan2: interface open error %d\n",rc); return(rc); } intf = pconn->intf; } /* do the command */ memset(&req, 0, sizeof(req)); req.msg.cmd = cmd; req.msg.netfn = netfn; req.msg.lun = lun; req.msg.target_cmd = cmd; req.msg.data = pdata; req.msg.data_len = sdata; intf->target_addr = sa; /*usu 0x20*/ intf->target_lun = lun; intf->target_channel = bus; gettimeofday(&t1, NULL); rsp = intf->sendrecv(intf, &req); if (rsp == NULL) rc = -1; else { *pcc = rsp->ccode; rc = rsp->ccode; } gettimeofday(&t2, NULL); set_latency(&t1,&t2,&lan2_latency); if (rc == 0) { /* copy data */ if (rsp->data_len > *sresp) n = *sresp; else n = rsp->data_len; memcpy(presp,rsp->data,n); *sresp = n; } else { *sresp = 0; if (fdebugcmd) fprintf(fperr, "ipmi_cmd_lan2 error %d\n",rc); } return (rc); } /* * ipmi_cmd_lan2 * This is the entry point, called from ipmicmd.c */ int ipmi_cmd_lan2(char *node, ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rc, i; uchar mycmd; for (i = 0; i < NCMDS; i++) { if (ipmi_cmds[i].cmdtyp == cmd) break; } if (i >= NCMDS) { fprintf(fperr, "ipmi_cmd_lan2: Unknown command %x\n",cmd); return(-1); } if (cmd >= CMDMASK) mycmd = (uchar)(cmd & CMDMASK); /* unmask it */ else mycmd = (uchar)cmd; rc = ipmi_cmdraw_lan2(node,mycmd, ipmi_cmds[i].netfn, ipmi_cmds[i].lun, ipmi_cmds[i].sa, ipmi_cmds[i].bus, pdata, sdata, presp, sresp, pcc, fdebugcmd); return(rc); } #define NOEM 4 static struct { int id; char *name; } oem_list[NOEM] = { {0x000157, "intelplus"}, /*VENDOR_INTEL*/ {0x002A7C, "supermicro"}, /*VENDOR_SUPERMICRO*/ /* { 0, "icts"}, *ICTS testware, needs user option*/ {0x00000B, "hp"}, /*VENDOR_HP*/ {0x000002, "ibm"} /*VENDOR_IBM*/ }; #ifdef METACOMMAND extern int is_lan2intel(int vend, int prod); /*oem_intel.c*/ #else static int is_lan2intel(int vend, int prod) { int rv = 0; /* Older Intel BMCs use oem lan2i method, newer Intel FW uses lan2. */ if (vend == VENDOR_INTEL) if ((prod < 0x0030) || (prod == 0x0811)) rv = 1; return(rv); } #endif int ipmi_oem_active(struct ipmi_intf * intf, const char * oemtype) { int i, vend, prod, dtype; get_mfgid(&vend,&prod); dtype = get_driver_type(); if (verbose) lprintf(LOG_INFO,"oem_active(is_type==%s ?) vend=%x prod=%x", oemtype,vend,prod); if (strncmp("intelplus", oemtype, strlen(oemtype)) == 0) { /* special case to detect intelplus, not all Intel platforms */ if (dtype == DRV_LAN2I) { i = 1; } else { if (is_lan2intel(vend,prod)) { i = 1; set_driver_type("lan2i"); } else { /* If iBMC, does not use intelplus */ if (verbose) lprintf(LOG_WARN,"detected as not intelplus"); i = 0; } } if (verbose && i == 1) lprintf(LOG_WARN,"intelplus detected, vend=%x prod=%x",vend, prod); return i; } else { // if (intf->oem == NULL) return 0; for (i = 0; i < NOEM; i++) { if (strncmp(oem_list[i].name,oemtype,strlen(oemtype)) == 0) if (oem_list[i].id == vend) { if (verbose) lprintf(LOG_WARN,"%s detected, vend=%x",oemtype,vend); return 1; } } } return 0; } /* * lan2_validate_solrcv() * Validate the SOL receive packet, and save received SOL info * (recv seq num, char count) for use in send_sol header. * return value (bitwise): * 0x01 bit set: received packet is present with data len > 0 * 0x02 bit set: received packet flags error in the previously sent packet * 0x04 bit set: received packet is a retry of previous * 0x08 bit set: break detected */ static int lan2_validate_solrcv(struct ipmi_rs * rs) { int rv = 0; if (rs == NULL) return(rv); if (verbose > 4) dbg_dump("rs_sol_hdr", (uchar *)&rs->payload.sol_packet.packet_sequence_number,8,1); chars_to_resend = 0; sol_rlen = (uchar)rs->data_len; if (sol_rlen > 4) sol_rlen -= 4; else sol_rlen = 0; if (sol_rlen > 0) rv |= 0x01; /* have a receive packet with dlen > 0 */ if (rs->payload.sol_packet.packet_sequence_number != 0) { if (rs->payload.sol_packet.packet_sequence_number == sol_rseq) { lprintf(LOG_INFO,"received retry of sol_rseq %d, rlen=%d", sol_rseq,sol_rlen); /* do nothing because rs->data_len was set to 4 in lanplus */ // rv |= 0x04; /* return, don't process this again */ return(rv); } else sol_rseq = rs->payload.sol_packet.packet_sequence_number; } /* check for errors in previously sent packet */ if (rs->payload.sol_packet.acked_packet_number != 0) { if (rs->payload.sol_packet.acked_packet_number != sol_seq) rv |= 0x02; else if ((rs->payload.sol_packet.accepted_character_count < sol_len) && (sol_seq_acked < sol_seq)) { lprintf(LOG_INFO,"partial_ack, seq=%d: acked=%d < sent=%d", sol_seq,rs->payload.sol_packet.accepted_character_count, sol_len); chars_to_resend = sol_len - rs->payload.sol_packet.accepted_character_count; rv |= 0x02; } sol_seq_acked = rs->payload.sol_packet.acked_packet_number; } if (sol_seq != 0) { /*if we have sent something*/ if (rs->payload.sol_packet.is_nack) rv |= 0x02; if (rs->payload.sol_packet.transfer_unavailable) rv |= 0x02; if (rs->payload.sol_packet.sol_inactive) rv |= 0x02; if (rs->payload.sol_packet.transmit_overrun) rv |= 0x02; } if (rs->payload.sol_packet.break_detected) rv |= 0x08; if (rv & 0x02) { if (sol_seq_acked < sol_seq) { /*not already acked, needs retry*/ lprintf(LOG_INFO,"need to retry sol_seq=%d, acked=%d len=%d rv=%x", sol_seq,sol_seq_acked,sol_len,rv); if (chars_to_resend == 0) chars_to_resend = sol_len; } else rv &= 0xFD; } return(rv); } /* * lan2_set_sol_data * called from isolconsole when SOL 2.0 session is activated. */ void lan2_set_sol_data(int insize, int outsize, int port, void *handler, char esc_char) { struct ipmi_intf *intf = pconn->intf; if (intf == NULL) return; lprintf(LOG_INFO,"setting lanplus intf params(%d,%d,%d,%p,%c)", insize,outsize,port,handler,esc_char); intf->session->sol_data.max_inbound_payload_size = (ushort)insize; intf->session->sol_data.max_outbound_payload_size = (ushort)outsize; intf->session->sol_data.port = (ushort)port; intf->session->sol_data.sol_input_handler = handler; intf->session->timeout = 1; /* lib/.../lanplus.h: IPMI_LAN_TIMEOUT =1sec*/ intf->session->sol_escape_char = esc_char; /*usu '~'*/ } int lan2_keepalive(int type, SOL_RSP_PKT *rsp) { int rv = 0; struct ipmi_intf *intf = pconn->intf; if (fdbglog) dbglog("lan2_keepalive(%d,%p) called\n",type,rsp); /*++++*/ if (intf == NULL) return -1; if (rsp) rsp->len = 0; if (type == 2) { /*send empty SOL data*/ struct ipmi_v2_payload v2_payload; struct ipmi_rs * rs = NULL; memset(&v2_payload, 0, sizeof(v2_payload)); v2_payload.payload.sol_packet.packet_sequence_number = 0; v2_payload.payload.sol_packet.character_count = 0; v2_payload.payload.sol_packet.acked_packet_number = 0; v2_payload.payload.sol_packet.accepted_character_count = 0; rs = intf->send_sol(intf, &v2_payload); if (rs == NULL) { rv = -1; } else { /*may sometimes get data back*/ rsp->type = rs->session.payloadtype; rsp->len = rs->data_len; rsp->data = rs->data; lprintf(LOG_INFO, "keepalive: rq_seq=%d rs_seq=%d (0x%02x) rseq=%d rlen=%d", // v2_payload.payload.ipmi_request.rq_seq, v2_payload.payload.sol_packet.packet_sequence_number, rs->session.seq, rs->session.seq, rs->payload.sol_packet.packet_sequence_number,rs->data_len); rv = lan2_validate_solrcv(rs); if (rv > 1) lprintf(LOG_INFO, "keepalive: rv=%x need retry of sol_seq=%d(%d) sol_len=%d(%d)", rv,v2_payload.payload.sol_packet.packet_sequence_number, sol_seq,v2_payload.payload.sol_packet.character_count,sol_len); rv = 0; /* 0 = have recv buffer to process*/ } } else { rv = intf->keepalive(intf); /*get_device_id*/ } if (fdbglog) dbglog("lan2_keepalive rv = %d\n",rv); /*++++*/ return(rv); } static uchar inc_sol_seq( uchar lastseq ) { uchar seq; seq = lastseq + 1; if (seq > 15) seq = 1; pconn->intf->session->sol_data.sequence_number = seq; return(seq); } int lan2_send_break( SOL_RSP_PKT *rsp) { struct ipmi_rs *rs; static struct ipmi_v2_payload v2_payload; int rv = 0; struct ipmi_intf *intf = pconn->intf; if (intf == NULL) return -1; if (rsp == NULL) return -1; rsp->len = 0; /*just in case*/ memset(&v2_payload, 0, sizeof(v2_payload)); v2_payload.payload.sol_packet.character_count = 0; v2_payload.payload.sol_packet.generate_break = 1; rs = intf->send_sol(intf, &v2_payload); if (rs == NULL) { rv = -1; lprintf(LOG_INFO,"send_break error"); } else { rv = 0; rsp->type = rs->session.payloadtype; rsp->len = rs->data_len; rsp->data = rs->data; lprintf(LOG_INFO,"send_break(rs): sol_seq=%d rs_sol=%d " "rs_seq=%d (0x%02x) rseq=%d rlen=%d", v2_payload.payload.sol_packet.packet_sequence_number, rs->payload.sol_packet.packet_sequence_number, rs->session.seq, rs->session.seq, rs->payload.sol_packet.packet_sequence_number,rs->data_len); } return(rv); } int lan2_send_sol( uchar *payload, int len, SOL_RSP_PKT *rsp) { struct ipmi_rs *rs; static struct ipmi_v2_payload v2_payload; int rv = 0; struct ipmi_intf *intf = pconn->intf; if (rsp) rsp->len = 0; /*just in case*/ if (intf == NULL) return -1; memset(&v2_payload, 0, sizeof(v2_payload)); memcpy(v2_payload.payload.sol_packet.data,payload,len); sol_seq = inc_sol_seq(sol_seq); sol_len = (uchar)len; v2_payload.payload.sol_packet.packet_sequence_number = sol_seq; v2_payload.payload.sol_packet.character_count = (uchar)len; #ifdef TEST /* Note that the lanplus layer already did auto-ack of sol recv pkts, * but we can put the info in send_sol also for completeness. */ /* Further debug shows that this doesn't matter, so skip it. */ v2_payload.payload.sol_packet.acked_packet_number = sol_rseq; v2_payload.payload.sol_packet.accepted_character_count = sol_rlen; /* These flags were initialized to zero above via memset. */ v2_payload.payload.sol_packet.is_nack = 0; v2_payload.payload.sol_packet.assert_ring_wor = 0; v2_payload.payload.sol_packet.generate_break = 0; v2_payload.payload.sol_packet.deassert_cts = 0; v2_payload.payload.sol_packet.deassert_dcd_dsr = 0; v2_payload.payload.sol_packet.flush_inbound = 0; v2_payload.payload.sol_packet.flush_outbound = 0; #endif lprintf(LOG_INFO,"send_sol(rq): sol_seq=%d acked=%d chars=%d len=%d", v2_payload.payload.sol_packet.packet_sequence_number, v2_payload.payload.sol_packet.acked_packet_number, v2_payload.payload.sol_packet.accepted_character_count,len); if (verbose > 4) dbg_dump("rq_sol_hdr", (uchar *)&v2_payload.payload.sol_packet.packet_sequence_number, 10,1); rs = intf->send_sol(intf, &v2_payload); if (rs == NULL) { rv = -1; lprintf(LOG_INFO,"send_sol error (%d bytes)",len); } else { rsp->type = rs->session.payloadtype; rsp->len = rs->data_len; rsp->data = rs->data; lprintf(LOG_INFO,"send_sol(rs): sol_seq=%d rs_sol=%d rs_seq=%d (0x%02x)" " rseq=%d rlen=%d", v2_payload.payload.sol_packet.packet_sequence_number, // v2_payload.payload.sol_packet.acked_packet_number, rs->payload.sol_packet.packet_sequence_number, rs->session.seq, rs->session.seq, rs->payload.sol_packet.packet_sequence_number,rs->data_len); rv = lan2_validate_solrcv(rs); if (rv > 1) lprintf(LOG_INFO, "send_sol: rv=%x sol_seq=%d(%d) sol_len=%d(%d) not acked", rv,v2_payload.payload.sol_packet.packet_sequence_number, sol_seq,v2_payload.payload.sol_packet.character_count,sol_len); rv = 0; /* 0 = have recv buffer to process*/ } return(rv); } int lan2_recv_sol( SOL_RSP_PKT *rsp ) { struct ipmi_rs * rs; int rv; struct ipmi_intf *intf = pconn->intf; if (rsp == NULL) return -1; rsp->len = 0; if (intf == NULL) return -1; rs = intf->recv_sol(intf); if (rs == NULL) return -1; rsp->type = rs->session.payloadtype; rsp->len = rs->data_len; rsp->data = rs->data; lprintf(LOG_INFO,"recv_sol: rs_sol=%d rs_seq=%d (0x%02x) rseq=%d rlen=%d", rs->payload.sol_packet.packet_sequence_number, rs->session.seq, rs->session.seq, rs->payload.sol_packet.packet_sequence_number,rs->data_len); rv = lan2_validate_solrcv(rs); if (rv > 1) { lprintf(LOG_INFO, "recv_sol: rv=%x sol_seq=%d sol_len=%d not acked", rv,sol_seq,sol_len); } return(rsp->len); } void lan2_recv_handler( void *rs0) { struct ipmi_rs *rs = rs0; SOL_RSP_PKT rsp; int rv; rsp.len = 0; rsp.type = 0; if (rs == NULL) return; lprintf(LOG_INFO,"recv_handler: len=%d rs_seq=%d (0x%02x) rseq=%d rlen=%d", rs->data_len, rs->session.seq, rs->session.seq, rs->payload.sol_packet.packet_sequence_number,rs->data_len); rsp.type = rs->session.payloadtype; rsp.len = rs->data_len; rsp.data = rs->data; rv = lan2_validate_solrcv(rs); if (rv > 1) lprintf(LOG_INFO, "recv_handler: rv=%x sol_seq=%d sol_len=%d not acked", rv,sol_seq,sol_len); sol_output_handler(&rsp); return; } SockType lan2_get_fd(void) { if (pconn->intf == NULL) return pconn->lan2_fd; return(pconn->intf->fd); } #endif /* end ipmilanplus.c */ ipmiutil-3.1.5/util/ievents.c0000644000076400007640000026106713566765324016270 0ustar mgportalloggers/* * ievents.c * * This file decodes the IPMI event into a readable string. * It is used by showsel.c and getevent.c. * * ievents.c compile flags: * METACOMMAND - defined if building for ipmiutil meta-command binary * ALONE - defined if building for ievents standalone binary * else it could be compiled with libipmiutil.a * LINUX, BSD, WIN32, DOS - defined for that OS * * Author: Andy Cress arcress at users.sourceforge.net * * Copyright (c) 2009 Kontron America, Inc. * Copyright (c) 2006 Intel Corporation. * * 05/26/05 Andy Cress - created from showsel.c (see there for history) * 06/20/05 Andy Cress - changed PowerSupply present/not to Inserted/Removed * 08/01/05 Andy Cress - added more Power Unit & Battery descriptions * 03/02/06 Andy Cress - more decoding for Power Unit 0b vs. 6f * 04/11/07 Andy Cress - added events -p decoding for PET data * 10/03/07 Andy Cress - added file_grep for -p in Windows * 03/03/08 Andy Cress - added -f to interpret raw SEL file */ /*M* Copyright (c) 2009 Kontron America, Inc. Copyright (c) 2006, Intel Corporation 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 Corporation 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 #ifdef WIN32 #include #include #include #elif defined(DOS) #include #include #include #else #include #include #include #include #include #include #endif #include #include "ipmicmd.h" #include "ievents.h" #define SELprintf printf #define SMS_SA 0x41 #define SMI_SA 0x21 #ifdef METACOMMAND extern char *progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil events"; #else static char *progver = "3.15"; static char *progname = "ievents"; #endif static char fsensdesc = 0; /* 1= get extended sensor descriptions*/ static char fcanonical = 0; /* 1= show canonical, delimited output*/ static char fgetdevid = 0; /* 1= get device ID */ static char fnewevt = 0; /* 1= generate New event */ static char futc = 0; /* 1= raw UTC time */ static uchar thr_sa = SMS_SA; /* 0x41 (Sms) used by ipmitool PlarformEvents */ static void *sdrcache = NULL; static int pet_guid = 8; /*bytes in the input data for the GUID*/ static int iopt = -1; /*iana option*/ static char bcomma = ','; static char bdelim = BDELIM; /* '|' */ #ifdef ALONE char fdebug = 0; /* 1= debug output, standalone*/ static char fsm_debug = 0; #else extern char fdebug; /* 1= debug output, from ipmicmd.c*/ extern char fsm_debug; /*mem_if.c*/ #endif #define SDR_SZ 80 #pragma pack(1) typedef struct { ushort record_id; uchar record_type; uint timestamp; ushort generator_id; /*slave_addr/channel*/ uchar evm_rev; //event message revision uchar sensor_type; uchar sensor_number; uchar event_trigger; uchar event_data1; uchar event_data2; uchar event_data3; } SEL_RECORD; #pragma pack() #ifdef WIN32 static char sensfil[80] = "sensor_out.txt"; static char sensfil2[80] = "%ipmiutildir%\\sensor_out.txt"; // static char outfil[64] = "stype.tmp"; #else static char sensfil[80] = "/var/lib/ipmiutil/sensor_out.txt"; static char sensfil2[80] = "/usr/share/ipmiutil/sensor_out.txt"; // static char outfil[] = "/tmp/stype.tmp"; #endif static char rawfil[80] = ""; char *evt_hdr = "RecId Date/Time_______ SEV Src_ Evt_Type___ Sens# Evt_detail - Trig [Evt_data]\n"; char *evt_hdr2 = "RecId | Date/Time | SEV | Src | Evt_Type | Sensor | Evt_detail \n"; #ifdef MOVED /* moved SEV_* to ipmicmd.h */ #define SEV_INFO 0 #define SEV_MIN 1 #define SEV_MAJ 2 #define SEV_CRIT 3 #endif #define NSEV 4 char *sev_str[NSEV] = { /*0*/ "INF", /*1*/ "MIN", /*2*/ "MAJ", /*3*/ "CRT" }; /* sensor_types: See IPMI 1.5 Table 36-3, IPMI 2.0 Table 42-3 */ #define NSTYPES 0x2F static const char *sensor_types[NSTYPES] = { /* 00h */ "reserved", /* 01h */ "Temperature", /* 02h */ "Voltage", /* 03h */ "Current", /* 04h */ "Fan", /* 05h */ "Platform Security", /* 06h */ "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", /*incl POST code errors*/ /* 10h */ "Event Log", /*SEL Disabled or Cleared */ /* 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", /* 2Ah */ "SessionAudit", /* 2Bh */ "Version Change", /* 2Ch */ "FRU State", /* 2Dh */ "SMI Timeout", /* 0xF3 == OEM SMI Timeout */ /* 2Eh */ "ME" /* 0xDC == ME Node Manager */ }; #define NFWERRS 14 static struct { /* See Table 36-3, type 0Fh, offset 00h */ int code; char *msg; } fwerrs[NFWERRS + 1] = { { 0x00, "Unspecified"}, { 0x01, "No system memory"}, { 0x02, "No usable memory"}, { 0x03, "Unrecovered Hard Disk"}, { 0x04, "Unrecovered System Board"}, { 0x05, "Unrecovered Diskette"}, { 0x06, "Unrecovered Hard Disk Ctlr"}, { 0x07, "Unrecovered PS2 USB"}, { 0x08, "Boot media not found"}, { 0x09, "Unrecovered video controller"}, { 0x0A, "No video device"}, { 0x0B, "Firmware ROM corruption"}, { 0x0C, "CPU voltage mismatch"}, { 0x0D, "CPU speed mismatch"}, { 0x0E, "Reserved" } }; #define NFWSTAT 26 static struct { /* See Table 36-3, type 0Fh, offset 01h & 02h */ int code; char *msg; } fwstat[NFWSTAT + 1] = { { 0x00, "Unspecified"}, { 0x01, "Memory init"}, { 0x02, "Hard disk init"}, { 0x03, "Secondary processor"}, { 0x04, "User authentication"}, { 0x05, "User-init sys setup"}, { 0x06, "USB configuration"}, { 0x07, "PCI configuration"}, { 0x08, "Option ROM init"}, { 0x09, "Video init"}, { 0x0a, "Cache init"}, { 0x0b, "SM Bus init"}, { 0x0c, "Keyboard init"}, { 0x0d, "Mgt controller"}, { 0x0e, "Docking attach"}, { 0x0f, "Enabling docking"}, { 0x10, "Docking eject"}, { 0x11, "Disabling docking"}, { 0x12, "OS wake-up"}, { 0x13, "Starting OS boot"}, { 0x14, "Baseboard init"}, { 0x15, "reserved"}, { 0x16, "Floppy init"}, { 0x17, "Keyboard test"}, { 0x18, "Mouse test"}, { 0x19, "Primary processor"}, { 0x1A, "Reserved"} }; #define NGDESC 12 static struct { ushort g_id; const char desc[8]; } gen_desc[NGDESC] = { /*empirical, format defined in IPMI 1.5 Table 23-5 */ { 0x0000, "IPMB"}, { 0x0001, "EFI "}, { 0x0003, "BIOS"}, /* BIOS POST */ { BMC_SA, "BMC "}, /* 0x0020==BMC_SA*/ { SMI_SA, "SMI "}, /* 0x0021==SMI_SA, platform events */ { 0x0028, "CHAS"}, /* Chassis Bridge Controller */ { 0x0031, "mSMI"}, /* BIOS SMI/POST errors on miniBMC or ia64 */ { 0x0033, "Bios"}, /* BIOS SMI (runtime), usually for memory errors */ { SMS_SA, "Sms "}, /* 0x0041==SmsOs for MS Win2008 Boot, ipmitool event */ { 0x002C, "ME "}, /* ME Node Manager for S5500 */ { 0x602C, "ME "}, /* ME Node Manager for S5500/i7 bus=0x6, sa=0x2C */ { HSC_SA, "HSC "} /* 0x00C0==HSC_SA for SAF-TE Hot-Swap Controller*/ }; #define NCRITS 10 char * crit_int_str[NCRITS] = { /* Critical Interrupt descriptions */ /*00*/ "FP NMI ", /* Front Panel NMI */ /*01*/ "Bus Timout", /*02*/ "IOch NMI ", /* IO channel check NMI */ /*03*/ "Soft NMI ", /*04*/ "PCI PERR ", /*05*/ "PCI SERR ", /*06*/ "EISA Timout", /*07*/ "Bus Warn ", /* Bus Correctable Error */ /*08*/ "Bus Error", /* Bus Uncorrectable Error */ /*09*/ "Fatal NMI" }; #define NBOOTI 8 char * boot_init_str[NBOOTI] = { /* System Boot Initiated */ /*00*/ "Power Up ", /*01*/ "Hard Reset", /*02*/ "Warm Reset", /*03*/ "PXE Boot ", /*04*/ "Diag Boot ", /*05*/ "SW Hard Reset", /*06*/ "SW Warm Reset", /*07*/ "RestartCause" }; #define NOSBOOT 10 char * osboot_str[NOSBOOT] = { /* OS Boot */ /*00*/ "A: boot completed", /*01*/ "C: boot completed", /*02*/ "PXE boot completed", /*03*/ "Diag boot completed", /*04*/ "CDROM boot completed", /*05*/ "ROM boot completed", /*06*/ "Other boot completed", /*07*/ "USB7 boot completed", /*08*/ "USB8 boot completed" }; #define NSLOTC 9 char * slot_str[NSLOTC] = { /* Slot/Connector descriptions */ /*00*/ "Fault ", /*01*/ "Identify", /*02*/ "Inserted", /*03*/ "InsReady", /*04*/ "RemReady", /*05*/ "PowerOff", /*06*/ "RemRequest", /*07*/ "Interlock", /*08*/ "Disabled" }; #define NBATT 3 char * batt_str[NBATT] = { /* Battery assert descriptions */ /*00*/ "Low", /*01*/ "Failed", /*02*/ "Present" }; char * batt_clr[NBATT] = { /* Battery deassert descriptions */ /*00*/ "Low is OK now", /*01*/ "Failed is OK now", /*02*/ "Absent" }; #define N_NMH 6 char * nmh_str[N_NMH] = { /* ME Node Manager Health (73) descriptions */ /*10*/ "Policy Misconfig", /*11*/ "Power Sensor Err", /*12*/ "Inlet Temp Sensor Err", /*13*/ "Host Comm Err", /*14*/ "RTC Sync Err" , /*15*/ "Plat Shutdown" }; #define N_NMFW 6 char * nmfw_str[N_NMFW] = { /* ME Firmware Health (75) descriptions */ /*00*/ "Forced GPIO Recov", /*01*/ "Image Exec Fail", /*02*/ "Flash Erase Error", /*03*/ "Flash Corrupt" , /*04*/ "Internal Watchdog Timeout", // FW Watchdog Timeout, need to flash ME /*05*/ "BMC Comm Error" }; #define N_NM 4 char * nm_str[N_NM] = { /* Node Manager descriptions */ /*72*/ "NM Exception", /*or NM Alert Threshold*/ /*73*/ "NM Health", /*74*/ "NM Capabilities", /*75*/ "FW Health" }; #define NPROC 11 char * proc_str[NPROC] = { /* Processor descriptions */ /*00*/ "IERR", /*01*/ "Thermal Trip", /*02*/ "FRB1/BIST failure", /*03*/ "FRB2 timeout", /*04*/ "FRB3 Proc error", /*05*/ "Config error", /*06*/ "SMBIOS CPU error", /*07*/ "Present", /*08*/ "Disabled", /*09*/ "Terminator", /*0A*/ "Throttled" }; #define NACPIP 15 char * acpip_str[NACPIP] = { /* ACPI Power State descriptions */ /*00*/ "S0/G0 Working", /*01*/ "S1 sleeping, proc/hw context maintained", /*02*/ "S2 sleeping, proc context lost", /*03*/ "S3 sleeping, proc/hw context lost, mem ok", /*42 chars*/ /*04*/ "S4 non-volatile sleep/suspend", /*05*/ "S5/G2 soft-off", /*06*/ "S4/S5 soft-off, no specific state", /*07*/ "G3/Mechanical off", /*08*/ "Sleeping in an S1/S2/S3 state", /*09*/ "G1 sleeping", /*0A*/ "S5 entered by override", /*0B*/ "Legacy ON state", /*0C*/ "Legacy OFF state", /*0D*/ "Unknown", /*0E*/ "Unknown" }; #define NAUDIT 2 char * audit_str[NAUDIT] = { /* Session Audit descriptions */ /*00*/ "Activated", /*01*/ "Deactivated"}; #define N_AVAIL 9 char * avail_str[N_AVAIL] = { /* Discrete Availability, evtype 0x0A */ /*00*/ "chg to Running", /*01*/ "chg to In Test", /*02*/ "chg to Power Off", /*03*/ "chg to On Line", /*04*/ "chg to Off Line", /*05*/ "chg to Off Duty", /*06*/ "chg to Degraded", /*07*/ "chg to Power Save", /*08*/ "Install Error"}; #define NSDESC 88 struct { ushort genid; /* generator id: BIOS, BMC, etc. (slave_addr/channel) */ uchar s_typ; /* 1=temp,2=voltage,4=fan,... */ uchar s_num; uchar evtrg; /* event trigger/type, see IPMI 1.5 table 36.1 & 36.2 */ uchar data1; uchar data2; uchar data3; uchar sev; /* 0=SEV_INFO, 1=SEV_MIN, 2=SEV_MAJ, 3=SEV_CRIT */ const char desc[40]; } sens_desc[NSDESC] = { /* if value is 0xff, matches any value */ {0xffff,0x05, 0xff, 0x6f, 0x40,0xff,0xff, 1,"Chassis Intrusion"}, /*chassis*/ {0xffff,0x05, 0xff, 0xef, 0x40,0xff,0xff, 0,"Chassis OK"}, /*chassis*/ {0xffff,0x05, 0xff, 0x6f, 0x44,0xff,0xff, 1,"LAN unplugged"}, /*chassis*/ {0xffff,0x05, 0xff, 0xef, 0x44,0xff,0xff, 0,"LAN restored "}, /*chassis*/ {0xffff,0x06, 0xff, 0xff, 0x45,0xff,0xff, 0,"Password"}, /*security*/ {0xffff,0x07, 0xff, 0xff, 0x41,0xff,0xff, 3,"Thermal trip"}, /*processor*/ {0xffff,0x08, 0xff, 0x6f, 0x40,0xff,0xff, 0,"Inserted"}, /*PowerSupply*/ {0xffff,0x08, 0xff, 0x6f, 0x41,0xff,0xff, 2,"Failure detected"},/*PowerSupply*/ {0xffff,0x08, 0xff, 0x6f, 0x42,0xff,0xff, 1,"Predictive failure"}, {0xffff,0x08, 0xff, 0x6f, 0x43,0xff,0xff, 0,"AC Lost"}, {0xffff,0x08, 0xff, 0x6f, 0x46,0xff,0xff, 2,"Config Error"}, {0xffff,0x08, 0xff, 0xef, 0x40,0xff,0xff, 1,"Removed"}, /*PowerSupply*/ {0xffff,0x08, 0xff, 0xef, 0x41,0xff,0xff, 0,"is OK "}, /*PowerSupply*/ {0xffff,0x08, 0xff, 0xef, 0x42,0xff,0xff, 0,"Predictive OK"}, {0xffff,0x08, 0xff, 0xef, 0x43,0xff,0xff, 0,"AC Regained"}, /*PowerSupply*/ {0xffff,0x08, 0xff, 0xef, 0x46,0xff,0xff, 0,"Config OK now"}, {0xffff,0x0c, 0xff, 0xff, 0x00,0xff,0xff, 1,"Correctable ECC"}, /*memory*/ {0xffff,0x0f, 0x06, 0xff, 0xff,0xff,0xff, 2,"POST Code"}, {0xffff,0x10, 0x09, 0xff, 0x42,0x0f,0xff, 0,"Log Cleared"}, {0xffff,0x10, 0xff, 0xff, 0x02,0xff,0xff, 0,"Log Cleared"}, {0xffff,0x10, 0xff, 0xff, 0xc0,0x03,0xff, 1,"ECC Memory Errors"}, /* Often see these 3 Boot records with reboot: * 0003 12 83 6f 05 00 ff = System/SEL ClockSync_1 (start of POST) * 0003 12 83 6f 05 80 ff = System/SEL ClockSync_2 (end of POST) * 0003 12 83 6f 01 ff ff = OEM System Boot Event (after POST, loader), or * 0003 12 83 6f 41 0f ff = OEM System Boot Event (same w 01 & 41) * can be either 0003 (BIOS) or 0001 (EFI) */ {0xffff,0x12, 0xfe, 0xff, 0xc5,0x00,0xff, 0,"Boot: ClockSync_1"}, {0xffff,0x12, 0xfe, 0xff, 0xc5,0x80,0xff, 0,"Boot: ClockSync_2"}, {0xffff,0x12, 0x83, 0xff, 0x05,0x00,0xff, 0,"Boot: ClockSync_1"}, {0xffff,0x12, 0x83, 0xff, 0x05,0x80,0xff, 0,"Boot: ClockSync_2"}, {0xffff,0x12, 0x83, 0xff, 0x01,0xff,0xff, 0,"OEM System Booted"}, {0x0001,0x12, 0x08, 0xff, 0x01,0xff,0xff, 0,"OEM System Booted"}, /*ia64*/ {0xffff,0x12, 0x01, 0x6f, 0x01,0xff,0xff, 0,"OEM System Booted"}, /*S5000*/ {0xffff,0x12, 0x38, 0x6f, 0x00,0xff,0xff, 0,"OEM System Booted"}, /*KTC*/ {0xffff,0x12, 0x38, 0xef, 0x00,0xff,0xff, 0,"OEM System Booted"}, /*KTC*/ {0x0031,0x12, 0x00, 0x6f, 0xc3,0xff,0xff, 0,"PEF Action"}, /*ia64*/ {BMC_SA,0x12, 0x83, 0x6f, 0x80,0xff,0xff, 0,"System Reconfigured"}, /*BMC*/ {BMC_SA,0x12, 0x83, 0x0b, 0x80,0xff,0xff, 0,"System Reconfigured"}, /*BMC*/ {BMC_SA,0x12, 0x0b, 0x6f, 0x80,0xff,0xff, 0,"System Reconfigured"}, /*BMC*/ {BMC_SA,0x12, 0x83, 0xff, 0x41,0xff,0xff, 0,"OEM System Boot"}, /*BMC*/ {BMC_SA,0x12, 0x83, 0x6f, 0x42,0xff,0xff, 2,"System HW failure"}, /*BMC*/ {BMC_SA,0x12, 0x83, 0x6f, 0x04,0xff,0xff, 0,"PEF Action"}, /*BMC*/ {HSC_SA,0x0d, 0xff, 0x08, 0x00,0xff,0xff, 1,"Device Removed"}, /*HSC*/ {HSC_SA,0x0d, 0xff, 0x08, 0x01,0xff,0xff, 0,"Device Inserted"}, /*HSC*/ {0xffff,0x0d, 0xff, 0x6f, 0x00,0xff,0xff, 0,"Drive present"}, /*Romley BMC*/ {0xffff,0x0d, 0xff, 0xef, 0x00,0xff,0xff, 0,"Drive removed"}, /*BMC*/ {0xffff,0x0d, 0xff, 0x6f, 0x01,0xff,0xff, 2,"Drive fault"}, /*0x0D Drive*/ {0xffff,0x0d, 0xff, 0xef, 0x01,0xff,0xff, 0,"Drive fault OK"}, {0xffff,0x0d, 0xff, 0x6f, 0x02,0xff,0xff, 1,"Drive predict fail"}, {0xffff,0x0d, 0xff, 0x6f, 0x05,0xff,0xff, 1,"Drive not redundant"}, {0xffff,0x0d, 0xff, 0x6f, 0x07,0xff,0xff, 0,"Rebuild in progress"}, {0xffff,0x0d, 0xff, 0xef, 0x07,0xff,0xff, 0,"Rebuild complete"}, {0xffff,0x14, 0xff, 0xff, 0x42,0xff,0xff, 1,"Reset Button pressed"}, {0xffff,0x14, 0xff, 0xff, 0x40,0xff,0xff, 1,"Power Button pressed"}, {0xffff,0x14, 0xff, 0xff, 0x01,0xff,0xff, 0,"ID Button pressed"}, {0xffff,0x23, 0xff, 0xff, 0x40,0xff,0xff, 2,"Expired, no action"},/*watchdog2*/ {0xffff,0x23, 0xff, 0xff, 0x41,0xff,0xff, 3,"Hard Reset action"}, /*watchdog2*/ {0xffff,0x23, 0xff, 0xff, 0x42,0xff,0xff, 3,"Power down action"}, /*watchdog2*/ {0xffff,0x23, 0xff, 0xff, 0x43,0xff,0xff, 3,"Power cycle action"},/*watchdog2*/ {0xffff,0x23, 0xff, 0xff, 0x48,0xff,0xff, 2,"Timer interrupt"}, /*watchdog2*/ {0xffff,0xf3, 0xff, 0x83, 0x41,0xff,0xff, 0,"SMI de-asserted"}, {0xffff,0xf3, 0xff, 0x03, 0x41,0xff,0xff, 3,"SMI asserted"}, {0xffff,0x20, 0x00, 0xff, 0xff,0xff,0xff, 3,"OS Kernel Panic"}, {0xffff,0x01, 0xff, 0x03, 0x01,0xff,0xff, 2,"Temp Asserted"}, /*Discrete temp*/ {0xffff,0x01, 0xff, 0x83, 0x01,0xff,0xff, 0,"Temp OK"}, /*Discrete ok*/ {0xffff,0x01, 0xff, 0x05, 0x01,0xff,0xff, 2,"Temp Asserted"}, /*CPU Hot */ {0xffff,0x01, 0xff, 0x85, 0x01,0xff,0xff, 0,"Temp OK"}, /*CPU Hot ok*/ {0xffff,0x01, 0xff, 0x07, 0x01,0xff,0xff, 2,"Temp Asserted"}, /*Discrete temp*/ {0xffff,0x01, 0xff, 0x87, 0x01,0xff,0xff, 0,"Temp OK"}, /*Discrete ok*/ /*Thresholds apply to sensor types 1=temp, 2=voltage, 3=current, 4=fan*/ /*Note that last 2 bytes usu show actual & threshold values*/ /*evtrg: 0x01=thresh, 0x81=restored/deasserted */ {0xffff,0xff, 0xff, 0x01, 0x50,0xff,0xff, 1,"Lo Noncrit thresh"}, {0xffff,0xff, 0xff, 0x01, 0x51,0xff,0xff, 0,"Lo NoncritH OK now"}, {0xffff,0xff, 0xff, 0x01, 0x52,0xff,0xff, 2,"Lo Crit thresh"}, {0xffff,0xff, 0xff, 0x01, 0x53,0xff,0xff, 0,"Lo CritHi OK now"}, {0xffff,0xff, 0xff, 0x01, 0x54,0xff,0xff, 3,"Lo Unrec thresh"}, {0xffff,0xff, 0xff, 0x01, 0x55,0xff,0xff, 0,"Lo UnrecH OK now"}, {0xffff,0xff, 0xff, 0x01, 0x56,0xff,0xff, 0,"Hi NoncritL OK now"}, {0xffff,0xff, 0xff, 0x01, 0x57,0xff,0xff, 1,"Hi Noncrit thresh"}, {0xffff,0xff, 0xff, 0x01, 0x58,0xff,0xff, 0,"Hi CritLo OK now"}, {0xffff,0xff, 0xff, 0x01, 0x59,0xff,0xff, 2,"Hi Crit thresh"}, {0xffff,0xff, 0xff, 0x01, 0x5A,0xff,0xff, 0,"Hi UnrecL OK now"}, {0xffff,0xff, 0xff, 0x01, 0x5B,0xff,0xff, 3,"Hi Unrec thresh"}, {0xffff,0xff, 0xff, 0x81, 0x50,0xff,0xff, 0,"LoN thresh OK now"}, {0xffff,0xff, 0xff, 0x81, 0x51,0xff,0xff, 1,"LoNoncrit thresh"}, {0xffff,0xff, 0xff, 0x81, 0x52,0xff,0xff, 0,"LoC thresh OK now"}, {0xffff,0xff, 0xff, 0x81, 0x53,0xff,0xff, 2,"LoCritHi thresh"}, {0xffff,0xff, 0xff, 0x81, 0x54,0xff,0xff, 0,"LoU thresh OK now"}, {0xffff,0xff, 0xff, 0x81, 0x55,0xff,0xff, 3,"LoUnrecH thresh"}, {0xffff,0xff, 0xff, 0x81, 0x56,0xff,0xff, 1,"HiNoncrit thresh"}, {0xffff,0xff, 0xff, 0x81, 0x57,0xff,0xff, 0,"HiN thresh OK now"}, {0xffff,0xff, 0xff, 0x81, 0x58,0xff,0xff, 2,"HiCritLo thresh"}, {0xffff,0xff, 0xff, 0x81, 0x59,0xff,0xff, 0,"HiC thresh OK now"}, {0xffff,0xff, 0xff, 0x81, 0x5A,0xff,0xff, 3,"HiURecLo thresh"}, {0xffff,0xff, 0xff, 0x81, 0x5B,0xff,0xff, 0,"HiU thresh OK now"} }; #define NENTID 53 static struct { char * str; uchar styp; } entitymap[NENTID] = { /* 00 */ { "unspecified", 0x00 }, /* 01 */ { "other", 0x00 }, /* 02 */ { "unknown", 0x00 }, /* 03 */ { "Processor", 0x07 }, /* 04 */ { "Disk", 0x00 }, /* 05 */ { "Peripheral bay", 0x0D }, /* 06 */ { "Management module", 0x00 }, /* 07 */ { "System board", 0x00 }, /* 08 */ { "Memory module", 0x00 }, /* 09 */ { "Processor module", 0x00 }, /* 10 */ { "Power supply", 0x08 }, /* 11 */ { "Add-in card", 0x00 }, /* 12 */ { "Front panel bd", 0x00 }, /* 13 */ { "Back panel board", 0x00 }, /* 14 */ { "Power system bd", 0x00 }, /* 15 */ { "Drive backplane", 0x00 }, /* 16 */ { "Expansion board", 0x00 }, /* 17 */ { "Other system board", 0x15 }, /* 18 */ { "Processor board", 0x15 }, /* 19 */ { "Power unit", 0x09 }, /* 20 */ { "Power module", 0x08 }, /* 21 */ { "Power distr board", 0x09 }, /* 22 */ { "Chassis back panel bd", 0x00 }, /* 23 */ { "System Chassis", 0x00 }, /* 24 */ { "Sub-chassis", 0x00 }, /* 25 */ { "Other chassis board", 0x15 }, /* 26 */ { "Disk Drive Bay", 0x0D }, /* 27 */ { "Peripheral Bay", 0x00 }, /* 28 */ { "Device Bay", 0x00 }, /* 29 */ { "Fan", 0x04 }, /* 30 */ { "Cooling unit", 0x0A }, /* 31 */ { "Cable/interconnect", 0x1B }, /* 32 */ { "Memory device ", 0x0C }, /* 33 */ { "System Mgt Software", 0x28 }, /* 34 */ { "BIOS", 0x00 }, /* 35 */ { "Operating System", 0x1F }, /* 36 */ { "System bus", 0x00 }, /* 37 */ { "Group", 0x00 }, /* 38 */ { "Remote Mgt Comm Device", 0x00 }, /* 39 */ { "External Environment", 0x00 }, /* 40 */ { "battery", 0x29 }, /* 41 */ { "Processing blade", 0x00 }, /* 43 */ { "Processor/memory module", 0x0C }, /* 44 */ { "I/O module", 0x15 }, /* 45 */ { "Processor/IO module", 0x00 }, /* 46 */ { "Mgt Controller Firmware", 0x0F }, /* 47 */ { "IPMI Channel", 0x00 }, /* 48 */ { "PCI Bus", 0x00 }, /* 49 */ { "PCI Express Bus", 0x00 }, /* 50 */ { "SCSI Bus", 0x00 }, /* 51 */ { "SATA/SAS bus", 0x00, }, /* 52 */ { "Processor FSB", 0x00 } }; char *decode_entity_id(int id) { char *str = NULL; if (id < 0) id = 0; if (id > NENTID) { if (id >= 0x90 && id < 0xB0) str = "Chassis-specific"; else if (id >= 0xB0 && id < 0xD0) str = "Board-specific"; else if (id >= 0xD0 && id <= 0xFF) str = "OEM-specific"; else str = "invalid"; } else str = entitymap[id].str; return(str); } uchar entity2sensor_type(uchar ent) { uchar stype = 0x12; uchar b; if (ent < NENTID) { b = entitymap[ent].styp; if (fdebug) printf("entity2sensor_type(%x,%s), stype=%x\n",ent, entitymap[ent].str,b); if (b != 0) stype = b; } return(stype); } static char *mem_str(int off) { char *pstr; switch(off) { case 0x00: pstr = "Correctable ECC"; break; case 0x01: pstr = "Uncorrectable ECC"; break; case 0x02: pstr = "Parity"; break; case 0x03: pstr = "Memory Scrub Failed"; break; case 0x04: pstr = "Memory Device Disabled"; break; case 0x05: pstr = "ECC limit reached" ; break; case 0x07: pstr = "ConfigError: SMI Link Lane FailOver"; break; /*Quanta QSSC_S4R*/ case 0x08: pstr = "Spare"; break; /*uses data3 */ case 0x09: pstr = "Memory Automatically Throttled"; break; case 0x0A: pstr = "Critical Overtemperature"; break; default: pstr = "Other Memory Error"; break; } return(pstr); } #if defined(METACOMMAND) /* METACOMMAND is defined for ipmiutil meta-command build. */ /* These can only be external if linked with non-core objects. */ extern int GetSDR(int recid, int *recnext, uchar *sdr, int szsdr, int *slen); extern double RawToFloat(uchar raw, uchar *psdr); extern char *get_unit_type(uchar iunit, uchar ibase, uchar imod, int flg); extern int find_sdr_by_snum(uchar *psdr,uchar *pcache, uchar snum, uchar sa); extern int GetSensorType(int snum, uchar *stype, uchar *rtype); extern char * get_mfg_str(uchar *rgmfg, int *pmfg); /*from ihealth.c*/ extern int decode_post_intel(int prod, ushort code, char *outbuf,int szbuf); extern int decode_sel_kontron(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_kontron.c*/ extern int decode_sel_fujitsu(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_fujitsu.c*/ extern int decode_sel_intel(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_intel.c*/ extern int decode_sel_supermicro(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_supermicro.c*/ extern int decode_sel_lenovo(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_lenovo.c*/ extern int decode_sel_quanta(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_quanta.c*/ extern int decode_sel_newisys(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_newisys.c*/ extern int decode_sel_dell(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_dell.c*/ extern int decode_mem_intel(int prod, uchar b2, uchar b3, char *desc, int *psz); /*oem_intel.c*/ extern int decode_mem_supermicro(int prod, uchar b2, uchar b3, char *desc, int *psz); /*oem_intel.c*/ #else /* else it could be ALONE or for a libipmiutil.a build */ static int default_mem_desc(uchar b2, uchar b3, char *desc, int *psz) { int array, dimm, n; uchar bdata; if (desc == NULL || psz == NULL) return -1; if (b3 == 0xff) bdata = b2; /*ff is reserved*/ else bdata = b3; /* normal case */ array = (bdata & 0xc0) >> 6; dimm = bdata & 0x3f; if (bdata == 0xFF) n = sprintf(desc,DIMM_UNKNOWN); else n = sprintf(desc,DIMM_NUM,dimm); *psz = n; return(0); } static int decode_mem_intel(int prod, uchar b2, uchar b3, char *desc, int *psz) { return(default_mem_desc(b2,b3,desc,psz)); } static int decode_mem_supermicro(int prod, uchar b2, uchar b3, char *desc, int *psz) { return(default_mem_desc(b2,b3,desc,psz)); } static char * get_mfg_str(uchar *rgmfg, int *pmfg) { /* standalone routine here for minimal set of strings*/ char *mfgstr; int mfg; mfg = rgmfg[0] + (rgmfg[1] << 8) + (rgmfg[2] << 16); if (pmfg != NULL) *pmfg = mfg; if (mfg == VENDOR_INTEL) mfgstr = "Intel"; else if (mfg == VENDOR_MICROSOFT) mfgstr = "Microsoft"; else if (mfg == VENDOR_KONTRON) mfgstr = "Kontron"; else if (mfg == VENDOR_SUPERMICROX) mfgstr = "SuperMicro"; else if (mfg == VENDOR_SUPERMICRO) mfgstr = "SuperMicro"; else mfgstr = " "; return (mfgstr); } #ifdef SENSORS_OK extern int GetSDR(int recid, int *recnext, uchar *sdr, int szsdr, int *slen); extern double RawToFloat(uchar raw, uchar *psdr); extern char *get_unit_type(uchar iunit, uchar ibase, uchar imod, int flg); extern int find_sdr_by_snum(uchar *psdr,uchar *pcache, uchar snum, uchar sa); extern int GetSensorType(int snum, uchar *stype, uchar *rtype); #else static int GetSDR(int recid, int *recnext, uchar *sdr, int szsdr, int *slen) { return(-1); } static double RawToFloat(uchar raw, uchar *psdr) { return((double)raw); } static char *get_unit_type(uchar iunit, uchar ibase, uchar imod, int flg) { return(""); }; static int find_sdr_by_snum(uchar *psdr,uchar *pcache, uchar snum, uchar sa) { return(-1); } static int GetSensorType(int snum, uchar *stype, uchar *rtype) { return(-1); } #endif #endif #if defined(ALONE) /* ALONE is defined for ievents standalone build. */ /* IPMI Spec says that this is an index into the DIMMs. * Walking through the SDRs dynamically would be too slow, * but isel -e has an SDR cache which could be leveraged, * however not all platforms have DIMM slot SDRs. * The BIOS references the DIMM Locator descriptors from * SMBIOS type 17, and the descriptions vary for each baseboard. * We'll just show the index here by default. * Do the SMBIOS lookup if not standalone build. */ int g_vend_id = VENDOR_INTEL; /*assume a default of Intel*/ int strlen_(const char *s) { return((int)strlen(s)); } char *get_iana_str(int vend) { return(""); } /*from subs.c*/ void set_iana(int vend) { g_vend_id = vend; return; } char is_remote(void) { return(1); } /* act as if remote with standalone */ int get_MemDesc(int array, int idimm, char *desc, int *psz) { /* standalone, so use the default method for the DIMM index */ return(default_mem_desc(array,idimm,desc,psz)); } void get_mfgid(int *vend, int *prod) { if ((vend == NULL) || (prod == NULL)) return; *vend = g_vend_id; /*assume a default of Intel*/ *prod = 0; } char * decode_rv(int rv) { static char mystr[30]; char *pstr; switch(rv) { case 0: pstr = "completed successfully"; break; case ERR_BAD_PARAM: pstr = "invalid parameter"; break; case ERR_USAGE: pstr = "usage or help requested"; break; case ERR_FILE_OPEN: pstr = "cannot open file"; break; case ERR_NOT_FOUND: pstr = "item not found"; break; default: sprintf(mystr,"error = %d",rv); pstr = mystr; break; } return(pstr); } void dump_buf(char *tag, uchar *pbuf, int sz, char fshowascii) { uchar line[17]; uchar a; int i, j; char *stag; FILE *fpdbg1; fpdbg1 = stdout; if (tag == NULL) stag = "dump_buf"; /*safety valve*/ else stag = tag; fprintf(fpdbg1,"%s (len=%d): ", stag,sz); line[0] = 0; line[16] = 0; j = 0; if (sz < 0) { fprintf(fpdbg1,"\n"); return; } /*safety valve*/ for (i = 0; i < sz; i++) { if (i % 16 == 0) { line[j] = 0; j = 0; fprintf(fpdbg1,"%s\n %04x: ",line,i); } if (fshowascii) { a = pbuf[i]; if (a < 0x20 || a > 0x7f) a = '.'; line[j++] = a; } fprintf(fpdbg1,"%02x ",pbuf[i]); } if (fshowascii) { if ((j > 0) && (j < 16)) { /* space over the remaining number of hex bytes */ for (i = 0; i < (16-j); i++) fprintf(fpdbg1," "); } else j = 16; line[j] = 0; } fprintf(fpdbg1,"%s\n",line); return; } int ipmi_cmdraw(uchar cmd, uchar netfn, uchar sa, uchar bus, uchar lun, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { return(-9); } #else /* ipmicmd.h has ipmi_cmdraw() */ extern int get_MemDesc(int array, int dimm, char *desc, int *psz); /*mem_if.c*/ extern void get_mfgid(int *vend, int *prod); /*from ipmicmd.c*/ extern char is_remote(void); /*from ipmicmd.c*/ extern char * decode_rv(int rv); /*from ipmilan.c*/ extern void dump_buf(char *tag, uchar *pbuf, int sz, char fshowascii); #endif static int decode_mem_default(uchar b1, uchar b2, uchar b3, uchar etype, char *desc, int *psz) { int cpu, dimm, n; int rv = -1; int offset = 0; uchar bdata; if ((desc == NULL) || (psz == NULL)) return -1; offset = (b1 & 0x0F); if ((b1 & 0x20) != 0) { bdata = b3; } /*dimm data in byte 3*/ else if (b2 == 0xff) { bdata = b3; } /*ff is reserved*/ else { bdata = b2; } /*if here, should also have (b1 & 0x80)*/ if (bdata == 0xFF) n = sprintf(desc,DIMM_UNKNOWN); else { cpu = (bdata & 0xc0) >> 6; dimm = (bdata & 0x3F); n = sprintf(desc,DIMM_NUM,dimm); /* Use DMI if we get confirmation about cpu/dimm indices. */ if (! is_remote()) { fsm_debug = fdebug; rv = get_MemDesc(cpu,dimm,desc,psz); if (rv != 0) n = sprintf(desc,DIMM_NUM,dimm); } } *psz = n; if (fdebug) printf("decode_mem_default: bdata=%02x(%d) %d dimm=%d\n",bdata,bdata,offset,dimm); rv = 0; return(rv); } /*end decode_mem_default*/ int new_event(uchar *buf, int len) { int rlen, rv; uchar idata[8]; uchar rdata[4]; uchar cc; /* Platform Event Message command, inputs: offset 0 = GeneratorID, 0x20 for BMC, 0x21 for SMI/kernel, 0x33 for BIOS 1 = EVM Rev, 3=IPMI10, 4=IPMI15 2 = Sensor Type 3 = Sensor Number 4 = Event Type (0x6f = sensor specific) 5 = data1 6 = data2 7 = data3 */ idata[0] = buf[0]; /*GenID on input is two bytes, but one byte here*/ idata[1] = buf[2]; idata[2] = buf[3]; idata[3] = buf[4]; idata[4] = buf[5]; idata[5] = buf[6]; idata[6] = buf[7]; idata[7] = buf[8]; rlen = sizeof(rdata); rv = ipmi_cmdraw(0x02, NETFN_SEVT, BMC_SA, PUBLIC_BUS, BMC_LUN, idata,8, rdata,&rlen,&cc, fdebug); if (fdebug) printf("platform_event: rv = %d, cc = %02x\n",rv,cc); if ((rv == 0) && (cc != 0)) rv = cc; return(rv); } char *get_sensor_type_desc(uchar stype) { int i; static char stype_desc[25]; char *pstr; if (stype == 0xF3) i = 0x2D; /*OEM SMI*/ else if (stype == 0xDC) i = 0x2E; /*NM*/ else if (stype == SMI_SA) i = BMC_SA; /*SMI -> BMC*/ else if (stype >= NSTYPES) i = 0; else i = stype; if (i == 0) { /* reserved, show the raw sensor_type also */ if (stype == 0xCF) strncpy(stype_desc,"OEM Board Reset", sizeof(stype_desc)); else if (stype >= 0xC0) sprintf(stype_desc,"OEM(%02x)",stype); else sprintf(stype_desc,"%s(%02x)",sensor_types[i],stype); /*reserved*/ pstr = (char *)stype_desc; } else { pstr = (char *)sensor_types[i]; } return(pstr); } /*------------------------------------------------------------------------ * get_misc_desc * Uses the sens_desc array to decode misc entries not otherwise handled. * Called by decode_sel_entry *------------------------------------------------------------------------*/ char * get_misc_desc(ushort genid, uchar type, uchar num, uchar trig, uchar data1, uchar data2, uchar data3, uchar *sev) { int i; char *pstr = NULL; /* Use sens_desc array for other misc descriptions */ data1 &= 0x0f; /*ignore top half of sensor offset for matching */ for (i = 0; i < NSDESC; i++) { if ((sens_desc[i].s_typ == 0xff) || (sens_desc[i].s_typ == type)) { if (sens_desc[i].s_num != 0xff && sens_desc[i].s_num != num) continue; if (sens_desc[i].genid != 0xffff && sens_desc[i].genid != genid) continue; if (sens_desc[i].evtrg != 0xff && sens_desc[i].evtrg != trig) continue; if (sens_desc[i].data1 != 0xff && (sens_desc[i].data1 & 0x0f) != (data1 & 0x0f)) continue; if (sens_desc[i].data2 != 0xff && sens_desc[i].data2 != data2) continue; if (sens_desc[i].data3 != 0xff && sens_desc[i].data3 != data3) continue; /* have a match, use description */ pstr = (char *)sens_desc[i].desc; if (sev != NULL) *sev = sens_desc[i].sev; break; } } /*end for*/ return(pstr); } /* end get_misc_desc() */ time_t utc2local(time_t t) { struct tm * tm_tmp; int gt_year,gt_yday,gt_hour,lt_year,lt_yday,lt_hour; int delta_hour; time_t lt; // convert UTC time to local time // i.e. number of seconds from 1/1/70 0:0:0 1970 GMT tm_tmp=gmtime(&t); gt_year=tm_tmp->tm_year; gt_yday=tm_tmp->tm_yday; gt_hour=tm_tmp->tm_hour; tm_tmp=localtime(&t); lt_year=tm_tmp->tm_year; lt_yday=tm_tmp->tm_yday; lt_hour=tm_tmp->tm_hour; delta_hour=lt_hour - gt_hour; if ( (lt_year > gt_year) || ((lt_year == gt_year) && (lt_yday > gt_yday)) ) delta_hour += 24; if ( (lt_year < gt_year) || ((lt_year == gt_year) && (lt_yday < gt_yday)) ) delta_hour -= 24; if (fdebug) printf("utc2local: delta_hour = %d\n",delta_hour); lt = t + (delta_hour * 60 * 60); return(lt); } void fmt_time(time_t etime, char *buf, int bufsz) { time_t t; if (bufsz < 18) printf("fmt_time: buffer size should be >= 18\n"); if (futc) t = etime; else t = utc2local(etime); /*assume input time is UTC*/ strncpy(buf,"00/00/00 00:00:00",bufsz); strftime(buf,bufsz, "%x %H:%M:%S", gmtime(&t)); /*or "%x %T"*/ return; } /* * findmatch * Finds a matching pattern within a string buffer. * returns offset of the match if found, or -1 if not found. */ int findmatch(char *buffer, int sbuf, char *pattern, int spattern, char figncase) { int c, i, j, imatch; j = 0; imatch = 0; for (j = 0; j < sbuf; j++) { if ((sbuf - j) < spattern && imatch == 0) return(-1); c = buffer[j]; if (c == pattern[imatch]) { imatch++; } else if ((figncase == 1) && ((c & 0x5f) == (pattern[imatch] & 0x5f))) { imatch++; } else if (pattern[imatch] == '?') { /*wildcard char*/ imatch++; } else { if (imatch > 0) { if (j > 0) j--; /* try again with the first match char */ imatch = 0; } } if (imatch == spattern) break; } if (imatch == spattern) { i = (j+1) - imatch; /*buffer[i] is the match */ return(i); } else return (-1); /*not found*/ } /*end findmatch */ /* * file_grep * Search (grep) for a pattern within a file. * Inputs: fname = file name to search * pattn = pattern string to search for * line = line buffer * sline = size of line buffer * bmode = 0 to use last match, * 1 to use first match, * 2 to specify starting line number & use first match. * nret = IN: starting char offset, OUT: num chars read * Outputs: line = resulting line (stringified) that matches pattn * nret = resulting line number within file (0-based) * returns 0 if match, < 0 if error */ int file_grep(char *fname, char *pattn, char *line, int sline, char bmode, int *nret) { FILE *fp; char buff[1024]; int ret = ERR_NOT_FOUND; int i, plen, blen; int n = 0; int nstart = 0; int bufsz; if ((bmode == 2) && (nret != NULL)) nstart = *nret; bufsz = sizeof(buff); fp = fopen(fname,"r"); if (fp == NULL) { if (fdebug) printf("file_grep: Cannot open %s\n",fname); ret = ERR_FILE_OPEN; /*cannot open file*/ } else { plen = strlen_(pattn); fseek(fp, nstart, SEEK_SET); n = nstart; while (fgets(buff, bufsz, fp) != NULL) { blen = strlen_(buff); /* check for pattern in this line */ i = findmatch(&buff[0],blen,pattn,plen,0); if (i >= 0) { ret = 0; /* found it, success */ if ((line != NULL) && sline > 1) { if (blen >= sline) blen = sline - 1; strncpy(line,buff,blen); line[blen] = 0; /*stringify*/ } if (nret != NULL) *nret = n + i + plen; if (bmode > 0) break; /* else keep looking, use last one if multiples */ } n += blen; /*number of chars*/ } /*end while*/ fclose(fp); } /*end else file opened*/ return(ret); } /*end file_grep*/ char *get_sev_str(int val) { if (val >= NSEV) val = SEV_CRIT; return(sev_str[val]); } /* The htoi() routine is available in subs.c, but ievents.c also * needs a local copy of it if built with -DALONE. */ static uchar _htoi(char *inhex) { // char rghex[16] = "0123456789ABCDEF"; uchar val; char c; c = inhex[0] & 0x5f; /* force cap */ if (c > '9') c += 9; /* c >= 'A' */ val = (c & 0x0f) << 4; c = inhex[1] & 0x5f; /* force cap */ if (c > '9') c += 9; /* c >= 'A' */ val += (c & 0x0f); return(val); } /* * set_sel_opts is used to specify options for showing/decoding SEL events. * sensdesc : 0 = simple, no sensor descriptions * 1 = get sensor descriptions from sdr cache * 2 = get sensor descriptions from sensor file (-s) * canon : 0 = normal output * 1 = canonical, delimited output * sdrs : NULL = no sdr cache, dynamically get sdr cache if sensdesc==1 * ptr = use this pointer as existing sdr cache if sensdesc==1 * fdbg : 0 = normal mode * 1 = debug mode * futc : 0 = normal mode * 1 = show raw UTC time */ void set_sel_opts(int sensdesc, int canon, void *sdrs, char fdbg, char utc) { fsensdesc = (char)sensdesc; /*get extended sensor descriptions*/ fcanonical = (char)canon; /*show canonical, delimited output*/ if (sdrcache == NULL) sdrcache = sdrs; else printf("Warning: attempted to set_sel_opts(sdrcache) twice\n"); fdebug = fdbg; futc = utc; } /* get_sensdesc - get the sensor tag/description from the sensor.out file */ int get_sensdesc(uchar sa, int snum, char *sensdesc, int *pstyp, int *pidx) { int rv, i, j, len, idx; char pattn[20]; char sensline[100]; int nline = 0; uchar sa2; char *sfil; char *p; if (sensdesc == NULL) return ERR_BAD_PARAM; sensdesc[0] = 0; if (fdebug) printf("sensdesc(%02x,%02x) with %s\n",sa,snum,sensfil); sprintf(pattn,"snum %02x",snum); for (j = 0; j < 3; j++) { sfil = sensfil; /* Use this logic for both Linux and Windows */ rv = file_grep(sfil,pattn, sensline, sizeof(sensline), 2, &nline); if (rv != 0) { if (rv == ERR_FILE_OPEN) { if (fdebug) fprintf(stdout,"Cannot open file %s\n",sfil); sfil = sensfil2; rv = file_grep(sfil, pattn, sensline,sizeof(sensline), 2, &nline); if (fdebug && rv == ERR_FILE_OPEN) fprintf(stdout,"Cannot open file %s\n",sfil); } if (rv != ERR_FILE_OPEN) { if (fdebug) printf("Cannot find snum %02x in file %s\n",snum,sfil); rv = ERR_NOT_FOUND; } break; } if (rv == 0) { idx = _htoi(&sensline[2]) + (_htoi(&sensline[0]) << 8); sa2 = _htoi(&sensline[20]); if (fdebug) printf("sensdesc(%02x,%02x) found snum for sa %02x at offset %d\n", sa,snum,sa2,nline); if (sa == sa2) { /* truncate the sensor line to omit the reading */ len = strlen_(sensline); for (i = 0; i < len; i++) if (sensline[i] == '=') { sensline[i] = 0; break; } if (sensline[i-1] != ' ') { sensline[i] = ' '; sensline[++i] = 0; } /* skip to just the sensor description from the SDR */ p = strstr(sensline,"snum"); p += 8; /* skip 'snum 11 ' */ strcpy(sensdesc,p); if (pstyp != NULL) *pstyp = _htoi(&sensline[25]); if (pidx != NULL) *pidx = idx; break; } } } /*end-for j*/ if (j >= 3) rv = ERR_NOT_FOUND; /*not found*/ return(rv); } char *get_genid_str(ushort genid) { static char genstr[10]; char *gstr; int i; sprintf(genstr,"%04x",genid); gstr = genstr; /* default */ for (i = 0; i < NGDESC; i++) { if (gen_desc[i].g_id == genid) { gstr = (char *)gen_desc[i].desc; break; } } return(gstr); } static int is_threshold(uchar evtrg, ushort genid) { int val = 0; /*false*/ /* It would be better to check the SDR (if Full supports thresholds), * but we do not always have that available. */ if ( ((genid == BMC_SA) || /*from BMC*/ (genid == SMI_SA) || /*from SMI (simulated)*/ (genid == thr_sa)) && /*from HSC, or other*/ ((evtrg == 0x01) || /*threshold evt*/ (evtrg == 0x81))) /*threshold ok*/ val = 1; return(val); } static void get_sdr_tag(uchar *sdr, char *tagstr) { int i, j, k, len; len = sdr[4] + 5; switch(sdr[3]) { case 0x01: k = 48; break; /*full sensor*/ case 0x02: k = 32; break; /*compact sensor*/ case 0x03: k = 17; break; /*compact sensor*/ case 0x10: k = 16; break; /*compact sensor*/ case 0x11: k = 16; break; /*compact sensor*/ case 0x12: k = 16; break; /*compact sensor*/ default: k = 0; break; } if (k > 0 && k < len) { i = len - k; for (j = 0; j < i; j++) { if (sdr[k+j] == 0) break; tagstr[j] = sdr[k+j]; } tagstr[j++] = ' '; tagstr[j] = 0; } } /* * get_sensor_tag * * Get the sensor tag (name) based on the sensor number, etc. * Use one of 3 methods to get this: * 1) Parse the sensor_out.txt (sensfil) if fsensdesc==2. * Use this method if not METACOMMAND or if user-specified. * 2) Find this SDR in the SDR cache, if available. * 3) Do a GetSDR command function now (can be slow) * Input parameters: * isdr = index of SDR, use 0 if unknown * genid = genid or sa (slave address) of this sensor * snum = sensor number of this sensor * tag = pointer to a buffer for the sensor tag (min 17 bytes) * sdr = pointer to buffer for the SDR if found (usu <= 65 bytes) * szsdr = size of the SDR buffer * Output parameters: * tag = filled in with sensor tag (name) * sdr = filled in with SDR, if found. * Returns: * 0 if tag and sdr are found. * ERR_NOT_FOUND if SDR is not found (but tag may be found) * other errors, see ipmicmd.h */ int get_sensor_tag(int isdr, int genid, uchar snum, char *tag, uchar *sdr, int szsdr) { int rv, i, j = 0; if (tag == NULL) return(ERR_BAD_PARAM); if (sdr == NULL) return(ERR_BAD_PARAM); if (genid == SMS_SA) genid = BMC_SA; /*parse Sms as if BMC*/ if (genid == SMI_SA) genid = BMC_SA; /*parse SMI as if BMC*/ tag[0] = 0; if (fsensdesc == 2) { /*not connected, so do not try to GetSDR*/ rv = get_sensdesc((uchar)genid, snum, tag,NULL,&isdr); rv = ERR_NOT_FOUND; /*got tag, but did not get SDR*/ } else if (sdrcache != NULL) { /*valid sdr cache*/ rv = find_sdr_by_snum(sdr,sdrcache, snum, (uchar)genid); if (rv == 0) { get_sdr_tag(sdr,tag); } } else { /* try to get this SDR */ rv = GetSDR(isdr, &i,sdr,szsdr,&j); if (fdebug) printf("get_sensor_tag GetSDR[%x] rv=%d sz=%d\n",isdr,rv,j); if (rv == 0) { get_sdr_tag(sdr,tag); } else { /* use a saved sensor.out file */ rv = get_sensdesc((uchar)genid, snum, tag,NULL,&isdr); if (rv != 0) tag[0] = 0; rv = ERR_NOT_FOUND; /*got tag, but did not get SDR*/ } } if (rv != 0) strcpy(tag,"na "); if (fdebug) printf("get_sensor_tag(%d): find_sdr(%x,%x) rv=%d tag=/%s/\n", fsensdesc,snum,genid,rv,tag); return(rv); } static int decode_post_oem(int vend, int prod, ushort code, char *outbuf,int szbuf) { int rv = -1; if (outbuf == NULL || szbuf == 0) return(rv); #if defined(METACOMMAND) switch(vend) { case VENDOR_INTEL: rv = decode_post_intel(prod,code,outbuf,szbuf); break; default: break; } #endif if (rv != 0) snprintf(outbuf,szbuf,"POST Code %04x",code); return(rv); } static int decode_sel_oem(int vend, uchar *pevt, char *outbuf,int szbuf, char fdesc, char fdbg) { int rv = -1; #ifdef METACOMMAND switch(vend) { case VENDOR_KONTRON: rv = decode_sel_kontron(pevt,outbuf,szbuf,fdesc,fdbg); break; case VENDOR_FUJITSU: /* Fujitsu does an OEM IPMI command to return the decoded string. */ rv = decode_sel_fujitsu(pevt,outbuf,szbuf,fdesc,fdbg); break; case VENDOR_INTEL: thr_sa = HSC_SA; /* HSC_SA(0xC0) by default */ rv = decode_sel_intel(pevt,outbuf,szbuf,fdesc,fdbg); break; case VENDOR_PEPPERCON: /*SuperMicro AOC-SIMSO*/ if (pevt[7] == 0x40) pevt[7] = BMC_SA; /*genid broken, fix it*/ break; case VENDOR_MAGNUM: case VENDOR_SUPERMICRO: case VENDOR_SUPERMICROX: rv = decode_sel_supermicro(pevt,outbuf,szbuf,fdesc,fdbg); break; case VENDOR_LENOVO: case VENDOR_LENOVO2: rv = decode_sel_lenovo(pevt,outbuf,szbuf,fdesc,fdbg); break; case VENDOR_QUANTA: rv = decode_sel_quanta(pevt,outbuf,szbuf,fdesc,fdbg); break; case VENDOR_NEWISYS: rv = decode_sel_newisys(pevt,outbuf,szbuf,fdesc,fdbg); break; case VENDOR_DELL: rv = decode_sel_dell(pevt,outbuf,szbuf,fdesc,fdbg); break; default: break; } #endif if (fdebug) printf("decode_sel_oem(0x%04x) rv=%d\n",vend,rv); return(rv); } #define N_PWRUNIT 12 static struct { uchar trg; uchar data1; uchar sev; char *msg; } pwrunit_evts[N_PWRUNIT] = { { 0x6f, 0x00, 0,"Power Off "}, { 0x6f, 0x01, 0,"Power Cycle "}, { 0x6f, 0x02, 0,"240VA power down"}, { 0x6f, 0x03, 0,"Interlock power down"}, { 0x6f, 0x04, 1,"AC Lost"}, { 0x6f, 0x05, 2,"Soft Powerup failure"}, { 0x6f, 0x06, 2,"Failure detected"}, { 0x6f, 0x07, 1,"Predictive failure"}, { 0xef, 0x00, 0,"Power Restored"}, { 0xef, 0x01, 0,"Power Cycle ok"}, { 0xef, 0x04, 0,"AC Regained"}, { 0xef, 0x06, 0,"Failure OK now"} }; static int decode_pwrunit(uchar trg, uchar data1, char *pstr, uchar *psev) { int rv = -1; int i, j; j = data1 & 0x0f; if (psev == NULL || pstr == NULL) return(rv); sprintf(pstr,"_"); for (i = 0; i < N_PWRUNIT; i++) { if ((trg == pwrunit_evts[i].trg) && (j == pwrunit_evts[i].data1)) { *psev = pwrunit_evts[i].sev; sprintf(pstr,"%s",pwrunit_evts[i].msg); rv = 0; } } return(rv); } #define N_REDUN 16 static struct { uchar trg; uchar data1; uchar sev; char *msg; } redund_evts[N_REDUN] = { { 0x0B, 0x00, SEV_INFO,"Redundancy OK "}, { 0x0B, 0x01, SEV_MAJ, "Redundancy Lost"}, { 0x0B, 0x02, SEV_MAJ, "Redundancy Degraded"}, { 0x0B, 0x03, SEV_MAJ, "Not Redundant"}, { 0x0B, 0x04, SEV_MAJ, "Sufficient Resources"}, { 0x0B, 0x05, SEV_CRIT,"Insufficient Resources"}, { 0x0B, 0x06, SEV_MAJ, "Fully-to-Degraded"}, { 0x0B, 0x07, SEV_MIN, "NonR-to-Degraded"}, { 0x8B, 0x00, SEV_MAJ, "Redundancy NOT ok"}, { 0x8B, 0x01, SEV_INFO,"Redundancy Regained"}, { 0x8B, 0x02, SEV_INFO,"Redundancy Restored"}, { 0x8B, 0x03, SEV_INFO,"Redundant"}, { 0x8B, 0x04, SEV_MAJ, "Not Sufficient"}, { 0x8B, 0x05, SEV_INFO,"Not Insufficient"}, { 0x8B, 0x06, SEV_INFO,"Degraded-to-Fully"}, { 0x8B, 0x07, SEV_MIN, "Degraded-to-NonR"} }; static int decode_redund(uchar trg, uchar data1, char *pstr, uchar *psev) { int rv = -1; int i, j; j = data1 & 0x0f; if (psev == NULL || pstr == NULL) return(rv); sprintf(pstr,"_"); for (i = 0; i < N_REDUN; i++) { if ((trg == redund_evts[i].trg) && (j == redund_evts[i].data1)) { *psev = redund_evts[i].sev; sprintf(pstr,"%s",redund_evts[i].msg); rv = 0; } } return(rv); } #define N_PRESENT 2 static char * present_str[N_PRESENT] = { /* Availability, evtype 0x08 */ /*00*/ "Absent", /*Absent/Removed*/ /*01*/ "Present"}; /*Present/Inserted*/ static int decode_presence(uchar trg, uchar data1, char *pstr, uchar *psev) { int rv = -1; int i; if (psev == NULL || pstr == NULL) return(rv); sprintf(pstr,"_"); *psev = SEV_INFO; i = data1 & 0x0f; if (trg == 0x08) { if (i >= N_PRESENT) i = N_PRESENT - 1; sprintf(pstr,"%s",present_str[i]); rv = 0; } else if (trg == 0x88) { if (data1 & 0x01) i = 0; else i = 1; sprintf(pstr,"%s",present_str[i]); } return(rv); } void format_event(ushort id, time_t timestamp, int sevid, ushort genid, char *ptype, uchar snum, char *psens, char *pstr, char *more, char *outbuf, int outsz) { char sensdesc[36]; char timestr[40]; uchar sdr[MAX_BUFFER_SIZE]; /*sdr usu <= 65 bytes*/ char *gstr; int isdr = 0; int rv; if (more == NULL) more = ""; if (psens != NULL) ; /* use what was passed in */ else { /*psens==NULL, may need to get tag*/ psens = &sensdesc[0]; sensdesc[0] = 0; if (fsensdesc) { rv = get_sensor_tag(isdr,genid,snum,psens,sdr,sizeof(sdr)); if (fdebug) printf("get_sensor_tag(%x) rv = %d\n",snum,rv); } } fmt_time(timestamp, timestr, sizeof(timestr)); gstr = get_genid_str(genid); /*get Generator ID / Source string*/ if (fcanonical) { snprintf(outbuf,outsz,"%04x %c %s %c %s %c %s %c %s %c %s %c %s %s\n", id, bdelim, timestr, bdelim, get_sev_str(sevid), bdelim, gstr, bdelim, ptype, bdelim, psens, bdelim, pstr, more ); } else { snprintf(outbuf,outsz,"%04x %s %s %s %s #%02x %s %s %s\n", id, timestr, get_sev_str(sevid), gstr, ptype, snum, psens, pstr, more); } return; } /*------------------------------------------------------------------------ * decode_sel_entry * Parse and decode the SEL record into readable format. * This routine is constructed so that it could be used as a library * function. * Note that this routine outputs 14 of the 16 bytes in either text or * raw hex form. For the two bytes not shown: * . record type: usually = 02, is shown otherwise (e.g. OEM type) * . event msg revision: =03 if IPMI 1.0, =04 if IPMI 1.5 or IPMI 2.0 * * Input: psel, a pointer to the IPMI SEL record (16 bytes) * Output: outbuf, a description of the event, max 80 chars. * Called by: ReadSEL() * Calls: fmt_time() get_misc_desc() * * IPMI SEL record format (from IPMI Table 32-1): * Offset Meaning * 0-1 Record ID (LSB, MSB) * 2 Record Type (usu 0x02) * 3-6 Timestamp (LS byte first) * 7-8 Generator ID (LS first, usually 20 00) * 9 Event message format (=0x04, or =0x03 if IPMI 1.0) * 10 Sensor type * 11 Sensor number * 12 Event Dir | Event Type * 13 Event Data 1 * 14 Event Data 2 * 15 Event Data 3 *------------------------------------------------------------------------*/ int decode_sel_entry( uchar *pevt, char *outbuf, int szbuf) { char mystr[80] = "panic(123)"; /*used for panic string*/ char *pstr; char poststr[80] = "OEM Post Code = %x%x"; char sensstr[50]; char datastr[64]; char cstr[4]; char *psensstr; int i, j, k, n; time_t eventTime; uchar *evtime; char timebuf[40]; uchar *pc; SEL_RECORD *psel; uchar fdeassert = 0; uchar etype; uchar sev = SEV_INFO; uchar sdr[MAX_BUFFER_SIZE]; /*sdr usu <= 65 bytes*/ int isdr = 0; int vend, prod; int rv = 0; char fhave_sdr = 0; char mdesc[80]; /*used for oem memory description*/ int msz; char *mfgstr; int mfg; if (outbuf == NULL) return(ERR_BAD_PARAM); if (pevt == NULL) { outbuf[0] = 0; return(ERR_BAD_PARAM); } get_mfgid(&vend,&prod); /*saved from ipmi_getdeviceid */ psel = (SEL_RECORD *)pevt; etype = psel->event_trigger; j = decode_sel_oem(vend,pevt,outbuf,szbuf,fsensdesc,fdebug); if (j == 0) return(0); /*successful, have the description*/ if (psel->record_type == RT_OEMIU) { /* 0xDB usu ipmiutil OEM string */ /* ipmiutil OEM event with 9-byte string */ pc = (uchar *)&psel->generator_id; /* offset 7 */ evtime = (uchar *)&psel->timestamp; eventTime = evtime[0] + (evtime[1] << 8) + (evtime[2] << 16) + (evtime[3] << 24); fmt_time(eventTime, timebuf, sizeof(timebuf)); if (fcanonical) sprintf(outbuf,"%04x %c %s %c %s %c %02x %c OEM Event ", psel->record_id, bdelim, timebuf, bdelim, get_sev_str(sev), bdelim, psel->record_type, bdelim); else sprintf(outbuf,"%04x %s %s %02x OEM Event ", psel->record_id, timebuf, get_sev_str(sev), psel->record_type); j = strlen_(outbuf); for (i = 0; i < 9; i++) { /* 7:16 = 9 bytes string data */ if (pc[i] == 0) outbuf[j] = ' '; else sprintf(&outbuf[j],"%c",pc[i]); j += 1; } outbuf[j++] = '\n'; outbuf[j++] = 0; } else if (psel->record_type == 0xDC) { /* OEM Record: these are usually Microsoft */ evtime = (uchar *)&psel->timestamp; eventTime = evtime[0] + (evtime[1] << 8) + (evtime[2] << 16) + (evtime[3] << 24); fmt_time(eventTime, timebuf, sizeof(timebuf)); pc = (uchar *)&psel->generator_id; /* offset 7 */ mfgstr = get_mfg_str(&pc[0],&mfg); if (fcanonical) sprintf(outbuf,"%04x %c %s %c %s %c %02x %c %06x %c %s %c OEM Event ", psel->record_id, bdelim, timebuf, bdelim, get_sev_str(sev), bdelim, psel->record_type, bdelim, mfg, bdelim, mfgstr, bdelim); else sprintf(outbuf,"%04x %s %s %02x %06x %s OEM Event ", psel->record_id, timebuf, get_sev_str(sev), psel->record_type, mfg, mfgstr); j = strlen_(outbuf); for (i = 3; i < 9; i++) { /* 10:16 = 6 bytes data */ sprintf(&outbuf[j],"%02x ",pc[i]); j += 3; } outbuf[j++] = '\n'; outbuf[j++] = 0; } else if (psel->record_type == 0xDD) { /* usu Intel OEM string */ int ix = 0; /* Windows reboot reason string from MS ipmidrv.sys */ evtime = (uchar *)&psel->timestamp; eventTime = evtime[0] + (evtime[1] << 8) + (evtime[2] << 16) + (evtime[3] << 24); fmt_time(eventTime, timebuf, sizeof(timebuf)); pc = (uchar *)&psel->generator_id; /* IANA at offset 7 */ mfgstr = get_mfg_str(&pc[0],&mfg); if (fcanonical) sprintf(outbuf,"%04x %c %s %c %s %c %02x %c %06x %c %s %c OEM Event ", psel->record_id, bdelim, timebuf, bdelim, get_sev_str(sev), bdelim, psel->record_type, bdelim, mfg, bdelim, mfgstr, bdelim); else sprintf(outbuf,"%04x %s %s %02x %06x %s OEM Event ", psel->record_id, timebuf, get_sev_str(sev), psel->record_type, mfg, mfgstr ); j = strlen_(outbuf); for (i = 3; i < 9; i++) { /* 10:16 = 6 bytes data */ if (i == 3 || ix == 0) { if (i == 3) ix = pc[i]; sprintf(&outbuf[j],"%02x ",pc[i]); j += 3; } else { if (pc[i] == 0) outbuf[j] = ' '; else sprintf(&outbuf[j],"%c",pc[i]); j += 1; } } outbuf[j++] = '\n'; outbuf[j++] = 0; } else if (psel->record_type >= 0xe0) { /*OEM Record 26.3*/ /* 3 bytes header, 13 bytes data, no timestamp */ pc = (uchar *)&psel->timestamp; /*bytes 4:16*/ if (fcanonical) sprintf(outbuf,"%04x %c %s %c %s %c %02x %c %s %c %s %c OEM Event ", psel->record_id, bdelim, "", bdelim, get_sev_str(sev), bdelim, psel->record_type, bdelim, "", bdelim, "", bdelim); else sprintf(outbuf,"%04x %s %02x OEM Event ", psel->record_id,get_sev_str(sev),psel->record_type); j = strlen_(outbuf); for (i = 0; i < 13; i++) { /* 5:16 = 11 bytes data */ if ((psel->record_type == 0xf0) && (i >= 2)) { /* Linux panic string will be type 0xf0 */ if (pc[i] == 0) break; outbuf[j++] = pc[i]; } else if (psel->record_type == 0xf1) { /* custom ascii string record, type 0xf1 */ if (i == 0) { /*linux panic*/ outbuf[j++] = ':'; outbuf[j++] = ' '; } if (pc[i] == 0) break; outbuf[j++] = pc[i]; } else { sprintf(&outbuf[j],"%02x ",pc[i]); j += 3; } } outbuf[j++] = '\n'; outbuf[j++] = 0; } else if (psel->record_type >= 0xc0) { /*OEM Record 26.3*/ /* 10 bytes header, 6 bytes data, has timestamp */ evtime = (uchar *)&psel->timestamp; eventTime = evtime[0] + (evtime[1] << 8) + (evtime[2] << 16) + (evtime[3] << 24); fmt_time(eventTime, timebuf, sizeof(timebuf)); pc = (uchar *)&psel->generator_id; /* IANA at offset 7 */ if (fcanonical) sprintf(outbuf,"%04x %c %s %c %s %c %02x %c %02x%02x%02x %c %s %c OEM Event ", psel->record_id, bdelim, timebuf, bdelim, get_sev_str(sev), bdelim, psel->record_type, bdelim, pc[2],pc[1],pc[0], bdelim, "", bdelim); else sprintf(outbuf,"%04x %s %s %02x %02x%02x%02x OEM Event ", psel->record_id, timebuf, get_sev_str(sev), psel->record_type, pc[2],pc[1],pc[0] ); j = strlen_(outbuf); for (i = 3; i < 9; i++) { /* 10:16 = 6 bytes data */ sprintf(&outbuf[j],"%02x ",pc[i]); j += 3; } outbuf[j++] = '\n'; outbuf[j++] = 0; } else if (psel->record_type == 0x02) { uchar c = 0; /* most records are record type 2 */ /* Interpret the event by sensor type */ switch(psel->sensor_type) { case 0x20: /*OS Crit Stop*/ i = psel->event_data1 & 0x0f; switch(i) { case 0x00: pstr = "Startup Crit Stop"; sev = SEV_CRIT; break; case 0x02: pstr = "OS Graceful Stop"; break; case 0x03: pstr = "OS Graceful Shutdown"; break; case 0x04: pstr = "PEF Soft-Shutdown"; break; case 0x05: pstr = "Agent Not Responding"; break; case 0x01: /*OS Runtime Critical Stop (panic)*/ default: sev = SEV_CRIT; if (psel->sensor_number == 0) { /*Windows*/ pstr = "Runtime Crit Stop"; } else { /*Linux panic, get string*/ /* Show first 3 chars of panic string */ pstr = mystr; strcpy(mystr,"panic("); for (i = 6; i <= 8; i++) { switch(i) { case 6: c = psel->sensor_number; break; case 7: c = psel->event_data2; break; case 8: c = psel->event_data3; break; } c &= 0x7f; if (c < 0x20) c = '.'; mystr[i] = c; } mystr[9] = ')'; mystr[10] = 0; if (psel->sensor_number & 0x80) strcat(mystr,"Oops!"); if (psel->event_data2 & 0x80) strcat(mystr,"Int!"); if (psel->event_data3 & 0x80) strcat(mystr,"NullPtr!"); } break; } /*end data1 switch*/ break; case 0x01: /*Temperature events*/ if (is_threshold(psel->event_trigger, psel->generator_id)) { pstr = get_misc_desc( psel->generator_id, psel->sensor_type, psel->sensor_number, psel->event_trigger, psel->event_data1, psel->event_data2, psel->event_data3, &sev); } else { /*else discrete temp event*/ /* data1 should usually be 0x01 */ if (psel->event_trigger & 0x80) strcpy(mystr,"Temp OK"); else strcpy(mystr,"Temp Asserted"); pstr = mystr; } /*end-else discrete*/ break; /* case 0X04 for Fan events is further below. */ case 0x07: /*Processor (CPU)*/ i = psel->event_data1 & 0x0f; if (psel->event_trigger == 0x6f) { /* Processor status sensor */ if (i >= NPROC) i = NPROC - 1; if (i == 7) sev = SEV_INFO; else if (i > 7) sev = SEV_MIN; else sev = SEV_CRIT; sprintf(mystr,"%s",proc_str[i]); pstr = mystr; } else if (psel->event_trigger == 0xef) { sev = SEV_CRIT; if (i >= NPROC) i = NPROC - 1; sprintf(mystr,"%s deasserted",proc_str[i]); pstr = mystr; } else if (psel->sensor_number == 0x80) { /*CATERR*/ char *p1, *p2; sev = SEV_CRIT; switch( psel->event_data2 & 0x0F) { case 1: p1 = "CATERR"; break; case 2: p1 = "CPU Core Error"; break; case 3: p1 = "MSID Mismatch"; break; default: p1 = "Unknown Error"; break; } if (psel->event_data2 & 0x01) p2 = "CPU0"; else if (psel->event_data2 & 0x02) p2 = "CPU1"; else if (psel->event_data2 & 0x04) p2 = "CPU2"; else if (psel->event_data2 & 0x08) p2 = "CPU3"; else p2 = "CPU4"; sprintf(mystr,"%s on %s",p1,p2); pstr = mystr; } else if (psel->event_trigger == 0x03) { if (i) {pstr = "Proc Config Error"; sev = SEV_CRIT;} else {pstr = "Proc Config OK"; sev = SEV_INFO; } } else if (psel->event_trigger == 0x83) { if (i) { pstr = "Proc Config OK"; sev = SEV_INFO; } else { pstr = "Proc Config Error"; sev = SEV_CRIT; } } else { /* else other processor sensor */ i = ((psel->event_trigger & 0x80) >> 7); if (i) { pstr = "ProcErr Deasserted"; sev = SEV_INFO;} else { pstr = "ProcErr Asserted"; sev = SEV_CRIT; } } break; case 0x08: /*Power Supply*/ pstr = NULL; /*falls through to unknown*/ if ((psel->event_trigger == 0x0b) || (psel->event_trigger == 0x8b)) { rv = decode_redund(psel->event_trigger, psel->event_data1, mystr, &sev); if (rv == 0) pstr = mystr; } else { pstr = get_misc_desc( psel->generator_id, psel->sensor_type, psel->sensor_number, psel->event_trigger, psel->event_data1, psel->event_data2, psel->event_data3, &sev); } break; case 0x09: /*Power Unit*/ if ((psel->event_trigger == 0x0b) || (psel->event_trigger == 0x8b)) { rv = decode_redund(psel->event_trigger, psel->event_data1, mystr, &sev); } else { /*sensor-specific 0x6f/0xef*/ rv = decode_pwrunit(psel->event_trigger, psel->event_data1, mystr, &sev); } if (rv == 0) pstr = mystr; else pstr = NULL; /*falls through to unknown*/ break; case 0x0C: /*Memory*/ i = psel->event_data1 & 0x0f; /*memstr index*/ { /* now get the DIMM index from data2 or data3 */ uchar b2, b3, bdata; b2 = psel->event_data2; b3 = psel->event_data3; if ((vend == VENDOR_INTEL && prod == 0x4311) || (vend == VENDOR_NSC)) { /*mini-BMC*/ bdata = b2; } else if (b3 == 0xff) { /* FF is reserved */ bdata = b2; } else { /* normal case */ bdata = b3; } j = bdata & 0x3f; /* Now i==data1(lo nib) for memstr, j==DIMM index */ if (i == 0) sev = SEV_MIN; /*correctable ECC*/ else sev = SEV_MAJ; if (fdebug) printf("DIMM(%d) vend=%x prod=%x\n",j,vend,prod); msz = sizeof(mdesc); /* For Intel S5500/S2600 see decode_mem_intel */ if (vend == VENDOR_INTEL) { decode_mem_intel(prod,b2,b3,mdesc,&msz); sprintf(mystr,"%s%c %s",mem_str(i),bcomma,mdesc); } else if ((vend == VENDOR_SUPERMICRO) || (vend == VENDOR_SUPERMICROX)) { decode_mem_supermicro(prod,b2,b3,mdesc,&msz); sprintf(mystr,"%s%c %s",mem_str(i),bcomma,mdesc); } else { /*decode_mem_raw*/ decode_mem_default(psel->event_data1,b2,b3,etype,mdesc,&msz); sprintf(mystr,"%s%c %s",mem_str(i),bcomma,mdesc); //old: sprintf(mystr,"%s%c DIMM[%d]",mem_str(i),bcomma,j); /* DIMM[2] = 3rd one (zero-based index) */ } } pstr = mystr; break; case 0x0F: /*System Firmware events, incl POST Errs*/ sev = SEV_MAJ; /*usu major, but platform-specific*/ switch (psel->event_data1 & 0x0f) { case 0x00: /* System firmware errors */ i = psel->event_data2; if (i > NFWERRS) i = NFWERRS; pstr = fwerrs[i].msg; break; case 0x01: /* System firmware hang */ i = psel->event_data2; if (i > NFWSTAT) i = NFWSTAT; sprintf(poststr,"hang%c %s",bcomma, fwstat[i].msg); pstr = poststr; break; case 0x02: /* System firmware progress */ sev = SEV_INFO; i = psel->event_data2; if (i > NFWSTAT) i = NFWSTAT; sprintf(poststr,"prog%c %s",bcomma, fwstat[i].msg); pstr = poststr; break; case 0xa0: /* OEM post codes */ /* OEM post codes in bytes 2 & 3 (lo-hi) */ j = psel->event_data2 | (psel->event_data3 << 8); /* interpret some OEM post codes if -e */ i = decode_post_oem(vend,prod,(ushort)j, poststr,sizeof(poststr)); pstr = poststr; break; default: pstr = get_misc_desc( psel->generator_id, psel->sensor_type, psel->sensor_number, psel->event_trigger, psel->event_data1, psel->event_data2, psel->event_data3, &sev); if (pstr == NULL) pstr = "POST Event"; /*default string*/ } /*end switch(data1)*/ break; case 0x13: /*Crit Int*/ sev = SEV_CRIT; i = psel->event_data1 & 0x0f; if (i >= NCRITS) i = NCRITS - 1; pstr = crit_int_str[i]; if ((psel->event_trigger == 0x70) || (psel->event_trigger == 0x71)) { uchar bus,dev,func; /* Intel AER< decode PCI bus:dev.func data */ bus = psel->event_data2; dev = ((psel->event_data3 & 0xf8) >> 3); func = (psel->event_data3 & 0x07); sprintf(mystr,"%s (on %02x:%02x.%d)", crit_int_str[i],bus,dev,func); pstr = mystr; } break; case 0x15: /*Board (e.g. IO Module)*/ if ((psel->event_trigger == 0x08) || (psel->event_trigger == 0x88)) { rv = decode_presence(psel->event_trigger, psel->event_data1, mystr, &sev); pstr = mystr; } else pstr = NULL; /*falls through to unknown*/ break; case 0x16: /*Microcontroller (e.g. ME or HDD)*/ // if (psel->event_trigger == 0x0A) // Availability { i = psel->event_data1 & 0x0f; if (i >= N_AVAIL) i = N_AVAIL - 1; if (i >= 4) sev = SEV_MIN; else sev = SEV_INFO; pstr = avail_str[i]; } break; case 0x1D: /*System Boot Initiated*/ i = psel->event_data1 & 0x0f; if (i >= NBOOTI) i = NBOOTI - 1; pstr = boot_init_str[i]; break; case 0x1F: /*OS Boot */ i = psel->event_data1 & 0x0f; if (i >= NOSBOOT) i = NOSBOOT - 1; pstr = osboot_str[i]; break; case 0x21: /*Slot/Con*/ i = psel->event_data1 & 0x0f; if (i >= NSLOTC) i = NSLOTC - 1; if (i == 0) sev = SEV_MAJ; /*Fault*/ else if (i == 8) sev = SEV_MIN; sprintf(mystr,"%s",slot_str[i]); /* could also decode data2/data3 here if valid */ pstr = mystr; break; case 0x22: /*ACPI Power state*/ i = psel->event_data1 & 0x0f; if (i >= NACPIP) i = NACPIP - 1; sprintf(mystr,"%s",acpip_str[i]); pstr = mystr; break; case 0x28: /*Management Subsystem Health*/ i = psel->event_data1 & 0x0f; if (i == 0x04) /*sensor error*/ sprintf(mystr,"Sensor %02x fault",psel->event_data2); else sprintf(mystr,"Other FW HAL error"); pstr = mystr; break; case 0x29: /*Battery*/ if (is_threshold(psel->event_trigger, psel->generator_id)) { pstr = get_misc_desc( psel->generator_id, psel->sensor_type, psel->sensor_number, psel->event_trigger, psel->event_data1, psel->event_data2, psel->event_data3, &sev); } else { i = psel->event_data1 & 0x0f; if (i >= NBATT) i = NBATT - 1; /* sev defaults to SEV_INFO */ if (psel->event_trigger & 0x80) { /*deasserted*/ sprintf(mystr,"%s",batt_clr[i]); } else { /*asserted*/ sprintf(mystr,"%s",batt_str[i]); if (i == 0) sev = SEV_MIN; else if (i == 1) sev = SEV_MAJ; } pstr = mystr; } break; case 0x2A: /*Session Audit, new for IPMI 2.0*/ i = psel->event_data1 & 0x0f; if (i >= NAUDIT) i = NAUDIT - 1; sprintf(mystr,"%s User%d",audit_str[i], psel->event_data2); /* see also psel->event_data3 for cause/channel*/ pstr = mystr; break; case 0xDC: /*ME Node Manager, for S5500 Urbanna*/ i = psel->event_trigger; if (i & 0x80) { fdeassert = 1; i &= 0x7f; } if (i >= 0x72) i -= 0x72; if (i >= N_NM) i = N_NM - 1; sprintf(mystr,"%s",nm_str[i]); if (fdeassert) strcat(mystr," OK"); n = strlen_(mystr); sprintf(cstr,"%c ",bcomma); j = psel->event_data2; switch(i) { case 0x00: /*0x72 NM Exception*/ j = psel->event_data1; if ((j & 0x08) == 0) { k = j & 0x03; sprintf(&mystr[n], "%sThreshold %d Exceeded",cstr,k); } else { /*Policy event*/ sprintf(&mystr[n], "%sPolicy Time Exceeded",cstr); } sev = SEV_MIN; break; case 0x01: /*0x73 NM Health*/ j &= 0x0f; // if (j >= 0x10) j -= 0x10; if (j >= N_NMH) j = N_NMH - 1; if (j != 5) sev = SEV_MAJ; strcat(mystr,cstr); /*", "*/ strcat(mystr,nmh_str[j]); break; case 0x03: /*0x75 FW Health*/ if (j >= N_NMFW) j = N_NMFW - 1; sev = SEV_MAJ; strcat(mystr,cstr); /*", "*/ strcat(mystr,nmfw_str[j]); break; case 0x02: /*0x74 NM Capabilities*/ default: sev = SEV_MIN; break; } pstr = mystr; break; case 0x04: /*Fan sensor events */ if ((psel->event_trigger == 0x0b) || (psel->event_trigger == 0x8b)) { rv = decode_redund(psel->event_trigger, psel->event_data1, mystr, &sev); pstr = mystr; break; } else if ((psel->event_trigger == 0x08) || (psel->event_trigger == 0x88)) { rv = decode_presence(psel->event_trigger, psel->event_data1, mystr, &sev); pstr = mystr; break; } else if (psel->event_trigger == 0x06) { /* usu psel->event_data1 == 0x01 */ sev = SEV_MIN; strcpy(mystr,"Performance Lags"); pstr = mystr; break; } else if (psel->event_trigger == 0x86) { sev = SEV_INFO; strcpy(mystr,"Performance OK"); pstr = mystr; break; } /* else Fan threshold events handled below, trig=01/81*/ default: /* all other sensor types, see sens_desc */ pstr = get_misc_desc( psel->generator_id, psel->sensor_type, psel->sensor_number, psel->event_trigger, psel->event_data1, psel->event_data2, psel->event_data3, &sev); break; } /*end switch(sensor_type)*/ if (pstr == NULL) { /* none found, unknown */ mystr[0] = '-'; mystr[1] = 0; pstr = mystr; } /*firmware timestamp is #seconds since 1/1/1970 localtime*/ evtime = (uchar *)&psel->timestamp; eventTime = evtime[0] + (evtime[1] << 8) + (evtime[2] << 16) + (evtime[3] << 24); if (fdebug) { char tbuf[40]; char *tz; char *lctime; strftime(timebuf,sizeof(timebuf), "%x %H:%M:%S %Z", localtime(&eventTime)); strftime(tbuf,sizeof(tbuf), "%x %H:%M:%S %Z", gmtime(&eventTime)); tz = getenv("TZ"); if (tz == NULL) tz = ""; lctime = getenv("LC_TIME"); if (lctime == NULL) lctime = ""; SELprintf("%s\nTZ=%s, LC_TIME=%s, gmtime=%s\n", timebuf,tz,lctime,tbuf); } psensstr = NULL; sensstr[0] = 0; if (fsensdesc) { rv = get_sensor_tag(isdr,psel->generator_id, psel->sensor_number, sensstr, sdr, sizeof(sdr)); if (rv == 0) { fhave_sdr = 1; psensstr = &sensstr[0]; } else rv = 0; /*no sdr but not an error*/ } /*endif fsensdesc*/ if (is_threshold(psel->event_trigger,psel->generator_id)) { /* Also usually ((psel->event_data1 & 0x50) == 0x50) */ /* We know that these two MCs should include the * actual and threshold raw values in data2 & data3 */ if (fsensdesc && fhave_sdr) { double v1, v2; char *u; /* if sdrcache, find_sdr_by_snum got the sdr above */ /* else, GetSDR tried to get the sdr above */ v1 = RawToFloat(psel->event_data2,sdr); v2 = RawToFloat(psel->event_data3,sdr); u = get_unit_type(sdr[20],sdr[21],sdr[22],1); sprintf(datastr, "actual=%.2f %s, threshold=%.2f %s", v1,u, v2,u); } else { // if (fsensdesc == 0 || (rv != 0)) { sprintf(datastr,"act=%02x thr=%02x", psel->event_data2, /*actual raw reading*/ psel->event_data3 ); /*threshold raw value*/ } } else { if (fcanonical) datastr[0] = 0; else sprintf(datastr,"%02x [%02x %02x %02x]", psel->event_trigger, psel->event_data1, psel->event_data2, psel->event_data3 ); } format_event(psel->record_id, eventTime, sev, psel->generator_id, get_sensor_type_desc(psel->sensor_type), psel->sensor_number, psensstr, pstr, datastr, outbuf,szbuf); } /*endif type 2 */ else { /* other misc record type */ if (fdebug) printf("Unrecognized record type %02x\n", psel->record_type); rv = ERR_NOT_FOUND; pc = (uchar *)&psel->record_type; sprintf(outbuf,"%04x Type%02x %s ", psel->record_id,pc[0],get_sev_str(sev)); j = strlen_(outbuf); for (i = 1; i < 14; i++) { sprintf(mystr,"%02x ",pc[i]); strcat(outbuf,mystr); } strcat(outbuf,"\n"); } /*endif misc type*/ return(rv); } /*end decode_sel_entry()*/ static void show_usage(void) { printf("Usage: %s [-bdfhprstux] 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10\n",progname); printf("where -b = interpret Binary raw SEL file, from ipmitool sel writeraw\n"); printf(" -d = get DeviceID for vendor/product-specific events\n"); printf(" -f = interpret File with raw ascii SEL data, from ipmiutil sel -r\n"); printf(" -h = interpret Hex binary raw SEL file (same as -b)\n"); #ifndef ALONE printf(" -o = specify the target vendor IANA number.\n"); #endif printf(" -n = generate New platform event, use last 9 event bytes\n"); printf(" -p = decode PET event bytes, use 34 PET data bytes,\n"); printf(" skipping the first 8 of the 47-byte PET data (-t=all).\n"); printf(" If not specified, assumes a 16-byte IPMI event.\n"); printf(" -r = interpret RAW ascii SEL file (same as -f)\n"); printf(" -s = sensor file with output of 'ipmiutil sensor', used\n"); printf(" to get the PET sensor_type from the sensor_num.\n"); printf(" The default is %s\n",sensfil); printf(" -t = decode PET trap bytes, use all 47 PET data bytes (-p=34)\n"); printf(" If not specified, assumes a 16-byte IPMI event.\n"); printf(" -u = use raw UTC time\n"); printf(" -x = show eXtra debug messages\n"); } /* * decode_raw_sel * input parameters: * raw_file : filename of raw SEL file * mode : 1 = ascii raw from ipmiutil sel -r * 2 = binary hex from ipmiutil sel writeraw {raw_file} */ int decode_raw_sel(char *raw_file, int mode) { FILE *fp; char buff[256]; char msg[132]; uchar hbuf[50]; int fvalid = 0; int len, i; fp = fopen(raw_file,"r"); if (fp == NULL) { printf("Cannot open file %s\n",raw_file); return(ERR_FILE_OPEN); } else { printf("%s",evt_hdr); /*"RecId Date/Time_______*/ if (mode == 1) { /*ascii raw*/ if (fdebug) printf("decoding raw ascii file with IPMI event bytes\n"); 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; for (i = 0; i < 16; i++) { hbuf[i] = _htoi(&buff[i*3]); } decode_sel_entry(hbuf,msg,sizeof(msg)); printf("%s", msg); } /*end while*/ } else { /*hex raw*/ if (fdebug) printf("decoding binary hex file with IPMI event bytes\n"); while (fread(hbuf, 1, 16, fp) == 16) { decode_sel_entry(hbuf,msg,sizeof(msg)); printf("%s", msg); } /*end while*/ } fclose(fp); } return(0); } /* * The events utility interprets standard 16-byte IPMI events into * human-readable form by default. * User must pass raw 16-byte event data from some log text for decoding. * * Sample IPMI event usage: * # ievents fb 07 02 e5 1a b8 44 21 00 03 1d 9a 6f 40 8f ff * RecId Date/Time_______ SEV Src_ Evt_Type___ Sens# Evt_detail - Trig [Evt_data] * 07fb 07/14/06 18:29:57 INF SMI System Boot Initiated #9a Power Up 6f [40 8f ff] * # ievents 14 04 02 BE 35 13 45 33 40 04 0C 08 6F 20 00 04 * RecId Date/Time_______ SEV Src_ Evt_Type___ Sens# Evt_detail - Trig [Evt_data] * 0414 09/21/06 21:00:46 MIN 4033 Memory #08 Correctable ECC, DIMM[4] 6f [20 00 04] * * If fPET, interpret the SNMP Platform Event Trap hex varbind data. * For interpreting the 47-byte hex data from SNMP Platform Event Traps, * specify events -p with the 34 data bytes following the 16-byte GUID. * * Sample SNMP PET Data for events: * 0000: 3C A7 56 85 08 C5 11 D7 C3 A2 00 04 23 BC AC 12 * 0010: 51 14 11 72 38 58 FF FF 20 20 00 10 83 07 01 41 * 0020: 0F FF 00 00 00 00 00 19 00 00 01 57 00 22 C1 * * Sample events -p command from above data: * # ievents -p C3 A2 00 04 23 BC AC 12 51 14 11 72 38 58 FF FF 20 20 00 10 83 07 01 41 0F FF 00 00 00 00 * RecId Date/Time_______ SEV Src_ Evt_Type___ Sens# Evt_detail - Trig [Evt_data] * 0014 04/11/07 12:03:20 INF BMC System Event #83 OEM System Booted 6f [41 0f ff] * * Platform Event Trap Format * Offset Len Meaning * 0 16 System GUID * 16 2 Sequence Number/Cookie * 18 4 Local Timestamp * 22 2 UTC Offset * 24 1 Trap Source Type (usu 0x20) * 25 1 Event Source Type (usu 0x20) * 26 1 Event Severity * 27 1 Sensor Device * 28 1 Sensor Number * 29 1 Entity * 30 1 Entity Instance * 31 8 Event Data (8 bytes max, 3 bytes used) * 39 1 Language Code (usu 0x19/25. = English) * 40 4 Manufacturer IANA number (Intel=0x000157) * 44 1-N OEM data, C1="No more fields" * If Intel (0x000157): * 44 2 Product ID * 46 1 0xC1 (No more fields) */ #if defined(ALONE) #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #else /* #elif defined(METACOMMAND) or if libipmiutil */ int i_events(int argc, char **argv) #endif { uchar buf[50]; uchar msg[132]; uchar *pmsg; int i, j, len; char fPET = 0; char frawfile = 0; char fhexfile = 0; int rv = 0; char c; uchar b = 0; #ifndef ALONE uchar devid[16]; #endif #if defined(METACOMMAND) char *p; #endif printf("%s version %s\n",progname,progver); if (argc > 0) { argc--; argv++; } /*skip argv[0], program name*/ /* ievents getopt: [ -bdfhnoprstux -NPRUEFJTVY */ while ((argc > 0) && argv[0][0] == '-') { c = argv[0][1]; switch(c) { case 'x': fdebug = 1; break; case 'd': fgetdevid = 1; break; /*get device id (vendor, product)*/ case 'n': fnewevt = 1; break; /* generate New event */ case 'p': /* PET format, minus first 8 bytes*/ /* This is important for some SNMP trap receivers that obscure * the first 8 bytes of the trap data */ fPET = 1; /*incoming data is in PET format*/ break; case 'u': futc = 1; break; /*use raw UTC time*/ case 'M': /* Set manufacturer IANA */ case 'o': /*specify OEM IANA manufacturer id */ if (argc > 1) { /*next argv is IANA number */ iopt = atoi(argv[1]); printf("setting IANA to %d (%s)\n",iopt,get_iana_str(iopt)); set_iana(iopt); argc--; argv++; } else { printf("option -%c requires an argument\n",c); rv = ERR_BAD_PARAM; } break; case 't': /*PET format Trap, use all data*/ /* This may be helpful if all bytes are available, or if * the GUID is relevant. */ fPET = 1; /*incoming data is in PET format*/ pet_guid = 16; break; case 'f': case 'r': /* interpret raw ascii SEL file from optarg */ frawfile = 1; if (argc > 1) { /*next argv is filename*/ len = strlen_(argv[1]); if (len >= sizeof(rawfil)) len = sizeof(rawfil) - 1; strncpy(rawfil,argv[1],len); rawfil[len] = 0; /*stringify*/ argc--; argv++; } else { printf("option -%c requires a filename argument\n",c); rv = ERR_BAD_PARAM; } break; case 'b': case 'h': /* interpret raw binary/hex SEL file from optarg */ fhexfile = 1; if (argc > 1) { /*next argv is filename*/ len = strlen_(argv[1]); if (len >= sizeof(rawfil)) len = sizeof(rawfil) - 1; strncpy(rawfil,argv[1],len); rawfil[len] = 0; /*stringify*/ argc--; argv++; } else { printf("option -%c requires a filename argument\n",c); rv = ERR_BAD_PARAM; } break; case 's': /* get sensor file from optarg */ if (argc > 1) { /*next argv is filename*/ FILE *fp; len = strlen_(argv[1]); if (len >= sizeof(sensfil)) len = sizeof(sensfil) - 1; strncpy(sensfil,argv[1],len); sensfil[len] = 0; /*stringify*/ fp = fopen(sensfil,"r"); if (fp == NULL) { printf("cannot open file %s\n",sensfil); rv = ERR_FILE_OPEN; } else fclose(fp); argc--; argv++; } else { printf("option -%c requires a filename argument\n",c); rv = ERR_BAD_PARAM; } fsensdesc = 2; break; #if defined(METACOMMAND) case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ if (c == 'Y' || c == 'E') p = NULL; else if (argc <= 1) { printf("option -%c requires an argument\n",c); rv = ERR_BAD_PARAM; } else { /* has an optarg */ p = argv[1]; argc--; argv++; } if (rv == 0) parse_lan_options(c,p,fdebug); break; #endif default: /*unknown option*/ printf("Unknown option -%c\n",c); show_usage(); rv = ERR_USAGE; goto do_exit; break; } argc--; argv++; } /*end while options*/ len = argc; /*number of data bytes*/ if (!fPET && len > 16) len = 16; /* IPMI event max is 16 */ if (frawfile || fhexfile) len = 0; else if (fnewevt) { if (len < 9) { printf("Need 9 bytes for a New event, got %d bytes input\n",len); show_usage(); rv = ERR_BAD_PARAM; } } else if (len < 16) { printf("Need 16 bytes for an IPMI event, got %d bytes input\n",len); show_usage(); rv = ERR_BAD_PARAM; } if (rv != 0) goto do_exit; #ifndef ALONE if (fgetdevid || fsensdesc) rv = ipmi_getdeviceid( devid, sizeof(devid),fdebug); /*sets mfgid*/ #endif for (i = 0; i < len; i++) { if (fPET) msg[i] = _htoi(argv[i]); else buf[i] = _htoi(argv[i]); } if (fPET != 0) /*PET, reorder bytes to std event format*/ { uchar snum, styp; int timestamp; int yrs, time2; char sensdesc[100]; int mfg; pmsg = &msg[pet_guid]; /*pet_guid=8, skip the GUID*/ if (fdebug) { printf("decoding IPMI PET event bytes\n"); dump_buf("PET buffer",msg,len,1); } /* pmsg[ 9] is event source type (gen id, usu 0x20) */ /* pmsg[10] is event severity */ /* pmsg[11] is sensor device */ /* pmsg[12] is sensor number */ /* pmsg[13] is Entity */ snum = pmsg[12]; styp = entity2sensor_type(pmsg[13]); rv = get_sensdesc(pmsg[9],snum,sensdesc,&i,NULL); if (rv == 0) { styp = (uchar)i; if (fdebug) printf("sensor[%02x]: %s\n",snum,sensdesc); set_sel_opts(2,0, NULL,fdebug,futc); } else { if (rv == ERR_NOT_FOUND) { printf("Cannot find snum %02x in %s\n",snum,sensfil); printf("Resolve this by doing 'ipmiutil sensor >sensorX.txt' " "on a system similar\nto the target, then use " "'ipmiutil events -s sensorX.txt ...'\n"); } /* Try GetSensorType(), which will work if local IPMI. */ rv = GetSensorType(snum,&b,NULL); if (fdebug) printf("sensor[%02x]: GetSensorType rv=%d stype=%x\n", snum,rv,b); if (rv == 0) styp = b; } buf[0] = pmsg[1]; /*record id (sequence num)*/ buf[1] = 0; /* was pmsg[0]; */ buf[2] = 0x02; /*event type*/ #ifdef RAW buf[3] = pmsg[5]; /*timestamp*/ buf[4] = pmsg[4]; /*timestamp*/ buf[5] = pmsg[3]; /*timestamp*/ buf[6] = pmsg[2]; /*timestamp*/ #else timestamp = pmsg[5] + (pmsg[4] << 8) + (pmsg[3] << 16) + (pmsg[2] << 24); /* add 28 years, includes 7 leap days, less 1 hour TZ fudge */ // yrs = ((3600 * 24) * 365 * 28) + (7 * (3600 * 24)) - 3600; yrs = 0x34aace70; time2 = timestamp + yrs; if (fdebug) printf("timestamp: %08x + %08x = %08x\n",timestamp,yrs,time2); buf[3] = time2 & 0x000000ff; /*timestamp*/ buf[4] = (time2 & 0x0000ff00) >> 8; /*timestamp*/ buf[5] = (time2 & 0x00ff0000) >> 16; /*timestamp*/ buf[6] = (time2 & 0xff000000) >> 24; /*timestamp*/ #endif buf[7] = pmsg[9]; /*generator_id*/ buf[8] = 0; buf[9] = 0x04; /*evm_rev*/ buf[10] = styp; /*derived sensor type, from above */ buf[11] = snum; /*sensor number*/ /* set the event trigger based on context */ switch(styp) { /*set the event trigger*/ case 0x12: buf[12] = 0x6f; break; /*system event (sensor-specific)*/ case 0x09: buf[12] = 0x0b; break; /*Power Unit*/ case 0x01: /*temp*/ case 0x02: /*voltage*/ case 0x03: /*current*/ case 0x04: /*fan*/ if (pmsg[10] == 0x04) buf[12] = 0x81; /*info severity, ok*/ else buf[12] = 0x01; /* threshold asserted*/ break; default: buf[12] = pmsg[14]; /*event trigger = Entity Instance */ /*Note that Entity Instance will not match an event trigger*/ buf[12] = 0x6f; /*set trigger to sensor-specific*/ break; } memcpy(&buf[13],&pmsg[15],3); /*event data*/ mfg = pmsg[27] + (pmsg[26] << 8) + (pmsg[25] << 16); if (fdebug) { printf("PET severity=%02x, mfgId=%02x%02x%02x%02x\n", pmsg[10], pmsg[24], pmsg[25], pmsg[26], pmsg[27]); dump_buf("IPMI event",buf,16,0); } if (mfg == VENDOR_SUN) { /* Sun = 0x00002A, extra OEM data */ j = 28 + pet_guid; /*offset 28+16=44 (OEM data) */ pmsg = &msg[j]; for (i = 0; (i+j) < len; ) { if (pmsg[i] == 0xC1) break; if (i == 0) i += 2; /* 2-byte header 0x0c 0x01 */ else if (pmsg[i] == 0x80) { /* 3-byte header, usu strings */ if (pmsg[i+2] == 0x03) printf(" %s\n",&pmsg[i+3]); i += (3 + pmsg[i+1]); } else i++; } } decode_sel_entry(buf,(char *)msg,sizeof(msg)); printf("%s", evt_hdr); /*"RecId Date/Time_______*/ printf("%s", msg); } else if (fnewevt) { rv = new_event(buf,len); /*do new platform event*/ } else if (frawfile) { rv = decode_raw_sel(rawfil,1); /*ascii raw data from file */ } else if (fhexfile) { rv = decode_raw_sel(rawfil,2); /*binary/hex raw data from file*/ } else { if (fdebug) printf("decoding standard IPMI event bytes\n"); if (fdebug) dump_buf("IPMI event",buf,16,0); set_sel_opts(2,0, NULL,fdebug,futc); rv = decode_sel_entry(buf,(char *)msg,sizeof(msg)); /* show header for the event record */ printf("%s", evt_hdr); /*"RecId Date/Time_______*/ printf("%s", msg); } do_exit: #ifndef METACOMMAND printf("%s, %s\n",progname,decode_rv(rv)); #endif return(rv); } // #endif /* end ievents.c */ ipmiutil-3.1.5/util/ipicmg.h0000644000076400007640000002103113566765324016051 0ustar mgportalloggers/* (C) Kontron */ #ifndef _IPMI_PICMG_H_ #define _IPMI_PICMG_H_ #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int #define BMC_SA 0x20 #define PUBLIC_BUS 0 #define BMC_LUN 0 /* PICMG version */ #define PICMG_CPCI_MAJOR_VERSION 1 #define PICMG_ATCA_MAJOR_VERSION 2 #define PICMG_AMC_MAJOR_VERSION 4 #define FRU_PICMGEXT_LINK_TYPE_BASE 0x01 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET 0x02 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND 0x03 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR 0x04 #define FRU_PICMGEXT_LINK_TYPE_PCIE 0x05 #ifndef HAVE_FRU_PICMG_EXT #define HAVE_FRU_PICMG_EXT #pragma pack(1) struct fru_picmgext_link_desc { #ifndef WORDS_BIGENDIAN unsigned int desig_channel:6; unsigned int desig_if:2; unsigned int desig_port:4; unsigned int type:8; unsigned int ext:4; unsigned int grouping:8; #else unsigned int grouping:8; unsigned int ext:4; unsigned int type:8; unsigned int desig_port:4; unsigned int desig_if:2; unsigned int desig_channel:6; #endif }; /* __attribute__ ((packed)); */ struct fru_picmgext_amc_link_info { unsigned char linkInfo[3]; }; /* __attribute__ ((packed)); */ #pragma pack() #endif #define OEM_PICMG 12634 // IPMI_OEM_PICMG = 12634, #define FRU_PICMG_BACKPLANE_P2P 0x04 #define FRU_PICMG_ADDRESS_TABLE 0x10 #define FRU_PICMG_SHELF_POWER_DIST 0x11 #define FRU_PICMG_SHELF_ACTIVATION 0x12 #define FRU_PICMG_SHMC_IP_CONN 0x13 #define FRU_PICMG_BOARD_P2P 0x14 #define FRU_AMC_CURRENT 0x16 #define FRU_AMC_ACTIVATION 0x17 #define FRU_AMC_CARRIER_P2P 0x18 #define FRU_AMC_P2P 0x19 #define FRU_AMC_CARRIER_INFO 0x1a #define FRU_UTCA_FRU_INFO_TABLE 0x20 #define FRU_UTCA_CARRIER_MNG_IP 0x21 #define FRU_UTCA_CARRIER_INFO 0x22 #define FRU_UTCA_CARRIER_LOCATION 0x23 #define FRU_UTCA_SHMC_IP_LINK 0x24 #define FRU_UTCA_POWER_POLICY 0x25 #define FRU_UTCA_ACTIVATION 0x26 #define FRU_UTCA_PM_CAPABILTY 0x27 #define FRU_UTCA_FAN_GEOGRAPHY 0x28 #define FRU_UTCA_CLOCK_MAPPING 0x29 #define FRU_UTCA_MSG_BRIDGE_POLICY 0x2A #define FRU_UTCA_OEM_MODULE_DESC 0x2B #define FRU_PICMG_CLK_CARRIER_P2P 0x2C #define FRU_PICMG_CLK_CONFIG 0x2D #define FRU_PICMGEXT_LINK_TYPE_BASE 0x01 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET 0x02 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND 0x03 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR 0x04 #define FRU_PICMGEXT_LINK_TYPE_PCIE 0x05 #define FRU_PICMGEXT_LINK_TYPE_BASE 0x01 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET 0x02 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND 0x03 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR 0x04 #define FRU_PICMGEXT_LINK_TYPE_PCIE 0x05 #define FRU_PICMGEXT_AMC_LINK_TYPE_RESERVED 0x00 #define FRU_PICMGEXT_AMC_LINK_TYPE_RESERVED1 0x01 #define FRU_PICMGEXT_AMC_LINK_TYPE_PCI_EXPRESS 0x02 #define FRU_PICMGEXT_AMC_LINK_TYPE_ADVANCED_SWITCHING1 0x03 #define FRU_PICMGEXT_AMC_LINK_TYPE_ADVANCED_SWITCHING2 0x04 #define FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET 0x05 #define FRU_PICMGEXT_AMC_LINK_TYPE_RAPIDIO 0x06 #define FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE 0x07 #define FRU_PICMGEXT_OEM_SWFW 0x03 #define FRU_PICMGEXT_DESIGN_IF_BASE 0x00 #define FRU_PICMGEXT_DESIGN_IF_FABRIC 0x01 #define FRU_PICMGEXT_DESIGN_IF_UPDATE_CHANNEL 0x02 #define FRU_PICMGEXT_DESIGN_IF_RESERVED 0x03 #define FRU_PICMGEXT_AMC_LINK_TYPE_PCIE 0x02 #define FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS1 0x03 #define FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS2 0x04 #define FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET 0x05 #define FRU_PICMGEXT_AMC_LINK_TYPE_RAPIDIO 0x06 #define FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE 0x07 #define AMC_LINK_TYPE_EXT_PCIE_G1_NSSC 0x00 #define AMC_LINK_TYPE_EXT_PCIE_G1_SSC 0x01 #define AMC_LINK_TYPE_EXT_PCIE_G2_NSSC 0x02 #define AMC_LINK_TYPE_EXT_PCIE_G2_SSC 0x03 #define AMC_LINK_TYPE_EXT_ETH_1000_BX 0x00 #define AMC_LINK_TYPE_EXT_ETH_10G_XAUI 0x01 #define AMC_LINK_TYPE_EXT_STORAGE_FC 0x00 #define AMC_LINK_TYPE_EXT_STORAGE_SATA 0x01 #define AMC_LINK_TYPE_EXT_STORAGE_SAS 0x02 #define IPMI_NETFN_PICMG 0x2C /* PICMG commands */ #define PICMG_GET_PICMG_PROPERTIES_CMD 0x00 #define PICMG_GET_ADDRESS_INFO_CMD 0x01 #define PICMG_GET_SHELF_ADDRESS_INFO_CMD 0x02 #define PICMG_SET_SHELF_ADDRESS_INFO_CMD 0x03 #define PICMG_FRU_CONTROL_CMD 0x04 #define PICMG_GET_FRU_LED_PROPERTIES_CMD 0x05 #define PICMG_GET_LED_COLOR_CAPABILITIES_CMD 0x06 #define PICMG_SET_FRU_LED_STATE_CMD 0x07 #define PICMG_GET_FRU_LED_STATE_CMD 0x08 #define PICMG_SET_IPMB_CMD 0x09 #define PICMG_SET_FRU_POLICY_CMD 0x0A #define PICMG_GET_FRU_POLICY_CMD 0x0B #define PICMG_FRU_ACTIVATION_CMD 0x0C #define PICMG_GET_DEVICE_LOCATOR_RECORD_CMD 0x0D #define PICMG_SET_PORT_STATE_CMD 0x0E #define PICMG_GET_PORT_STATE_CMD 0x0F #define PICMG_COMPUTE_POWER_PROPERTIES_CMD 0x10 #define PICMG_SET_POWER_LEVEL_CMD 0x11 #define PICMG_GET_POWER_LEVEL_CMD 0x12 #define PICMG_RENEGOTIATE_POWER_CMD 0x13 #define PICMG_GET_FAN_SPEED_PROPERTIES_CMD 0x14 #define PICMG_SET_FAN_LEVEL_CMD 0x15 #define PICMG_GET_FAN_LEVEL_CMD 0x16 #define PICMG_BUSED_RESOURCE_CMD 0x17 /* AMC.0 commands */ #define PICMG_AMC_SET_PORT_STATE_CMD 0x19 #define PICMG_AMC_GET_PORT_STATE_CMD 0x1A /* AMC.0 R2.0 commands */ #define PICMG_AMC_SET_CLK_STATE_CMD 0x2C #define PICMG_AMC_GET_CLK_STATE_CMD 0x2D /* Site Types */ #define PICMG_ATCA_BOARD 0x00 #define PICMG_POWER_ENTRY 0x01 #define PICMG_SHELF_FRU 0x02 #define PICMG_DEDICATED_SHMC 0x03 #define PICMG_FAN_TRAY 0x04 #define PICMG_FAN_FILTER_TRAY 0x05 #define PICMG_ALARM 0x06 #define PICMG_AMC 0x07 #define PICMG_PMC 0x08 #define PICMG_RTM 0x09 #pragma pack(1) struct picmg_set_fru_activation_cmd { unsigned char picmg_id; /* always 0*/ unsigned char fru_id; /* threshold setting mask */ unsigned char fru_state; /* fru activation/deactivation */ }; // __attribute__ ((packed)); #pragma pack() typedef enum picmg_busres_board_cmd_types { PICMG_BUSRES_BOARD_CMD_QUERY =0, PICMG_BUSRES_BOARD_CMD_RELEASE, PICMG_BUSRES_BOARD_CMD_FORCE, PICMG_BUSRES_BOARD_CMD_BUS_FREE } t_picmg_busres_board_cmd_types ; typedef enum picmg_busres_shmc_cmd_types { PICMG_BUSRES_SHMC_CMD_REQUEST =0, PICMG_BUSRES_SHMC_CMD_RELINQUISH, PICMG_BUSRES_SHMC_CMD_NOTIFY } t_picmg_busres_shmc_cmd_types ; typedef enum picmg_busres_resource_id { PICMG_BUSRES_METAL_TEST_BUS_1=0, PICMG_BUSRES_METAL_TEST_BUS_2, PICMG_BUSRES_SYNC_CLOCK_GROUP_1, PICMG_BUSRES_SYNC_CLOCK_GROUP_2, PICMG_BUSRES_SYNC_CLOCK_GROUP_3 } t_picmg_busres_resource_id; struct sAmcPortState { #ifndef WORDS_BIGENDIAN unsigned short lane0 : 1; unsigned short lane1 : 1; unsigned short lane2 : 1; unsigned short lane3 : 1; unsigned short type : 8; unsigned short type_ext : 4; unsigned char group_id : 8; #else unsigned char group_id : 8; unsigned short type_ext : 4; unsigned short type : 8; unsigned short lane3 : 1; unsigned short lane2 : 1; unsigned short lane1 : 1; unsigned short lane0 : 1; #endif unsigned char state; }; #endif ipmiutil-3.1.5/util/ifru_picmg.c0000644000076400007640000003702413566765324016731 0ustar mgportalloggers/* * ifru_picmg.c * These are helper routines for FRU PICMG decoding. * * Author: Andy Cress arcress at users.sourceforge.net * * Copyright (c) 2009 Kontron America, Inc. * * 09/08/10 Andy Cress - created */ /*M* Copyright (c) 2010 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 Kontron 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*/ #ifdef WIN32 #include #include #include "getopt.h" #else #include #include #include #include #endif #include #include "ipmicmd.h" #include "ipicmg.h" extern int verbose; extern void show_guid(uchar *pguid); /*from ifru.c*/ static char *picmg_link_type(uchar b) { char *s; if (b >= 0xf0 && b <= 0xf3) s = "OEM GUID Definition"; else switch(b) { case 0x01: s = "PICMG 3.0 Base Interface 10/100/1000"; break; case 0x02: s = "PICMG 3.1 Ethernet Fabric Interface"; break; case 0x03: s = "PICMG 3.2 Infiniband Fabric Interface"; break; case 0x04: s = "PICMG 3.3 Star Fabric Interface"; break; case 0x05: s = "PICMG 3.4 PCI Express Fabric Interface"; break; default: s = "Reserved"; break; } return(s); } static char *picmg_if_type(uchar b) { char *s; switch(b) { case 0x00: s = "Base Interface"; break; case 0x01: s = "Fabric Interface"; break; case 0x02: s = "Update Channel"; break; case 0x03: default: s = "Reserved"; break; } return(s); } static char *picmg_chan_type(uchar b) { char *s; switch(b) { case 0x00: case 0x07: s = "PICMG 2.9"; break; case 0x08: s = "Single Port Fabric IF"; break; case 0x09: s = "Double Port Fabric IF"; break; case 0x0a: s = "Full Port Fabric IF"; break; case 0x0b: s = "Base IF"; break; case 0x0c: s = "Update Channel IF"; break; default: s = "Unknown IF"; break; } return(s); } void show_fru_picmg(uchar *pdata, int dlen) { int id, i, j, k, m, n; float f; uchar *p; uchar b0, b1, b2, b3, b4, b5, b6, b7, b8; char *s1, *s2; long l1, l2, l3; id = pdata[3]; i = 5; switch(id) { case FRU_PICMG_BACKPLANE_P2P: printf("\tFRU_PICMG_BACKPLANE_P2P\n"); while (i <= dlen) { b1 = pdata[i]; b2 = pdata[i+1]; b3 = pdata[i+2]; printf("\t Channel Type : %02x - %s\n",b1, picmg_chan_type(b1)); printf("\t Slot Address : %02x\n",b2); printf("\t Channel Count : %02x\n",b3); i += 3; for (j = 0; j < b3; j++) { if (i > dlen) break; if (verbose) printf("\t Channel[%d] : %02x -> %02x in slot %02x\n", j,pdata[i],pdata[i+1],pdata[i+2]); i += 3; } } break; case FRU_PICMG_ADDRESS_TABLE: printf("\tFRU_PICMG_ADDRESS_TABLE\n"); printf("\t Type/Len : %02x\n", pdata[i++]); printf("\t Shelf Addr : "); for (j = 0; j < 20; j++) printf("%02x ",pdata[i++]); printf("\n"); n = pdata[i++]; printf("\t AddrTable Entries: %02x\n",n); for (j = 0; j < n; j++) { if (i >= dlen) break; printf("\t HWAddr %02x, SiteNum %02x, SiteType %02x\n", pdata[i], pdata[i+1], pdata[i+2]); i += 3; } break; case FRU_PICMG_SHELF_POWER_DIST: printf("\tFRU_PICMG_SHELF_POWER_DIST\n"); n = pdata[i++]; printf("\t Num Power Feeds : %02x\n",n); for (j = 0; j < n; j++) { if (i >= dlen) break; printf("\t Max Ext Current : %04x\n", (pdata[i] | (pdata[i+1] << 8))); i += 2; printf("\t Max Int Current : %04x\n", (pdata[i] | (pdata[i+1] << 8))); i += 2; printf("\t Min Exp Voltage : %02x\n", pdata[i++]); m = pdata[i++]; /*num entries*/ printf("\t Feed to FRU count: %02x\n", m); for (k = 0; k < m; k++) { if (i >= dlen) break; printf("\t HW: %02x",pdata[i++]); printf(" FRU ID: %02x\n",pdata[i++]); } } break; case FRU_PICMG_SHELF_ACTIVATION: printf("\tFRU_PICMG_SHELF_ACTIVATION\n"); printf("\t Allowance for FRU Act Readiness : %02x\n", pdata[i++]); n = pdata[i++]; printf("\t FRU activation and Power desc Cnt: %02x\n",n); for (j = 0; j < n; j++) { if (i >= dlen) break; printf("\t HW Addr: %02x, ", pdata[i++]); printf(" FRU ID: %02x, ", pdata[i++]); printf(" Max FRU Power: %04x, ", pdata[i] | (pdata[i+1]<<8)); i += 2; printf(" Config: %02x\n", pdata[i++]); } break; case FRU_PICMG_SHMC_IP_CONN: printf("\tFRU_PICMG_SHMC_IP_CONN\n"); printf("\t Conn Data: "); for ( ; i < dlen; i++) { printf("%02x ",pdata[i]); } printf("\n"); break; case FRU_PICMG_BOARD_P2P: /*0x14*/ printf("\tFRU_PICMG_BOARD_P2P\n"); n = pdata[i++]; /*guid count*/ printf("\t GUID count : %d\n",n); for (j = 0; j < n; j++) { printf("\t GUID[%d] : ",j); show_guid(&pdata[i]); printf("\n"); i += 16; } for (j = 1; i < dlen; i += 4) { p = &pdata[i]; b1 = (p[0] & 0x3f); /*chan*/ b2 = (p[0] & 0xc0) >> 6; /*if*/ b3 = (p[1] & 0x0f); /*port*/ b4 = ((p[1] & 0xf0) >> 4) + (p[2] & 0xf0); /*type*/ b5 = (p[2] & 0x0f); /*ext*/ b6 = p[3]; /*grouping*/ printf("\t Link%d Grouping : %02x\n",j,b6); printf("\t Link%d Extension : %02x\n",j,b5); printf("\t Link%d Type : %02x - %s\n", j,b4,picmg_link_type(b4)); printf("\t Link%d Port : %02x\n",j,b3); printf("\t Link%d Interface : %02x - %s\n", j,b2,picmg_if_type(b2)); printf("\t Link%d Channel : %02x\n",j,b1); j++; } break; case FRU_AMC_CURRENT: printf("\tFRU_AMC_CURRENT\n"); b1 = pdata[i]; /*current*/ f = (float)(b1/10.0); printf("\t Current draw: %.1f A @ 12V => %.2f Watt\n", f, (f*12.0)); break; case FRU_AMC_ACTIVATION: printf("\tFRU_AMC_ACTIVATION\n"); b1 = pdata[i] | (pdata[i+1]<<8); /*max current*/ i += 2; f = (float)b1 / 10; printf("\t Max Internal Current(@12V) : %.2f A [ %.2f Watt ]\n", f, f*12); printf("\t Module Activation Readiness: %i sec.\n",pdata[i++]); n = pdata[i++]; printf("\t Descriptor Count: %i\n",n); for (j = 0; i < dlen; i += 3) { if (j >= n) break; printf("\t IPMB Address : %02x\n",pdata[i]); printf("\t Max Module Current: %.2f A\n", (float)(pdata[i+1]/10)); j++; } break; case FRU_AMC_CARRIER_P2P: printf("\tFRU_AMC_CARRIER_P2P\n"); for ( ; i < dlen; ) { b1 = pdata[i]; /*resource id*/ n = pdata[i+1]; /*desc count*/ i += 2; b2 = (b1 >> 7); printf("\t Resource ID: %i, Type: %s\n", (b1 & 0x07), (b2 == 1 ? "AMC" : "Local")); printf("\t Descriptor Count: %i\n",n); for (j = 0; j < n; j++) { if (i >= dlen) break; p = &pdata[i]; b3 = p[0]; /*remote resource id*/ b4 = (p[1] & 0x1f); /*remote port*/ b5 = (p[1] & 0xe0 >> 5) + (p[2] & 0x03 << 3); /*local*/ printf("\t Port %02d -> Remote Port %02d " "[ %s ID: %02d ]\n", b5, b4, ((b3 >> 7) == 1)? "AMC " : "local", b3 & 0x0f); i += 3; } } break; case FRU_AMC_P2P: printf("\tFRU_AMC_P2P\n"); n = pdata[i++]; /*guid count*/ printf("\t GUID count : %d\n",n); for (j = 0; j < n; j++) { printf("\t GUID[%d] : ",j); show_guid(&pdata[i]); printf("\n"); i += 16; } b1 = pdata[i] & 0x0f; /*resource id*/ b2 = (pdata[i] & 0x80) >> 7; /*resource type*/ i++; printf("\t Resource ID: %i - %s\n",b1, b2 ? "AMC Module" : "On-Carrier Device"); n = pdata[i++]; /*descriptor count*/ printf("\t Descriptor Count: %i\n",n); for (j = 0; j < n; j++) { /*channel desc loop*/ if (i >= dlen) break; p = &pdata[i]; b0 = p[0] & 0x1f; b1 = ((p[0] & 0xe0) >> 5) + ((p[1] & 0x03) << 3); b2 = ((p[1] & 0x7c) >> 2); b3 = ((p[1] & 0x80) >> 7) + ((p[2] & 0x0f) << 1); printf("\t Lane 0 Port: %i\n",b0); printf("\t Lane 1 Port: %i\n",b1); printf("\t Lane 2 Port: %i\n",b2); printf("\t Lane 3 Port: %i\n",b3); i += 3; } for ( ; i < dlen; i += 5) { /*ext descriptor loop*/ p = &pdata[i]; b0 = p[0]; /*channel id*/ b1 = p[1] & 0x01; /*port flag 0*/ b2 = (p[1] & 0x02) >> 1; /*port flag 1*/ b3 = (p[1] & 0x04) >> 2; /*port flag 2*/ b4 = (p[1] & 0x08) >> 3; /*port flag 3*/ b5 = ((p[1] & 0xf0) >> 4) + ((p[2] & 0x0f) << 4); /*type*/ b6 = (p[2] & 0xf0) >> 4; /*type ext*/ b7 = p[3]; /*group id*/ b8 = (p[4] & 0x03); /*asym match*/ printf("\t Link Designator: Channel ID: %i, " "Port Flag 0: %s%s%s%s\n",b0, b1 ? "o" : "-", b2 ? "o" : "-", b3 ? "o" : "-", b4 ? "o" : "-" ); switch(b5) { /*link type*/ case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE: printf("\t Link Type: %02x - %s\n", b5, "AMC.1 PCI Express"); switch(b6) { /*link type ext*/ case AMC_LINK_TYPE_EXT_PCIE_G1_NSSC: s2 = "Gen 1 capable - non SSC"; break; case AMC_LINK_TYPE_EXT_PCIE_G1_SSC: s2 = "Gen 1 capable - SSC"; break; case AMC_LINK_TYPE_EXT_PCIE_G2_NSSC: s2 = "Gen 2 capable - non SSC"; break; case AMC_LINK_TYPE_EXT_PCIE_G2_SSC: s2 = "Gen 2 capable - SSC"; break; default: s2 = "Invalid"; break; } printf("\t Link Type Ext: %02x - %s\n", b6,s2); break; case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS1: case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS2: printf("\t Link Type: %02x - %s\n", b5, "AMC.1 PCI Express Advanced Switching"); printf("\t Link Type Ext: %02x\n", b6); break; case FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET: s1 = "AMC.2 Ethernet"; printf("\t Link Type: %02x - %s\n", b5,s1); switch(b6) { /*link type ext*/ case AMC_LINK_TYPE_EXT_ETH_1000_BX: s2 = "1000Base-Bx (SerDES Gigabit) Ethernet Link"; break; case AMC_LINK_TYPE_EXT_ETH_10G_XAUI: s2 = "10Gbit XAUI Ethernet Link"; break; default: s2 = "Invalid"; break; } printf("\t Link Type Ext: %02x - %s\n", b6,s2); break; case FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE: printf("\t Link Type: %02x - %s\n", b5, "AMC.3 Storage"); switch(b6) { /*link type ext*/ case AMC_LINK_TYPE_EXT_STORAGE_FC: s2 = "Fibre Channel"; break; case AMC_LINK_TYPE_EXT_STORAGE_SATA: s2 = "Serial ATA"; break; case AMC_LINK_TYPE_EXT_STORAGE_SAS: s2 = "Serial Attached SCSI"; break; default: s2 = "Invalid"; break; } printf("\t Link Type Ext: %02x - %s\n", b6,s2); break; case FRU_PICMGEXT_AMC_LINK_TYPE_RAPIDIO: printf("\t Link Type: %02x - %s\n", b5, "AMC.4 Serial Rapid IO"); printf("\t Link Type Ext: %02x\n", b6); break; default: printf("\t Link Type: %02x - %s\n", b5, "reserved or OEM GUID"); printf("\t Link Type Ext: %02x\n", b6); break; } /*end switch(link_type)*/ printf("\t Link group Id: %i\n", b7); printf("\t Link Asym Match: %i\n", b8); } /*end ext descriptor loop*/ break; case FRU_AMC_CARRIER_INFO: printf("\tFRU_AMC_CARRIER_INFO\n"); b1 = pdata[i++]; /*extVersion*/ n = pdata[i++]; /*siteCount*/ printf("\t AMC.0 extension version: R%d.%d\n", b1 & 0x0f, (b1 >> 4) & 0x0f); printf("\t Carrier Site Count: %d\n",n); for (j = 0; j < n; j++) { if (i >= dlen) break; printf("\t Site ID: %i\n", pdata[i++]); } break; case FRU_PICMG_CLK_CARRIER_P2P: printf("\tFRU_PICMG_CLK_CARRIER_P2P\n"); b0 = pdata[i++]; n = pdata[i++]; k = (b0 & 0xC0) >> 6; switch(k) { case 0: s1 = "On-Carrier-Device"; break; case 1: s1 = "AMC slot"; break; case 2: s1 = "Backplane"; break; default: s1 = "reserved"; break; } printf("\t Clock Resource ID: %02x, Type: %s\n",b0,s1 ); printf("\t Channel Count : %02x\n",n); for (j = 0; j < n; j++) { b1 = pdata[i++]; /*local channel*/ b2 = pdata[i++]; /*remote channel*/ b3 = pdata[i++]; /*remote resource*/ k = (b3 & 0xC0) >> 6; switch(k) { case 0: s1 = "Carrier-Dev"; break; case 1: s1 = "AMC slot "; break; case 2: s1 = "Backplane "; break; default: s1 = "reserved "; break; } printf("\t CLK-ID: %02x -> %02x [ %s %02x ]\n",b1,b2,s1,b3); } break; case FRU_PICMG_CLK_CONFIG: printf("\tFRU_PICMG_CLK_CONFIG\n"); b0 = pdata[i++]; n = pdata[i++]; printf("\t Clock Resource ID: %02x\n",b0); printf("\t Descriptor Count : %02x\n",n); for (j = 0; j < n; j++) { b1 = pdata[i++]; /*channel id*/ b2 = pdata[i++]; /*control*/ printf("\t CLK-ID: %02x - CTRL %02x [ %12s ]\n", b1, b2, (b2 & 0x01) == 0 ? "Carrier IPMC":"Application"); b3 = pdata[i++]; /*indirect_cnt*/ b4 = pdata[i++]; /*direct_cnt*/ printf("\t Cnt: Indirect %02x / Direct %02x\n",b3,b4); for (k = 0; k < b3; k++) { b5 = pdata[i++]; /*feature*/ b6 = pdata[i++]; /*dep_chn_id*/ printf("\t Feature: %02x [%8s] - ", b5, (b5 & 0x01)==1 ? "Source":"Receiver"); printf("Dep. CLK-ID: %02x\n",b6); } for (k = 0; k < b4; k++) { b5 = pdata[i++]; /*feature*/ b6 = pdata[i++]; /*family*/ b7 = pdata[i++]; /*accuracy*/ l1 = pdata[i] | (pdata[i+1] << 8) | /*frequency*/ (pdata[i+2] << 8) | (pdata[i+3] << 8); i += 4; l2 = pdata[i] | (pdata[i+1] << 8) | /*min frequency*/ (pdata[i+2] << 8) | (pdata[i+3] << 8); i += 4; l3 = pdata[i] | (pdata[i+1] << 8) | /*max frequency*/ (pdata[i+2] << 8) | (pdata[i+3] << 8); i += 4; printf("\t Feature: %02x - PLL: %x / Asym: %s\n", b5, (b5 >> 1) & 0x01, (b5 & 1) ? "Source":"Receiver"); printf("\t Family : %02x - AccLVL: %02x\n", b6, b7); printf("\t FRQ : %-9d, min: %-9d, max: %-9d\n", (int)l1, (int)l2, (int)l3); } } break; case FRU_UTCA_FRU_INFO_TABLE: case FRU_UTCA_CARRIER_MNG_IP: case FRU_UTCA_CARRIER_INFO: case FRU_UTCA_CARRIER_LOCATION: case FRU_UTCA_SHMC_IP_LINK: case FRU_UTCA_POWER_POLICY: case FRU_UTCA_ACTIVATION: case FRU_UTCA_PM_CAPABILTY: case FRU_UTCA_FAN_GEOGRAPHY: case FRU_UTCA_CLOCK_MAPPING: case FRU_UTCA_MSG_BRIDGE_POLICY: case FRU_UTCA_OEM_MODULE_DESC: printf("\tNot yet implemented uTCA record %x\n",id); break; default: printf("\tUnknown PICMG Extension %x\n",id); break; } } /*end show_fru_picmg*/ /*end ifru_picmg.c */ ipmiutil-3.1.5/util/isensor.c0000644000076400007640000036374513566765324016303 0ustar mgportalloggers/* * 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 * 1) correct raw readings to floatval * 2) allow extra SDR bytes returned from HP netserver 1000r * Guo Min * 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 #include #include // for: double pow(double x, double y); #include #include #ifdef WIN32 #include #include "getopt.h" #elif defined(DOS) #include #include "getopt.h" #else #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #if defined(LINUX) #include #include #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= 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 { 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 > 0) { /* ret is a completion code error */ fprintf(stderr,"%04x GetSDR error 0x%02x %s, rlen=%d\n", recid,ret,decode_cc((ushort)0,(uchar)ret),sz); if (ret == 0xC5) { /* lost Reservation ID, retry */ /* This means that some other IPMI software has * requested a Reservation before we finished, so * we need to refresh the Reservation ID * retry. */ fDoReserve = 1; /* get a new SDR Reservation ID */ ret = GetSDR(recid,&recnext,sdrdata,sizeof(sdrdata),&sz); if (fdebug) printf("GetSDR[%04x]: ret = %x, next=%x\n",recid,ret, recnext); if (ret == 0xC5) sz = 0; /*failed to get Reservation ID*/ } } else 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 */ ipmiutil-3.1.5/util/ifirewall.c0000644000076400007640000010501113566765324016553 0ustar mgportalloggers/* * ifirewall.c * Handle firmware firewall IPMI command functions * * Change history: * 06/04/2010 ARCress - included in source tree * *--------------------------------------------------------------------- * Copyright (c) 2010 Kontron America Inc. All Rights Reserved, * Copyright (c) 2005 International Business Machines, Inc. All Rights Reserved * Copyright (c) 2003 Sun Microsystems, 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: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution 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. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. *--------------------------------------------------------------------- */ #ifdef WIN32 #include #include #include #include #include "getopt.h" #else #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include "ipmicmd.h" #include "ifirewall.h" /* global variables */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil firewall"; #else static char * progver = "3.08"; static char * progname = "ifirewall"; #endif static char fdebug = 0; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; extern int verbose; /*see ipmilanplus.c*/ extern void lprintf(int level, const char * format, ...); /*ipmilanplus.c*/ static void printf_firewall_usage(void) { printf("Firmware Firewall Commands:\n"); printf("\tinfo [channel H] [lun L]\n"); printf("\tinfo [channel H] [lun L [netfn N [command C [subfn S]]]]\n"); printf("\tenable [channel H] [lun L [netfn N [command C [subfn S]]]]\n"); printf("\tdisable [channel H] [lun L [netfn N [command C [subfn S]]]] [force])\n"); printf("\treset [channel H] \n"); printf("\t\twhere H is a Channel, L is a LUN, N is a NetFn,\n"); printf("\t\tC is a Command and S is a Sub-Function\n"); } // print n bytes of bit field bf (if invert, print ~bf) static void print_bitfield(const unsigned char * bf, int n, int invert, int loglevel) { int i = 0; if (loglevel < 0) { while (ichannel = atob(argv[i]); } else if (strncmp(argv[i], "lun", 3) == 0) { if (++i < argc) p->lun = atob(argv[i]); } else if (strncmp(argv[i], "force", 5) == 0) { p->force = 1; } else if (strncmp(argv[i], "netfn", 5) == 0) { if (++i < argc) p->netfn = atob(argv[i]); } else if (strncmp(argv[i], "command", 7) == 0) { if (++i < argc) p->command = atob(argv[i]); } else if (strncmp(argv[i], "subfn", 5) == 0) { if (++i < argc) p->subfn = atob(argv[i]); } } if (p->subfn >= MAX_SUBFN) { printf("subfn is out of range (0-%d)\n", MAX_SUBFN-1); return -1; } if (p->command >= MAX_COMMAND) { printf("command is out of range (0-%d)\n", MAX_COMMAND-1); return -1; } if (p->netfn >= MAX_NETFN) { printf("netfn is out of range (0-%d)\n", MAX_NETFN-1); return -1; } if (p->lun >= MAX_LUN) { printf("lun is out of range (0-%d)\n", MAX_LUN-1); return -1; } if (p->netfn >= 0 && p->lun < 0) { printf("if netfn is set, lun must be set also\n"); return -1; } if (p->command >= 0 && p->netfn < 0) { printf("if command is set, netfn must be set also\n"); return -1; } if (p->subfn >= 0 && p->command < 0) { printf("if subfn is set, command must be set also\n"); return -1; } return 0; } /* _get_netfn_suport * * @intf: ipmi interface * @channel: ipmi channel * @lun: a pointer to a 4 byte field * @netfn: a pointer to a 128-bit bitfield (16 bytes) * * returns 0 on success and fills in the bitfield for * the 32 netfn * 4 LUN pairs that support commands * returns -1 on error */ static int _get_netfn_support(void * intf, int channel, unsigned char * lun, unsigned char * netfn) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char * d, rqdata; unsigned int l; if (!lun || !netfn) { lprintf(LOG_ERR, "_get_netfn_suport: lun or netfn is NULL"); return -1; } memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_GET_NETFN_SUPPORT; rqdata = (unsigned char) channel; req.msg.data = &rqdata; req.msg.data_len = 1; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Get NetFn Support command failed: %d (0x%02x)\n",rv,rv); return(rv); } d = &rsp[0]; for (l=0; l<4; l++) { lun[l] = (*d)>>(2*l) & 0x3; } d++; memcpy(netfn, d, 16); return 0; } /* _get_command_suport * * @intf: ipmi interface * @p: a pointer to a struct ipmi_function_params * @lnfn: a pointer to a struct lun_netfn_support * * returns 0 on success and fills in lnfn according to the request in p * returns -1 on error */ static int _get_command_support(void * intf, struct ipmi_function_params * p, struct lun_netfn_support * lnfn) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char * d, rqdata[3]; unsigned int c; if (!p || !lnfn) { lprintf(LOG_ERR, "_get_command_suport: p or lnfn is NULL"); return -1; } memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_GET_COMMAND_SUPPORT; rqdata[0] = (unsigned char)p->channel; rqdata[1] = (unsigned char)p->netfn; rqdata[2] = (unsigned char)p->lun; req.msg.data = rqdata; req.msg.data_len = 3; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Get Command Support (LUN=%d, NetFn=%d, op=0) command failed: %d (0x%02x)\n", p->lun, p->netfn, rv,rv); return(rv); } d = &rsp[0]; for (c=0; c<128; c++) { if (!(d[c>>3] & (1<<(c%8)))) lnfn->command[c].support |= BIT_AVAILABLE; } memcpy(lnfn->command_mask, d, MAX_COMMAND_BYTES/2); memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_GET_COMMAND_SUPPORT; rqdata[0] = (unsigned char)p->channel; rqdata[1] = (unsigned char)(0x40 | p->netfn); rqdata[2] = (unsigned char)p->lun; req.msg.data = rqdata; req.msg.data_len = 3; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Get Command Support (LUN=%d, NetFn=%d, op=1) command failed: %d (0x%02x)\n", p->lun, p->netfn, rv,rv); return(rv); } d = &rsp[0]; for (c=0; c<128; c++) { if (!(d[c>>3] & (1<<(c%8)))) lnfn->command[128+c].support |= BIT_AVAILABLE; } memcpy(lnfn->command_mask+MAX_COMMAND_BYTES/2, d, MAX_COMMAND_BYTES/2); return 0; } /* _get_command_configurable * * @intf: ipmi interface * @p: a pointer to a struct ipmi_function_params * @lnfn: a pointer to a struct lun_netfn_support * * returns 0 on success and fills in lnfn according to the request in p * returns -1 on error */ static int _get_command_configurable(void * intf, struct ipmi_function_params * p, struct lun_netfn_support * lnfn) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char * d, rqdata[3]; unsigned int c; if (!p || !lnfn) { lprintf(LOG_ERR, "_get_command_configurable: p or lnfn is NULL"); return -1; } memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_GET_CONFIGURABLE_COMMANDS; rqdata[0] = (unsigned char)p->channel; rqdata[1] = (unsigned char)p->netfn; rqdata[2] = (unsigned char)p->lun; req.msg.data = rqdata; req.msg.data_len = 3; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Get Configurable Command (LUN=%d, NetFn=%d, op=0) command failed: %d (0x%02x)\n", p->lun, p->netfn, rv,rv); return(rv); } d = rsp; for (c=0; c<128; c++) { if (d[c>>3] & (1<<(c%8))) lnfn->command[c].support |= BIT_CONFIGURABLE; } memcpy(lnfn->config_mask, d, MAX_COMMAND_BYTES/2); memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_GET_CONFIGURABLE_COMMANDS; rqdata[0] = (unsigned char) p->channel; rqdata[1] = (unsigned char)(0x40 | p->netfn); rqdata[2] = (unsigned char)p->lun; req.msg.data = rqdata; req.msg.data_len = 3; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Get Configurable Command (LUN=%d, NetFn=%d, op=1) command failed: %d (0x%02x)\n", p->lun, p->netfn, rv,rv); return(rv); } d = rsp; for (c=0; c<128; c++) { if (d[c>>3] & (1<<(c%8))) lnfn->command[128+c].support |= BIT_CONFIGURABLE; } memcpy(lnfn->config_mask+MAX_COMMAND_BYTES/2, d, MAX_COMMAND_BYTES/2); return 0; } /* _get_command_enables * * @intf: ipmi interface * @p: a pointer to a struct ipmi_function_params * @lnfn: a pointer to a struct lun_netfn_support * * returns 0 on success and fills in lnfn according to the request in p * returns -1 on error */ static int _get_command_enables(void * intf, struct ipmi_function_params * p, struct lun_netfn_support * lnfn) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char * d, rqdata[3]; unsigned int c; if (!p || !lnfn) { lprintf(LOG_ERR, "_get_command_enables: p or lnfn is NULL"); return -1; } memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_GET_COMMAND_ENABLES; rqdata[0] = (unsigned char) p->channel; rqdata[1] = (unsigned char)p->netfn; rqdata[2] = (unsigned char)p->lun; req.msg.data = rqdata; req.msg.data_len = 3; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Get Command Enables (LUN=%d, NetFn=%d, op=0) command failed: %d (0x%02x)\n", p->lun, p->netfn, rv,rv); return(rv); } d = rsp; for (c=0; c<128; c++) { if (d[c>>3] & (1<<(c%8))) lnfn->command[c].support |= BIT_ENABLED; } memcpy(lnfn->enable_mask, d, MAX_COMMAND_BYTES/2); memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_GET_COMMAND_ENABLES; rqdata[0] = (unsigned char) p->channel; rqdata[1] = (unsigned char)(0x40 | p->netfn); rqdata[2] = (unsigned char)p->lun; req.msg.data = rqdata; req.msg.data_len = 3; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Get Command Enables (LUN=%d, NetFn=%d, op=1) command failed: %d (0x%02x)\n", p->lun, p->netfn, rv,rv); return(rv); } d = rsp; for (c=0; c<128; c++) { if (d[c>>3] & (1<<(c%8))) lnfn->command[128+c].support |= BIT_ENABLED; } memcpy(lnfn->enable_mask+MAX_COMMAND_BYTES/2, d, MAX_COMMAND_BYTES/2); return 0; } /* _set_command_enables * * @intf: ipmi interface * @p: a pointer to a struct ipmi_function_params * @lnfn: a pointer to a struct lun_netfn_support that contains current info * @enable: a pointer to a 32 byte bitfield that contains the desired enable state * @gun: here is a gun to shoot yourself in the foot. If this is true * you are allowed to disable this command * * returns 0 on success * returns -1 on error */ static int _set_command_enables(void * intf, struct ipmi_function_params * p, struct lun_netfn_support * lnfn, unsigned char * enable, int gun) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char * d, rqdata[19]; unsigned int c; if (!p || !lnfn) { lprintf(LOG_ERR, "_set_command_enables: p or lnfn is NULL"); return -1; } lprintf(LOG_INFO, "support: "); print_bitfield(lnfn->command_mask, MAX_COMMAND_BYTES, 1, LOG_INFO); lprintf(LOG_INFO, "configurable: "); print_bitfield(lnfn->config_mask, MAX_COMMAND_BYTES, 0, LOG_INFO); lprintf(LOG_INFO, "enabled: "); print_bitfield(lnfn->enable_mask, MAX_COMMAND_BYTES, 0, LOG_INFO); lprintf(LOG_INFO, "enable mask before: "); print_bitfield(enable, MAX_COMMAND_BYTES, 0, LOG_INFO); // mask off the appropriate bits (if not configurable, set enable bit // must be the same as the current enable bit) for (c=0; c<(MAX_COMMAND_BYTES); c++) { enable[c] = (lnfn->config_mask[c] & enable[c]) | (~lnfn->config_mask[c] & lnfn->enable_mask[c]); } // take the gun out of their hand if they are not supposed to have it if (!gun) { enable[SET_COMMAND_ENABLE_BYTE] = (lnfn->config_mask[SET_COMMAND_ENABLE_BYTE] & SET_COMMAND_ENABLE_BIT) | (~lnfn->config_mask[SET_COMMAND_ENABLE_BYTE] & lnfn->enable_mask[SET_COMMAND_ENABLE_BYTE]); } lprintf(LOG_INFO, "enable mask after: "); print_bitfield(enable, MAX_COMMAND_BYTES, 0, LOG_INFO); memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_SET_COMMAND_ENABLES; rqdata[0] = (unsigned char) p->channel; rqdata[1] = (unsigned char)p->netfn; rqdata[2] = (unsigned char)p->lun; memcpy(&rqdata[3], enable, MAX_COMMAND_BYTES/2); req.msg.data = rqdata; req.msg.data_len = 19; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Set Command Enables (LUN=%d, NetFn=%d, op=0) command failed: %d (0x%02x)\n", p->lun, p->netfn, rv,rv); return(rv); } d = &rsp[0]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_SET_COMMAND_ENABLES; rqdata[0] = (unsigned char) p->channel; rqdata[1] = (unsigned char)(0x40 | p->netfn); rqdata[2] = (unsigned char)p->lun; memcpy(&rqdata[3], enable+MAX_COMMAND_BYTES/2, MAX_COMMAND_BYTES/2); req.msg.data = rqdata; req.msg.data_len = 19; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Set Command Enables (LUN=%d, NetFn=%d, op=1) command failed: %d (0x%02x)\n", p->lun, p->netfn, rv,rv); return(rv); } d = &rsp[0]; return 0; } /* _get_subfn_support * * @intf: ipmi interface * @p: a pointer to a struct ipmi_function_params * @cmd: a pointer to a struct command_support * * returns 0 on success and fills in cmd according to the request in p * returns -1 on error */ static int _get_subfn_support(void * intf, struct ipmi_function_params * p, struct command_support * cmd) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char rqdata[4]; if (!p || !cmd) { lprintf(LOG_ERR, "_get_subfn_support: p or cmd is NULL"); return -1; } memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_GET_COMMAND_SUBFUNCTION_SUPPORT; rqdata[0] = (unsigned char) p->channel; rqdata[1] = (unsigned char)p->netfn; rqdata[2] = (unsigned char)p->lun; rqdata[3] = (unsigned char)p->command; req.msg.data = rqdata; req.msg.data_len = 4; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Get Command Subfunction Support (LUN=%d, NetFn=%d, cmd=%d) command failed: %d (0x%02x)\n", p->lun, p->netfn, p->command, rv,rv); return(rv); } memcpy(cmd->subfn_support, rsp, sizeof(cmd->subfn_support)); return 0; } /* _get_subfn_configurable * * @intf: ipmi interface * @p: a pointer to a struct ipmi_function_params * @cmd: a pointer to a struct command_support * * returns 0 on success and fills in cmd according to the request in p * returns -1 on error */ static int _get_subfn_configurable(void * intf, struct ipmi_function_params * p, struct command_support * cmd) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char rqdata[4]; if (!p || !cmd) { lprintf(LOG_ERR, "_get_subfn_configurable: p or cmd is NULL"); return -1; } memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_GET_CONFIGURABLE_COMMAND_SUBFUNCTIONS; rqdata[0] = (unsigned char) p->channel; rqdata[1] = (unsigned char)p->netfn; rqdata[2] = (unsigned char)p->lun; rqdata[3] = (unsigned char)p->command; req.msg.data = rqdata; req.msg.data_len = 4; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Get Configurable Command Subfunction Support (LUN=%d, NetFn=%d, cmd=%d) command failed: %d (0x%02x)\n", p->lun, p->netfn, p->command, rv,rv); return(rv); } memcpy(cmd->subfn_config, rsp, sizeof(cmd->subfn_config)); return 0; } /* _get_subfn_enables * * @intf: ipmi interface * @p: a pointer to a struct ipmi_function_params * @cmd: a pointer to a struct command_support * * returns 0 on success and fills in cmd according to the request in p * returns -1 on error */ static int _get_subfn_enables(void * intf, struct ipmi_function_params * p, struct command_support * cmd) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char rqdata[4]; if (!p || !cmd) { lprintf(LOG_ERR, "_get_subfn_enables: p or cmd is NULL"); return -1; } memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_GET_COMMAND_SUBFUNCTION_ENABLES; rqdata[0] = (unsigned char) p->channel; rqdata[1] = (unsigned char)p->netfn; rqdata[2] = (unsigned char)p->lun; rqdata[3] = (unsigned char)p->command; req.msg.data = rqdata; req.msg.data_len = 4; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Get Command Subfunction Enables (LUN=%d, NetFn=%d, cmd=%d) command failed: %d (0x%02x)\n", p->lun, p->netfn, p->command, rv,rv); return(rv); } memcpy(cmd->subfn_enable, rsp, sizeof(cmd->subfn_enable)); return 0; } /* _set_subfn_enables * * @intf: ipmi interface * @p: a pointer to a struct ipmi_function_params * @cmd: a pointer to a struct command_support * @enable: a pointer to a 4 byte bitfield that contains the desired enable state * * returns 0 on success (and modifies enable to be the bits it actually set) * returns -1 on error */ static int _set_subfn_enables(void * intf, struct ipmi_function_params * p, struct command_support * cmd, unsigned char * enable) { struct ipmi_rq req; uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; unsigned char rqdata[8]; unsigned int c; if (!p || !cmd) { lprintf(LOG_ERR, "_set_subfn_enables: p or cmd is NULL"); return -1; } lprintf(LOG_INFO, "support: "); print_bitfield(cmd->subfn_support, MAX_SUBFN_BYTES, 1, LOG_INFO); lprintf(LOG_INFO, "configurable: "); print_bitfield(cmd->subfn_config, MAX_SUBFN_BYTES, 0, LOG_INFO); lprintf(LOG_INFO, "enabled: "); print_bitfield(cmd->subfn_enable, MAX_SUBFN_BYTES, 0, LOG_INFO); lprintf(LOG_INFO, "enable mask before: "); print_bitfield(enable, MAX_SUBFN_BYTES, 0, LOG_INFO); // mask off the appropriate bits (if not configurable, set enable bit // must be the same as the current enable bit) for (c=0; csubfn_enable); c++) { enable[c] = (cmd->subfn_config[c] & enable[c]) | (~cmd->subfn_config[c] & cmd->subfn_enable[c]); } lprintf(LOG_INFO, "enable mask after: "); print_bitfield(enable, MAX_SUBFN_BYTES, 0, LOG_INFO); memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_SET_COMMAND_SUBFUNCTION_ENABLES; rqdata[0] = (unsigned char) p->channel; rqdata[1] = (unsigned char)p->netfn; rqdata[2] = (unsigned char)p->lun; rqdata[3] = (unsigned char)p->command; memcpy(&rqdata[4], enable, MAX_SUBFN_BYTES); req.msg.data = rqdata; req.msg.data_len = 8; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Set Command Subfunction Enables (LUN=%d, NetFn=%d, cmd=%d) command failed: %d (0x%02x)\n", p->lun, p->netfn, p->command, rv,rv); return(rv); } return 0; } /* _gather_info * * @intf: ipmi interface * @p: a pointer to a struct ipmi_function_params * @bmc: a pointer to a struct bmc_fn_support * @enable: a pointer to a 4 byte bitfield that contains the desired enable state * * returns 0 on success and fills in bmc according to request p * returns -1 on error */ static int _gather_info(void * intf, struct ipmi_function_params * p, struct bmc_fn_support * bmc) { int ret, l, n; unsigned char lun[MAX_LUN], netfn[16]; ret = _get_netfn_support(intf, p->channel, lun, netfn); if (ret != 0) return (ret); else { /*success*/ for (l=0; llun >= 0 && p->lun != l) continue; bmc->lun[l].support = lun[l]; if (lun[l]) { for (n=0; nlun[l].netfn[n].support = !!(netfn[offset>>3] & (1<<(offset%8))); } } } } if (p->netfn >= 0) { if (!((p->lun < 0 || bmc->lun[p->lun].support) && (p->netfn < 0 || bmc->lun[p->lun].netfn[p->netfn>>1].support))) { lprintf(LOG_ERR, "LUN or LUN/NetFn pair %d,%d not supported", p->lun, p->netfn); return 0; } ret = _get_command_support(intf, p, &(bmc->lun[p->lun].netfn[p->netfn>>1])); ret |= _get_command_configurable(intf, p, &(bmc->lun[p->lun].netfn[p->netfn>>1])); ret |= _get_command_enables(intf, p, &(bmc->lun[p->lun].netfn[p->netfn>>1])); if (!ret && p->command >= 0) { ret = _get_subfn_support(intf, p, &(bmc->lun[p->lun].netfn[p->netfn>>1].command[p->command])); ret |= _get_subfn_configurable(intf, p, &(bmc->lun[p->lun].netfn[p->netfn>>1].command[p->command])); ret |= _get_subfn_enables(intf, p, &(bmc->lun[p->lun].netfn[p->netfn>>1].command[p->command])); } } else if (p->lun >= 0) { l = p->lun; if (bmc->lun[l].support) { for (n=0; nnetfn = n*2; if (bmc->lun[l].netfn[n].support) { ret = _get_command_support(intf, p, &(bmc->lun[l].netfn[n])); ret |= _get_command_configurable(intf, p, &(bmc->lun[l].netfn[n])); ret |= _get_command_enables(intf, p, &(bmc->lun[l].netfn[n])); } if (ret) bmc->lun[l].netfn[n].support = 0; } } p->netfn = -1; } else { for (l=0; l<4; l++) { p->lun = l; if (bmc->lun[l].support) { for (n=0; nnetfn = n*2; if (bmc->lun[l].netfn[n].support) { ret = _get_command_support(intf, p, &(bmc->lun[l].netfn[n])); ret |= _get_command_configurable(intf, p, &(bmc->lun[l].netfn[n])); ret |= _get_command_enables(intf, p, &(bmc->lun[l].netfn[n])); } if (ret) bmc->lun[l].netfn[n].support = 0; } } } p->lun = -1; p->netfn = -1; } return 0; } /* ipmi_firewall_info - print out info for firewall functions * * @intf: ipmi inteface * @argc: argument count * @argv: argument list * * returns 0 on success * returns -1 on error */ static int ipmi_firewall_info(void * intf, int argc, char ** argv) { int ret = 0; struct ipmi_function_params p = {0xe, -1, -1, -1, -1}; struct bmc_fn_support * bmc_fn_support; unsigned int l, n, c; if ((argc > 0 && strncmp(argv[0], "help", 4) == 0) || ipmi_firewall_parse_args(argc, argv, &p) < 0) { printf("info [channel H]\n"); printf("\tlist all of the firewall information for all LUNs, NetFns, and Commands\n"); printf("\tthis is a long list and is not very human readable\n"); printf("info [channel H] lun L\n"); printf("\tthis also prints a long list that is not very human readable\n"); printf("info [channel H] lun L netfn N\n"); printf("\tthis prints out information for a single LUN/NetFn pair\n"); printf("\tthat is not really very usable, but at least it is short\n"); printf("info [channel H] lun L netfn N command C\n"); printf("\tthis is the one you want -- it prints out detailed human\n"); printf("\treadable information. It shows the support, configurable, and\n"); printf("\tenabled bits for the Command C on LUN/NetFn pair L,N and the\n"); printf("\tsame information about each of its Sub-functions\n"); return 0; } bmc_fn_support = malloc(sizeof(struct bmc_fn_support)); if (!bmc_fn_support) { lprintf(LOG_ERR, "malloc struct bmc_fn_support failed"); return -1; } ret = _gather_info(intf, &p, bmc_fn_support); if (p.command >= 0) { struct command_support * cmd; if (!((p.lun < 0 || bmc_fn_support->lun[p.lun].support) && (p.netfn < 0 || bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].support) && bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].command[p.command].support)) { lprintf(LOG_ERR, "Command 0x%02x not supported on LUN/NetFn pair %02x,%02x", p.command, p.lun, p.netfn); free(bmc_fn_support); return 0; } cmd = &bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].command[p.command]; c = cmd->support; printf("(A)vailable, (C)onfigurable, (E)nabled: | A | C | E |\n"); printf("-----------------------------------------------------\n"); printf("LUN %01d, NetFn 0x%02x, Command 0x%02x: | %c | %c | %c |\n", p.lun, p.netfn, p.command, (c & BIT_AVAILABLE) ? 'X' : ' ', (c & BIT_CONFIGURABLE) ? 'X' : ' ', (c & BIT_ENABLED) ? 'X': ' '); for (n=0; nsubfn_support, n)) ? 'X' : ' ', (bit_test(cmd->subfn_config, n)) ? 'X' : ' ', (bit_test(cmd->subfn_enable, n)) ? 'X' : ' '); } } else if (p.netfn >= 0) { if (!((p.lun < 0 || bmc_fn_support->lun[p.lun].support) && (bmc_fn_support->lun[p.lun].netfn[p.netfn>>1].support))) { lprintf(LOG_ERR, "LUN or LUN/NetFn pair %02x,%02x not supported", p.lun, p.netfn); free(bmc_fn_support); return 0; } n = p.netfn >> 1; l = p.lun; printf("Commands on LUN 0x%02x, NetFn 0x%02x\n", p.lun, p.netfn); printf("support: "); print_bitfield(bmc_fn_support->lun[l].netfn[n].command_mask, MAX_COMMAND_BYTES, 1, -1); printf("configurable: "); print_bitfield(bmc_fn_support->lun[l].netfn[n].config_mask, MAX_COMMAND_BYTES, 0, -1); printf("enabled: "); print_bitfield(bmc_fn_support->lun[l].netfn[n].enable_mask, MAX_COMMAND_BYTES, 0, -1); } else { for (l=0; l<4; l++) { p.lun = l; if (bmc_fn_support->lun[l].support) { for (n=0; nlun[l].netfn[n].support) { printf("%02x,%02x support: ", p.lun, p.netfn); print_bitfield(bmc_fn_support->lun[l].netfn[n].command_mask, MAX_COMMAND_BYTES, 1, -1); printf("%02x,%02x configurable: ", p.lun, p.netfn); print_bitfield(bmc_fn_support->lun[l].netfn[n].config_mask, MAX_COMMAND_BYTES, 0, -1); printf("%02x,%02x enabled: ", p.lun, p.netfn); print_bitfield(bmc_fn_support->lun[l].netfn[n].enable_mask, MAX_COMMAND_BYTES, 0, -1); } } } } p.lun = -1; p.netfn = -1; } free(bmc_fn_support); return ret; } /* ipmi_firewall_enable_disable - enable/disable BMC functions * * @intf: ipmi inteface * @enable: whether to enable or disable * @argc: argument count * @argv: argument list * * returns 0 on success * returns -1 on error */ static int ipmi_firewall_enable_disable(void * intf, int enable, int argc, char ** argv) { struct ipmi_function_params p = {0xe, -1, -1, -1, -1}; struct bmc_fn_support * bmc_fn_support; unsigned int l, n, c; int ret; unsigned char enables[MAX_COMMAND_BYTES]; if (argc < 1 || strncmp(argv[0], "help", 4) == 0) { char * s1 = enable?"en":"dis"; char * s2 = enable?"":" [force]"; printf("%sable [channel H] lun L netfn N%s\n", s1, s2); printf("\t%sable all commands on this LUN/NetFn pair\n", s1); printf("%sable [channel H] lun L netfn N command C%s\n", s1, s2); printf("\t%sable Command C and all its Sub-functions for this LUN/NetFn pair\n", s1); printf("%sable [channel H] lun L netfn N command C subfn S\n", s1); printf("\t%sable Sub-function S for Command C for this LUN/NetFn pair\n", s1); if (!enable) { printf("* force will allow you to disable the \"Command Set Enable\" command\n"); printf("\tthereby letting you shoot yourself in the foot\n"); printf("\tthis is only recommended for advanced users\n"); } return 0; } if (ipmi_firewall_parse_args(argc, argv, &p) < 0) return -1; bmc_fn_support = malloc(sizeof(struct bmc_fn_support)); if (!bmc_fn_support) { lprintf(LOG_ERR, "malloc struct bmc_fn_support failed"); return -1; } ret = _gather_info(intf, &p, bmc_fn_support); if (ret < 0) { free(bmc_fn_support); return ret; } l = p.lun; n = p.netfn>>1; c = p.command; if (p.subfn >= 0) { // firewall (en|dis)able [channel c] lun l netfn n command m subfn s // (en|dis)able this sub-function for this commnad on this lun/netfn pair memcpy(enables, bmc_fn_support->lun[l].netfn[n].command[c].subfn_enable, MAX_SUBFN_BYTES); bit_set(enables, p.subfn, enable); ret = _set_subfn_enables(intf, &p, &bmc_fn_support->lun[l].netfn[n].command[c], enables); } else if (p.command >= 0) { // firewall (en|dis)able [channel c] lun l netfn n command m // (en|dis)able all subfn and command for this commnad on this lun/netfn pair memset(enables, enable?0xff:0, MAX_SUBFN_BYTES); ret = _set_subfn_enables(intf, &p, &bmc_fn_support->lun[l].netfn[n].command[c], enables); memcpy(enables, &bmc_fn_support->lun[l].netfn[n].enable_mask, sizeof(enables)); bit_set(enables, p.command, enable); ret |= _set_command_enables(intf, &p, &bmc_fn_support->lun[l].netfn[n], enables, p.force); } else if (p.netfn >= 0) { // firewall (en|dis)able [channel c] lun l netfn n // (en|dis)able all commnads on this lun/netfn pair memset(enables, enable?0xff:0, sizeof(enables)); ret = _set_command_enables(intf, &p, &bmc_fn_support->lun[l].netfn[n], enables, p.force); /* } else if (p.lun >= 0) { // firewall (en|dis)able [channel c] lun l // (en|dis)able all commnads on all netfn pairs for this lun */ } free(bmc_fn_support); return ret; } /* ipmi_firewall_reset - reset firmware firewall to enable everything * * @intf: ipmi inteface * @argc: argument count * @argv: argument list * * returns 0 on success * returns -1 on error */ static int ipmi_firewall_reset(void * intf, int argc, char ** argv) { struct ipmi_function_params p = {0xe, -1, -1, -1, -1}; struct bmc_fn_support * bmc_fn_support; unsigned int l, n, c; int ret; unsigned char enables[MAX_COMMAND_BYTES]; if (argc > 0 || (argc > 0 && strncmp(argv[0], "help", 4) == 0)) { printf_firewall_usage(); return 0; } if (ipmi_firewall_parse_args(argc, argv, &p) < 0) return -1; bmc_fn_support = malloc(sizeof(struct bmc_fn_support)); if (!bmc_fn_support) { lprintf(LOG_ERR, "malloc struct bmc_fn_support failed"); return -1; } ret = _gather_info(intf, &p, bmc_fn_support); if (ret < 0) { free(bmc_fn_support); return ret; } for (l=0; llun[l].netfn[n].command[c], enables); } printf("reset lun %d, netfn %d, command\n", l, n); memset(enables, 0xff, sizeof(enables)); ret = _set_command_enables(intf, &p, &bmc_fn_support->lun[l].netfn[n], enables, 0); } } free(bmc_fn_support); return ret; } #ifdef METACOMMAND int i_firewall(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { void *intf = NULL; int rc = 0; int c, i; char *s1; printf("%s ver %s\n", progname,progver); while ( (c = getopt( argc, argv,"m:T:V:J:EYF:P:N:R:U:Z:x?")) != EOF ) switch (c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'x': fdebug = 1; verbose = 1; break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; case '?': printf_firewall_usage(); return 0; break; } for (i = 0; i < optind; i++) { argv++; argc--; } if (argc < 1 || strncmp(argv[0], "help", 4) == 0) { printf_firewall_usage(); } else if (strncmp(argv[0], "info", 4) == 0) { rc = ipmi_firewall_info(intf, argc-1, &(argv[1])); } else if (strncmp(argv[0], "enable", 6) == 0) { rc = ipmi_firewall_enable_disable(intf, 1, argc-1, &(argv[1])); } else if (strncmp(argv[0], "disable", 7) == 0) { rc = ipmi_firewall_enable_disable(intf, 0, argc-1, &(argv[1])); } else if (strncmp(argv[0], "reset", 5) == 0) { rc = ipmi_firewall_reset(intf, argc-1, &(argv[1])); } else { printf_firewall_usage(); rc = ERR_BAD_PARAM; } ipmi_close_(); // show_outcome(progname,rc); return rc; } ipmiutil-3.1.5/util/ipmiutil64.mak0000644000076400007640000003424713566765324017145 0ustar mgportalloggers# This makefile will build the ipmiutil util directory (x64) # # First download getopt.c getopt.h # Then download and build openssl for Windows # LIBC_RT=libcmt.lib /NODEFAULTLIB:"msvcirt.lib" # LIBC_RT=msvcrt.lib /NODEFAULTLIB:"msvcirt.lib" # The ipmiutil directory SRC_D=. LIB_D=..\lib L2_D=$(LIB_D)\lanplus L3_D=$(LIB_D)\lanplus\inc INSTALLTOP=install TMP_D=tmp INC=/I$(SRC_D) /I$(L2_D) /I$(L3_D) CMD_OBJ = getopt.obj ipmicmd.obj imbapi.obj md5.obj md2.obj \ ipmilan.obj ipmims.obj subs.obj CMD_OBJ = $(CMD_OBJ) ipmilanplus.obj # To remove lanplus support use the empty LANPLUS variables # L2_OBJ= # LF_LANPLUS= # CF_LANPLUS= L2_OBJ = $(L2_D)\helper.obj $(L2_D)\ipmi_strings.obj $(L2_D)\lanplus.obj \ $(L2_D)\lanplus_crypt_impl.obj $(L2_D)\lanplus_dump.obj \ $(L2_D)\lanplus_strings.obj $(L2_D)\lanplus_crypt.obj LF_LANPLUS=/LIBPATH:$(LIB_D) /LIBPATH:$(L2_D) $(L2_OBJ) ssleay32.lib libeay32.lib CF_LANPLUS=/D HAVE_LANPLUS # Set your compiler options # To remove any GPL dependencies, use the CF_EX line with NON_GPL # CFLAGS_O=/W3 /O2 /Zi /MD /GF /Gy /nologo # CFLAGS_O=/W3 /O2 /Zi /MD /nologo # CFLAGS_O=/W3 /O2 /Zi /MT /nologo CFLAGS_O=/W3 /O2 /Zi /MT /nologo CF_EX=/DWIN32 $(CF_LANPLUS) $(INC) /D_CONSOLE /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DHAVE_STRING_H CF_SAM=/DWIN32 $(INC) /D_CONSOLE /D_CRT_SECURE_NO_DEPRECATE /DHAVE_STRING_H $(CF_LANPLUS) CFLAGS=$(CFLAGS_O) $(CF_EX) /DSKIP_MD2 CFLAGS_M=$(CFLAGS_O) $(CF_EX) /DSKIP_MD2 /DMETACOMMAND CFLAGS_SAM=$(CFLAGS_O) $(CF_SAM) LFLAGS=/nologo /subsystem:console /machine:$(MARCH) /opt:ref #LFLAGS=/nologo /subsystem:console /machine:IX86 /opt:ref #LFLAGS=/nologo /subsystem:console /machine:IX86 /opt:ref /debug # LFLAGS_D=/nologo /subsystem:console /machine:I386 /opt:ref /dll # CFLAGS_W=/O2 /D_CONSOLE /D_MBCS /EHsc /ML /W3 /Zi /TP CFLAGS_W=/TP /EHsc $(CFLAGS) LFLAGS_W=/nologo /subsystem:console /machine:$(MARCH) /opt:ref LIBS_W=comsuppw.lib wbemuuid.lib # gdi32.lib comdlg32.lib shell32.lib uuid.lib CC=cl LINK=link MKDIR=-mkdir MKLIB=lib RM=del CP=copy LIBS_EX = advapi32.lib kernel32.lib wsock32.lib ws2_32.lib $(LIBS_W) $(LIBC_RT) LIBS_PEF = /LIBPATH:$(LIB_D) iphlpapi.lib # LIBS_EX+=wsock32.lib user32.lib gdi32.lib HEADER=ipmicmd.h imb_api.h ipmilan.h ipmidir.h ipmilanplus.h \ ipmiutil.h SHOWSEL = showsel TARG_EXE=ievents.exe $(SHOWSEL)msg.dll ipmi_sample.exe ipmi_sample2.exe ipmi_sample_evt.exe $(SAMP_DLL) # alarms.exe ihealth.exe $(SHOWSEL).exe $(SHOWSEL)msg.dll \ # ireset.exe ifru.exe ilan.exe iserial.exe wdt.exe \ # getevent.exe sensor.exe icmd.exe isolconsole.exe idiscover.exe \ # ievents.exe SAMP_LIB = ipmiutil.lib SAMP_DLL = ipmiutillib.dll E_EXE=ipmiutil.exe E_OBJ=$(TMP_D)\ipmiutil.obj \ $(TMP_D)\ialarms.obj $(TMP_D)\ihealth.obj $(TMP_D)\iwdt.obj \ $(TMP_D)\ireset.obj $(TMP_D)\ifru.obj $(TMP_D)\ilan.obj \ $(TMP_D)\iserial.obj $(TMP_D)\icmd.obj $(TMP_D)\isol.obj \ $(TMP_D)\isolwin.obj $(TMP_D)\AnsiTerm.obj $(TMP_D)\idiscover.obj \ $(TMP_D)\iconfig.obj $(TMP_D)\igetevent.obj $(TMP_D)\isensor.obj \ $(TMP_D)\isel.obj $(TMP_D)\ievents.obj \ $(TMP_D)\ipicmg.obj $(TMP_D)\ifirewall.obj \ $(TMP_D)\iekanalyzer.obj $(TMP_D)\ifru_picmg.obj \ $(TMP_D)\oem_kontron.obj $(TMP_D)\ihpm.obj $(TMP_D)\ifwum.obj \ $(TMP_D)\oem_fujitsu.obj $(TMP_D)\oem_intel.obj $(TMP_D)\oem_lenovo.obj \ $(TMP_D)\oem_asus.obj $(TMP_D)\iuser.obj \ $(TMP_D)\oem_sun.obj $(TMP_D)\oem_dell.obj $(TMP_D)\oem_hp.obj \ $(TMP_D)\oem_supermicro.obj $(TMP_D)\itsol.obj $(TMP_D)\idcmi.obj \ $(TMP_D)\oem_quanta.obj $(TMP_D)\oem_newisys.obj $(CMD_OBJ) mem_if.obj ################################################################### all: banner $(TMP_D) exe banner: @echo Building ipmiutil $(TMP_D): $(MKDIR) $(TMP_D) @echo created $(TMP_D) lib: $(L2_OBJ) cd $(LIB_D) nmake /nologo -f ipmilib.mak cd ../util exe: $(E_EXE) $(TARG_EXE) install: $(MKDIR) $(INSTALLTOP) $(MKDIR) $(INSTALLTOP)\bin $(CP) $(E_EXE) $(INSTALLTOP)\bin xcopy $(TARG_EXE) $(INSTALLTOP)\bin xcopy *.dll $(INSTALLTOP)\bin clean: $(RM) *.obj 2>NUL $(RM) $(TARG_EXE) 2>NUL $(RM) *.exe 2>NUL -$(RM) $(TMP_D)\*.obj 2>NUL distclean: $(RM) *.obj 2>NUL $(RM) $(TARG_EXE) 2>NUL $(RM) *.exe 2>NUL -$(RM) $(TMP_D)\*.* 2>NUL rmdir $(TMP_D) 2>NUL $(RM) *.rc 2>NUL $(RM) *.bin 2>NUL $(RM) *.RES 2>NUL $(RM) getopt.* 2>NUL getopt.obj: getopt.c $(CC) /c $(CFLAGS) getopt.c imbapi.obj: imbapi.c $(CC) /c $(CFLAGS_M) imbapi.c ipmicmd.obj: ipmicmd.c $(CC) /c $(CFLAGS) ipmicmd.c ipmilan.obj: ipmilan.c $(CC) /c $(CFLAGS) ipmilan.c ipmilanplus.obj: ipmilanplus.c $(CC) /c $(CFLAGS_M) ipmilanplus.c md5.obj: md5.c $(CC) /c $(CFLAGS) md5.c md2.obj: md2.c $(CC) /c $(CFLAGS) md2.c ievents.obj: ievents.c $(CC) /c $(CFLAGS) ievents.c ialarms.obj: ialarms.c $(CC) /c $(CFLAGS) ialarms.c ihealth.obj: ihealth.c $(CC) /c $(CFLAGS) ihealth.c igetevent.obj: igetevent.c $(CC) /c $(CFLAGS) igetevent.c mem_if.obj: mem_if.c $(CC) /c $(CFLAGS_W) mem_if.c ipmims.obj: ipmims.cpp $(CC) /c $(CFLAGS_W) ipmims.cpp isel.obj: isel.c $(CC) /c $(CFLAGS) isel.c ireset.obj: ireset.c $(CC) /c $(CFLAGS) ireset.c ireset.exe: ireset.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ireset.exe ireset.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) ifru.obj: ifru.c $(CC) /c $(CFLAGS) ifru.c ifru.exe: ifru.obj mem_if.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ifru.exe ifru.obj mem_if.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) ilan.obj: ilan.c $(CC) /c $(CFLAGS) ilan.c ilan.exe: ilan.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ilan.exe ilan.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_PEF) $(LIBS_EX) iserial.obj: iserial.c $(CC) /c $(CFLAGS) iserial.c iserial.exe: iserial.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:iserial.exe iserial.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) isensor.obj: isensor.c $(CC) /c $(CFLAGS) isensor.c isensor.exe: isensor.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:isensor.exe isensor.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) iwdt.obj: iwdt.c $(CC) /c $(CFLAGS) iwdt.c iwdt.exe: iwdt.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:iwdt.exe iwdt.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) isol.obj: isol.c $(CC) /c $(CFLAGS) isol.c isolwin.obj: isolwin.c $(CC) /c $(CFLAGS) isolwin.c isol.exe: isol.obj isolwin.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:isol.exe isol.obj isolwin.obj \ $(CMD_OBJ) $(LF_LANPLUS) $(LIBS_EX) icmd.obj: icmd.c $(CC) /c $(CFLAGS) icmd.c icmd.exe: icmd.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:icmd.exe icmd.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) idiscover.obj: idiscover.c $(CC) /c $(CFLAGS) idiscover.c idiscover.exe: idiscover.obj getopt.obj $(LINK) $(LFLAGS) /OUT:idiscover.exe idiscover.obj getopt.obj \ $(LF_LANPLUS) $(LIBS_EX) ialarms.exe: ialarms.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ialarms.exe ialarms.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) ihealth.exe: ihealth.obj mem_if.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ihealth.exe ihealth.obj mem_if.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) igetevent.exe: igetevent.obj ievents.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:igetevent.exe igetevent.obj ievents.obj \ $(CMD_OBJ) $(LF_LANPLUS) $(LIBS_EX) isel.exe: isel.obj ievents.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:isel.exe isel.obj ievents.obj \ $(CMD_OBJ) $(LF_LANPLUS) $(LIBS_EX) $(SHOWSEL).mc: $(CP) ..\scripts\$(SHOWSEL).mc . $(SHOWSEL)msg.dll: $(SHOWSEL).mc mc -U $(SHOWSEL).mc rc -r $(SHOWSEL).rc $(LINK) /machine:$(MARCH) -dll -noentry -out:$(SHOWSEL)msg.dll $(SHOWSEL).res mem_if.exe: $(TMP_D)\mem_if.obj $(LINK) $(LFLAGS_W) /OUT:mem_if.exe $(TMP_D)\mem_if.obj $(LIBS_EX) $(TMP_D)\mem_if.obj: mem_if.c $(CC) /c $(CFLAGS_W) /DCOMP_BIN /Fo$(TMP_D)\mem_if.obj mem_if.c ievents.exe: ievents.c $(CC) /c $(CFLAGS) /DALONE ievents.c $(LINK) $(LFLAGS) /OUT:ievents.exe ievents.obj $(LIBS_EX) $(RM) ievents.obj ipmims.exe: ipmims.cpp $(CC) /c $(CFLAGS_W) /DALONE /DTEST_BIN ipmims.cpp $(LINK) $(LFLAGS_W) /OUT:ipmims.exe ipmims.obj $(LIBS_EX) $(RM) ipmims.obj $(TMP_D)\ievents.obj: ievents.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ievents.obj ievents.c $(TMP_D)\ipmiutil.obj: ipmiutil.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ipmiutil.obj ipmiutil.c $(TMP_D)\ialarms.obj: ialarms.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ialarms.obj ialarms.c $(TMP_D)\ihealth.obj: ihealth.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ihealth.obj ihealth.c $(TMP_D)\iconfig.obj: iconfig.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iconfig.obj iconfig.c $(TMP_D)\ipicmg.obj: ipicmg.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ipicmg.obj ipicmg.c $(TMP_D)\ifirewall.obj: ifirewall.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifirewall.obj ifirewall.c $(TMP_D)\ifwum.obj: ifwum.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifwum.obj ifwum.c $(TMP_D)\ihpm.obj: ihpm.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ihpm.obj ihpm.c $(TMP_D)\idcmi.obj: idcmi.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\idcmi.obj idcmi.c $(TMP_D)\iuser.obj: iuser.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iuser.obj iuser.c $(TMP_D)\oem_fujitsu.obj: oem_fujitsu.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_fujitsu.obj oem_fujitsu.c $(TMP_D)\oem_kontron.obj: oem_kontron.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_kontron.obj oem_kontron.c $(TMP_D)\oem_intel.obj: oem_intel.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_intel.obj oem_intel.c $(TMP_D)\oem_sun.obj: oem_sun.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_sun.obj oem_sun.c $(TMP_D)\oem_dell.obj: oem_dell.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_dell.obj oem_dell.c $(TMP_D)\oem_hp.obj: oem_hp.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_hp.obj oem_hp.c $(TMP_D)\oem_supermicro.obj: oem_supermicro.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_supermicro.obj oem_supermicro.c $(TMP_D)\oem_lenovo.obj: oem_lenovo.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_lenovo.obj oem_lenovo.c $(TMP_D)\oem_asus.obj: oem_asus.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_asus.obj oem_asus.c $(TMP_D)\oem_quanta.obj: oem_quanta.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_quanta.obj oem_quanta.c $(TMP_D)\oem_newisys.obj: oem_newisys.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_newisys.obj oem_newisys.c $(TMP_D)\iekanalyzer.obj: iekanalyzer.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iekanalyzer.obj iekanalyzer.c $(TMP_D)\ifru_picmg.obj: ifru_picmg.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifru_picmg.obj ifru_picmg.c $(TMP_D)\ifru.obj: ifru.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifru.obj ifru.c $(TMP_D)\ireset.obj: ireset.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ireset.obj ireset.c $(TMP_D)\ilan.obj: ilan.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ilan.obj ilan.c $(TMP_D)\iserial.obj: iserial.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iserial.obj iserial.c $(TMP_D)\isensor.obj: isensor.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isensor.obj isensor.c $(TMP_D)\icmd.obj: icmd.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\icmd.obj icmd.c $(TMP_D)\igetevent.obj: igetevent.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\igetevent.obj igetevent.c $(TMP_D)\isel.obj: isel.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isel.obj isel.c $(TMP_D)\isol.obj: isol.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isol.obj isol.c $(TMP_D)\isolwin.obj: isolwin.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isolwin.obj isolwin.c $(TMP_D)\itsol.obj: itsol.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\itsol.obj itsol.c $(TMP_D)\AnsiTerm.obj: AnsiTerm.cpp $(CC) /c $(CFLAGS_W) /Fo$(TMP_D)\AnsiTerm.obj AnsiTerm.cpp $(TMP_D)\idiscover.obj: idiscover.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\idiscover.obj idiscover.c $(TMP_D)\iwdt.obj: iwdt.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iwdt.obj iwdt.c $(E_EXE): $(E_OBJ) $(LINK) $(LFLAGS) /OUT:$(E_EXE) $(E_OBJ) $(LF_LANPLUS) $(LIBS_PEF) $(LIBS_EX) ipmi_sample.obj: ipmi_sample.c $(CC) /c $(CFLAGS_SAM) ipmi_sample.c $(SAMP_LIB): $(CMD_OBJ) mem_if.obj $(CC) /c $(CFLAGS_SAM) ipmilanplus.c $(MKLIB) /OUT:$(SAMP_LIB) /nologo $(CMD_OBJ) mem_if.obj del ipmilanplus.obj $(SAMP_DLL): $(CMD_OBJ) mem_if.obj $(CC) /D_WINDLL /D_USRDLL /c $(CFLAGS_SAM) ipmilanplus.c $(LINK) /DLL $(LFLAGS) /OUT:$(SAMP_DLL) /def:ipmiutillib.def $(CMD_OBJ) mem_if.obj $(LIBS_PEF) $(LF_LANPLUS) $(LIBS_EX) del ipmilanplus.obj ipmi_sample.exe: $(SAMP_LIB) ipmi_sample.obj $(LINK) $(LFLAGS) /OUT:ipmi_sample.exe ipmi_sample.obj $(SAMP_LIB) $(LIBS_PEF) $(LF_LANPLUS) $(LIBS_EX) ipmi_sample2.exe: $(SAMP_LIB) ipmi_sample.c isensor.c ievents.c $(CC) /c $(CFLAGS_SAM) /DGET_SENSORS ipmi_sample.c $(CC) /c $(CFLAGS_SAM) isensor.c $(CC) /c $(CFLAGS_SAM) ievents.c $(LINK) $(LFLAGS) /OUT:ipmi_sample2.exe ipmi_sample.obj isensor.obj ievents.obj $(SAMP_LIB) $(LIBS_PEF) $(LF_LANPLUS) $(LIBS_EX) del isensor.obj ievents.obj ipmi_sample.obj ifruset.obj: ifruset.c $(CC) /c $(CFLAGS_SAM) ifruset.c ifruset.exe: $(SAMP_LIB) ifruset.obj ifru_picmg.obj $(LINK) $(LFLAGS) /OUT:ifruset.exe ifruset.obj ifru_picmg.obj $(SAMP_LIB) $(LIBS_PEF) $(LF_LANPLUS) $(LIBS_EX) ipmi_sample_evt.obj: ipmi_sample_evt.c $(HEADER) $(CC) /c $(CFLAGS_SAM) ipmi_sample_evt.c isensor2.obj: isensor.c isensor.h $(HEADER) $(CC) /c /Foisensor2.obj $(CFLAGS_SAM) isensor.c ievents2.obj: ievents.c ievents.h $(HEADER) $(CC) /c /Foievents2.obj $(CFLAGS_SAM) /DSENSORS_OK ievents.c ipmi_sample_evt.exe: $(SAMP_LIB) ipmi_sample_evt.obj ievents2.obj isensor2.obj $(LINK) $(LFLAGS) $(LF_LANPLUS) /OUT:ipmi_sample_evt.exe ipmi_sample_evt.obj ievents2.obj isensor2.obj $(SAMP_LIB) $(LIBS_PEF) $(LIBS_EX) ipmiutil-3.1.5/util/oem_supermicro.c0000644000076400007640000007324613566765324017643 0ustar mgportalloggers/* * oem_supermicro.c * Handle SuperMicro OEM command functions * * Change history: * 12/06/2010 ARCress - included in source tree * *--------------------------------------------------------------------- */ /*M* Copyright (c) 2010 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 Kontron 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*/ #ifdef WIN32 #include #include "getopt.h" #else #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #include #else #include #endif #endif #include #include #include #include #include "ipmicmd.h" #include "ievents.h" #include "isensor.h" #include "oem_supermicro.h" #ifdef MOVED /*moved to oem_supermicro.h*/ #define SUPER_NETFN_OEM 0x30 #define SUPER_CMD_BMCSTATUS 0x70 #define SUPER_CMD_RESET_INTRUSION 0x03 #define SUPER_NETFN_OEMFW 0x3C #define SUPER_CMD_OEMFWINFO 0x20 #endif void set_loglevel(int level); /*prototype */ extern char fsm_debug; /*mem_if.c*/ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil smcoem"; #else static char * progver = "3.08"; static char * progname = "ismcoem"; #endif static int verbose = 0; static char fdebug = 0; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static int vend_id = 0; static int prod_id = 0; int oem_supermicro_get_bmc_status(uchar *sts) { int rv; int rlen, ilen; uchar rdata[16]; uchar idata[16]; uchar cc; if (sts == NULL) return(LAN_ERR_INVPARAM); if ((vend_id == VENDOR_SUPERMICROX) || (vend_id == VENDOR_SUPERMICRO)) { /* subfunc 0xF0 is invalid for newer SMC systems */ idata[0] = 0x02; /* action: get status */ ilen = 1; } else { idata[0] = 0xF0; /* subfunction */ idata[1] = 0x02; /* action: get status */ // idata[2] = 0; ilen = 2; } rlen = sizeof(rdata); rv = ipmi_cmdraw(SUPER_CMD_BMCSTATUS, SUPER_NETFN_OEM, BMC_SA, PUBLIC_BUS, BMC_LUN, idata, ilen, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; if (rv == 0) { *sts = rdata[0]; } return(rv); } /* * oem_supermicro_get_bmc_services_status * * Request * 0x30 - OEM network function * 0x70 - OEM cmd * 0xF0 - subcommand * 0x?? - action 00=disable, 01=enable, 02=status * * Response * 0x?? - if action=status: 00=disabled, 01=enabled */ int oem_supermicro_set_bmc_status(uchar sts) { int rv; int rlen, ilen; uchar rdata[16]; uchar idata[16]; uchar cc; if (sts > 1) sts = 1; /* actions: 0=disable, 1=enable, 2=status*/ if ((vend_id == VENDOR_SUPERMICROX) || (vend_id == VENDOR_SUPERMICRO)) { idata[0] = sts; ilen = 1; } else { idata[0] = 0xF0; /* subfunction */ idata[1] = sts; ilen = 2; } rlen = sizeof(rdata); rv = ipmi_cmdraw(SUPER_CMD_BMCSTATUS, SUPER_NETFN_OEM, BMC_SA, PUBLIC_BUS, BMC_LUN, idata, ilen, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; return(rv); } /* oem_supermicro_psstatus1(uchar psnum, uchar *val) */ int oem_supermicro_psstatus1(uchar psnum, uchar *val) { int rv; int rlen; uchar idata[16]; uchar rdata[16]; uchar cc; idata[0] = 0x07; /*busid*/ if (psnum <= 1) idata[1] = 0x70; /* PS 1 */ else if (psnum == 2) idata[1] = 0x72; /* PS 2 */ else /*if (psnum == 3)*/ idata[1] = 0x74; /* PS 3 */ idata[2] = 0x01; /* return one byte of PS status data */ idata[3] = 0x0C; rlen = sizeof(rdata); rv = ipmi_cmd(MASTER_WRITE_READ, idata, 4, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; if (rv == 0) { *val = rdata[0]; } return(rv); } /* oem_supermicro_psstatus2(uchar psnum, uchar *val) Get PMBus Power Supply Status, for X10 motherboards */ int oem_supermicro_psstatus2(uchar psnum, uchar *val) { int rv; int rlen; uchar idata[16]; uchar rdata[16]; uchar cc; idata[0] = 0x07; /*busid*/ if (psnum <= 1) idata[1] = 0x78; /* PS 1 */ else if (psnum == 2) idata[1] = 0x7A; /* PS 2 */ else /*if (psnum == 3)*/ idata[1] = 0x7C; /* PS 3 */ idata[2] = 0x01; /* return one byte of PS status data */ idata[3] = 0x78; rlen = sizeof(rdata); rv = ipmi_cmd(MASTER_WRITE_READ, idata, 4, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; if (rv == 0) { *val = rdata[0]; } return(rv); } /* oem_supermicro_psstatus3(uchar psnum, uchar *val) Get PMBus Power Supply Status, for X10 motherboards raw 0x06 0x52 0x07 0xb0 0x01 0x0c for power supply 1 raw 0x06 0x52 0x07 0xb2 0x01 0x0c for power supply 2 */ int oem_supermicro_psstatus3(uchar psnum, uchar *val) { int rv; int rlen; uchar idata[16]; uchar rdata[16]; uchar cc; idata[0] = 0x07; /*busid*/ if (psnum <= 1) idata[1] = 0xB0; /* PS 1 */ else if (psnum == 2) idata[1] = 0xB2; /* PS 2 */ else /*if (psnum == 3)*/ idata[1] = 0xB4; /* PS 3 */ idata[2] = 0x01; /* return one byte of PS status data */ idata[3] = 0x0C; rlen = sizeof(rdata); rv = ipmi_cmd(MASTER_WRITE_READ, idata, 4, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; if (rv == 0) { *val = rdata[0]; } return(rv); } int oem_supermicro_get_lan_port(uchar *val) { int rv; int rlen, ilen; uchar rdata[16]; uchar idata[16]; uchar cc; idata[0] = 0x0c; /* subfunction */ idata[1] = 0x00; /* get */ ilen = 2; rlen = sizeof(rdata); rv = ipmi_cmdraw(SUPER_CMD_BMCSTATUS, SUPER_NETFN_OEM, BMC_SA, PUBLIC_BUS, BMC_LUN, idata, ilen, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; if (rv == 0) { *val = rdata[0]; } return(rv); } int oem_supermicro_set_lan_port(uchar val) { int rv; int rlen, ilen; uchar rdata[16]; uchar idata[16]; uchar cc; idata[0] = 0x0c; /* subfunction */ idata[1] = 0x01; /* set */ idata[2] = val; ilen = 3; rlen = sizeof(rdata); rv = ipmi_cmdraw(SUPER_CMD_BMCSTATUS, SUPER_NETFN_OEM, BMC_SA, PUBLIC_BUS, BMC_LUN, idata, ilen, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; return(rv); } char *oem_supermicro_lan_port_string(uchar val) { char *p; switch(val) { case 0: p = "Dedicated"; break; case 1: p = "Onboard_LAN1"; break; case 2: p = "Failover"; break; default: p = "unknown"; break; } return(p); } static void oem_supermicro_show_lan_port(uchar val) { printf("Current LAN interface is %s\n", oem_supermicro_lan_port_string(val)); } int oem_supermicro_get_health(char *pstr, int sz) { int rv; uchar bsts; char *str; rv = oem_supermicro_get_bmc_status(&bsts); if (rv == 0) { if (bsts == 0x01) str = "BMC status = enabled"; else str = "BMC status = disabled"; strncpy(pstr, str, sz); } return(rv); } /* * oem_supermicro_get_firmware_info * * From post by ipmitool developer. * http://sourceforge.net/mailarchive/message.php?msg_name=49ABCCC3.4040004%40cern.ch * * Request * 0x3C - OEM network function * 0x20 - OEM cmd (SUPER_CMD_OEMFWINFO) * * Response data: * 4 bytes - firmware major version (LSB first) * 4 bytes - firmware minor version (LSB first) * 4 bytes - firmware sub version (LSB first) * 4 bytes - firmware build number (LSB first) * 1 byte - hardware ID * ? bytes - firmware tag, null terminated string */ int oem_supermicro_get_firmware_info(uchar *info) { int rv; int rlen; uchar rdata[32]; uchar idata[16]; uchar cc; if (info == NULL) return(LAN_ERR_INVPARAM); rlen = sizeof(rdata); rv = ipmi_cmdraw(SUPER_CMD_OEMFWINFO, SUPER_NETFN_OEM, BMC_SA, PUBLIC_BUS, BMC_LUN, idata, 0, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; if (rv == 0) { memcpy(info,rdata,rlen); } return(rv); } int oem_supermicro_get_firmware_str(char *pstr, int sz) { int rv; uchar info[32]; uint32 fwmaj; uint32 fwmin; uint32 fwsub; uint32 fwbld; uchar hwid; rv = oem_supermicro_get_firmware_info(info); if (rv == 0) { fwmaj = info[0] + (info[1] << 8) + (info[2] << 16) + (info[3] << 24); fwmin = info[4] + (info[5] << 8) + (info[6] << 16) + (info[7] << 24); fwsub = info[8] + (info[9] << 8) + (info[10] << 16) + (info[11] << 24); fwbld = info[12] +(info[13] << 8) + (info[14] << 16) + (info[15] << 24); hwid = info[16]; /*info[17] = fw tag string */ snprintf(pstr,sz,"Firmware %d.%d.%d.%d HW %d %s\n",fwmaj,fwmin,fwsub, fwbld,hwid,&info[17]); } return(rv); } int oem_supermicro_reset_intrusion(void) { int rv; int rlen; uchar rdata[32]; uchar idata[16]; uchar cc; // if (state == NULL) return(LAN_ERR_INVPARAM); rlen = sizeof(rdata); rv = ipmi_cmdraw(SUPER_CMD_RESET_INTRUSION, SUPER_NETFN_OEM, BMC_SA, PUBLIC_BUS, BMC_LUN, idata, 0, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; if (rv == 0) { /* check rdata for more info */ } return(rv); } /* decode_threshold_supermicro() assumes Fans, not Temp * Temp thresholds are different order. */ int decode_threshold_supermicro(uchar rval, uchar *thresh) { int idx = 0; uchar bits; bits = thresh[0]; if (bits & 0x20) { /*hi-unrec*/ if (rval >= thresh[6]) { idx = 6; return(idx); } } if (bits & 0x10) { /*hi-crit*/ if (rval >= thresh[5]) { idx = 5; return(idx); } } if (bits & 0x08) { /*hi-noncr*/ if (rval >= thresh[4]) { idx = 4; return(idx); } } if (bits & 0x01) { /*lo-noncr*/ if (rval <= thresh[1]) { idx = 1; } } if (bits & 0x02) { /*lo-crit*/ if (rval <= thresh[2]) { idx = 2; } } if (bits & 0x04) { /*lo-unrec*/ if (rval <= thresh[3]) { idx = 3; } } return(idx); } /* * decode_sensor_supermicro * inputs: * sdr = the SDR buffer * reading = the 3 or 4 bytes of data from GetSensorReading * pstring = points to the output string buffer * slen = size of the output buffer * outputs: * rv = 0 if this sensor was successfully interpreted here, * non-zero otherwise, to use default interpretations. * pstring = contains the sensor reading interpretation string (if rv==0) */ int decode_sensor_supermicro(uchar *sdr,uchar *reading,char *pstring, int slen, int fsimple, char fdbg) { int i, rv = -1; uchar stype, etype, snum; uchar bval; char *pstr = NULL; uchar thresh[7]; SDR01REC *sdr01; char *typestr = NULL; double val; if (sdr == NULL || reading == NULL) return(rv); if (pstring == NULL || slen == 0) return(rv); fdebug = fdbg; bval = (reading[2] & 0x3f); snum = sdr[7]; /*sdr01->sens_num*/ stype = sdr[12]; /*sensor_type*/ etype = sdr[13]; /*sdr01->ev_type*/ get_mfgid(&vend_id,&prod_id); /*saved from ipmi_getdeviceid */ /* sdr[3] rec_type is 0x01 for Full, 0x02 for Compact */ if ((sdr[3] == 0x01) && (etype == 0x01)) { /* full threshold sensor */ /*if Temp sensor, bits==0 would show BelowCrit, so handle normally */ if ((stype == 0x01) && (bval == 0)) return(-1); /*Cannot rely upon the sensor reading[2], so get thresholds and compare*/ rv = GetSensorThresholds(snum,&thresh[0]); if (rv != 0) return(rv); i = decode_threshold_supermicro(reading[0],thresh); if (fdebug) printf("decode_sensor_supermicro: snum=%x stype=%x rdg=%x:%x thresh=%x:%x:%x:%x:%x:%x:%x i=%d rv=%d\n", snum,stype,reading[0],reading[2], thresh[0], thresh[1], thresh[2], thresh[3], thresh[4], thresh[5], thresh[6], i,rv); switch(i) { case 0: pstr = "OK"; break; case 1: pstr = "Warn-lo"; break; case 2: pstr = "Crit-lo"; break; case 3: pstr = "BelowCrit"; break; case 4: pstr = "Warn-hi"; break; case 5: pstr = "Crit-hi"; break; case 6: pstr = "AboveCrit"; break; default: pstr = "OK*"; break; } sdr01 = (SDR01REC *)sdr; val = RawToFloat(reading[0],sdr); typestr = get_unit_type(sdr01->sens_units,sdr01->sens_base,sdr01->sens_mod, 0); if (fsimple) snprintf(pstring, slen, "%s | %.2f %s",pstr,val,typestr); else snprintf(pstring, slen, "%s %.2f %s",pstr,val,typestr); return(rv); } switch(stype) { case 0xC0: /* CPU Temp Sensor, EvTyp=0x70 (Full) */ //if (dbg) printf("supermicro %x sensor reading %x\n",stype,reading); rv = 0; switch(bval) { case 0x0000: pstr = "Low"; break; case 0x0001: pstr = "Medium"; break; case 0x0002: pstr = "High"; break; case 0x0004: pstr = "Overheat"; break; case 0x0007: pstr = "Not Installed"; break; default: rv = -1; break; } break; case 0x08: /* Power Supply Status (Full/Discrete) Table 42-3 */ rv = 0; switch(bval) { case 0x00: pstr = "Absent"; break; /*bit 0*/ case 0x01: pstr = "Present"; break; /*bit 0*/ case 0x02: pstr = "Failure"; break; /*bit 1*/ case 0x04: pstr = "Predict Fail"; break; /*bit 2*/ case 0x08: pstr = "Input Lost"; break; /*bit 3*/ default: rv = -1; break; } break; case 0x0D: /* HDD Status (Full/Discrete) Table 42-3 */ rv = 0; switch(bval) { case 0x00: pstr = "Absent"; break; /*bit 0*/ case 0x01: pstr = "Present"; break; /*bit 0*/ case 0x02: pstr = "Failure"; break; /*bit 1*/ case 0x04: pstr = "Predict Fail"; break; /*bit 2*/ default: rv = -1; break; } break; case 0x29: /* VBAT sensor */ if (prod_id == 0x0917) { /*X11DRi has inert VBAT full sensor*/ if (bval == 0) { pstr = "NotAvailable"; rv = 0; } } break; default: break; } if (rv == 0) strncpy(pstring, pstr, slen); return(rv); } extern int get_MemDesc(int array, int dimm, char *desc, int *psz); /*mem_if.c*/ #define NPAIRS 26 char rgpair[NPAIRS] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int decode_mem_supermicro(int prod, uchar b2, uchar b3, char *desc, int *psz) { int cpu, pair, dimm, n; int rv = 0; int ver = 0; uchar bdata; if ((desc == NULL) || (psz == NULL)) return -1; if (b2 == 0xff) { ver = 1; bdata = b3; } /*ff is reserved*/ else { ver = 2; bdata = b2; } /* normal case */ #ifdef SMC_OLD /* normal method for other vendors */ cpu = (bdata & 0xc0) >> 6; dimm = bdata & 0x3f; /* SuperMicro advertised method (wrong) */ /* bdata = 0x10 (16.) means CPU 1, DIMM 6 */ cpu = bdata / 10; dimm = bdata % 10; #endif /* ver 0 previous SuperMicro firmware returned all zeros here. * Memory #00 Correctable ECC, 6f [00 00 00] * ver 1 returns data3 with some info (X9) * ver 2 returns data2 with some info (X9,X10) * There have been bugs in these SuperMicro events, but this * has been derived from test data by comparing BIOS data. */ if (ver == 0) { cpu = (bdata & 0xc0) >> 6; dimm =bdata & 0x3f; pair = 0; n = sprintf(desc,"CPU%d/DIMM%d",cpu,dimm); } else if (ver == 1) { cpu = 1; if (bdata > 0x80) cpu = 2; pair = (bdata & 0x70) >> 4; if (pair > NPAIRS) pair = NPAIRS - 1; dimm = (bdata & 0x07) + 1; /*convert to 1-based*/ n = sprintf(desc,"P%d_DIMM%c%d",cpu,rgpair[pair],dimm); } else { /* ver 2 method: 2A 80 = P1_DIMMB1 */ /* SuperMicro says: * pair: %c (data2 >> 4) + 0x40 + (data3 & 0x3) * 3, (='B') * dimm: %c (data2 & 0xf) + 0x27, * cpu: %x (data3 & 0x03) + 1); */ cpu = (b3 & 0x0F) + 1; /*0x80=CPU1, 0x81=CPU2*/ pair = ((bdata & 0xF0) >> 4) - 1; /*0x10=pairA, 0x20=pairB*/ if (pair < 0) pair = 0; if (pair > NPAIRS) pair = NPAIRS - 1; dimm = (bdata & 0x0F) - 9; /*0x0A=dimmX1, 0x0B=dimmX2*/ if (dimm < 0) n = sprintf(desc,DIMM_UNKNOWN); /* invalid */ else n = sprintf(desc,"P%d_DIMM%c%d",cpu,rgpair[pair],dimm); } /* Use DMI if we get confirmation about cpu/dimm indices. */ if (! is_remote()) { fsm_debug = fdebug; rv = get_MemDesc(cpu,dimm,desc,psz); /* if (rv != 0) desc has "DIMM[%d}" */ } if ((bdata == 0xFF) || (rv != 0)) n = sprintf(desc,DIMM_UNKNOWN); if (fdebug) printf("decode_mem_supermicro: v%d bdata=%02x(%d) cpu=%d dimm=%d pair=%d\n",ver,bdata,bdata,cpu,dimm,pair); *psz = n; rv = 0; return(rv); } /*end decode_mem_supermicro*/ /* * decode_sel_supermicro * inputs: * evt = the 16-byte IPMI SEL event * outbuf = points to the output string buffer * outsz = size of the output buffer * outputs: * rv = 0 if this event was successfully interpreted here, * non-zero otherwise, to use default interpretations. * outbuf = will contain the interpreted event text string (if rv==0) * See also decode_mem_supermicro above */ int decode_sel_supermicro(uchar *evt, char *outbuf, int outsz, char fdesc, char fdbg) { int rv = -1; ushort id; uchar rectype; ulong timestamp; char mybuf[64]; char mytype[64]; char *type_str = ""; char *pstr = NULL; int sevid, d1; ushort genid; uchar snum; uchar data1, data2, data3; char *psens = NULL; fdebug = fdbg; sevid = SEV_INFO; id = evt[0] + (evt[1] << 8); rectype = evt[2]; snum = evt[11]; timestamp = evt[3] + (evt[4] << 8) + (evt[5] << 16) + (evt[6] << 24); genid = evt[7] | (evt[8] << 8); data1 = evt[13]; data2 = evt[14]; data3 = evt[15]; if (rectype == 0x02) { sprintf(mybuf,"%02x [%02x %02x %02x]", evt[12],evt[13],evt[14],evt[15]); switch(evt[10]) { /*sensor type*/ case 0xC0: /* CPU Temp Sensor */ type_str = "OEM_CpuTemp"; d1 = (evt[13] & 0x0f); /*offset/data1 l.o. nibble*/ switch(d1) { case 0x02: /* CPU Temp Sensor Overheat event offset */ if (evt[12] & 0x80) { /*EvTyp==0xF0 if deassert*/ pstr = "CpuTemp Overheat OK"; sevid = SEV_INFO; } else { /* EvTyp=0x70 assert */ pstr = "CpuTemp Overheat "; sevid = SEV_MAJ; } break; default: pstr = "CpuTemp Event"; sprintf(mytype,"CpuTemp_%02x", d1); type_str = mytype; sevid = SEV_MIN; break; } rv = 0; break; case 0xC2: /* CPLD Event */ type_str = "OEM_CPLD"; switch((evt[13] & 0x0f)) { /* data1 usu 0xa0*/ case 0x00: if (evt[14] == 0x1c) { pstr = "CPLD CATERR Asserted"; sevid = SEV_CRIT; } else { pstr = "CPLD Event Asserted"; sevid = SEV_MIN; } break; default: pstr = "CPLD Event"; sevid = SEV_MIN; break; } rv = 0; break; case 0xD0: /* BMC Event */ type_str = "OEM_BMC"; pstr = "BMC unknown event"; sevid = SEV_CRIT; if (data1 == 0x80 && data3 == 0xFF) { switch(data2) { case 0x00: pstr = "BMC unexpected reset"; break; case 0x01: pstr = "BMC cold reset"; break; case 0x02: pstr = "BMC warm reset"; break; } } rv = 0; break; case 0xC5: /* Observed Event: Storage, drive slot */ /* usually OEM(c5) #52 - 6f [01 00 00] */ type_str = "OEM_C5"; pstr = "Storage/DriveSlot fault"; sevid = SEV_MAJ; rv = 0; break; case 0xC8: /* Observed Event: AC Power on event */ /* usually OEM(c8) #ff - 6f [a0 ff ff] */ type_str = "OEM_C8"; pstr = "AC Power On"; sevid = SEV_MAJ; rv = 0; break; default: /*other sensor types*/ break; } } if (rv == 0) { format_event(id,timestamp, sevid, genid, type_str, snum,psens,pstr,mybuf,outbuf,outsz); } return(rv); } /* factory_defaults: set SMC factory defaults * mode: 0 = detect, default is c0 41 method * 2 = use c0 41 method, also get guid * 3 = use f0 40 method (usu X11) */ static int factory_defaults(int mode) { int rv = -1; int rlen; uchar rdata[32]; uchar idata[16]; uchar cc; /* From SMC IPMICFG -fde factory defaults session: start_kcs_transaction - 18 01 (get_device_id) start_kcs_transaction - 18 25 (watchdog get) start_kcs_transaction - b0 00 00 (unknown, invalid) start_kcs_transaction - 18 01 (get_device_id) start_kcs_transaction - 18 37 (get_system_guid) start_kcs_transaction - 18 01 (get_device_id) start_kcs_transaction - c0 41 (reset_factory_defaults, -fde) */ if ((prod_id > 2200) && (prod_id < 2300) && (mode == 0)) { /* Looks like X11 board, may use netfn 3c, cmd 40 ? */ /* do not auto-set this if mode param is not 3 */ // mode = 3; /* cmd=0x40 netfn=0x3c (netfn/lun=0xF0) */ if (fdebug) printf("may also need ipmiutil cmd 00 20 f0 40\n"); } /* b0 00 00: cmd=00 netfn=2C */ rlen = sizeof(rdata); idata[0] = 0x00; rv = ipmi_cmdraw(0x00, (0xb0 >> 2), BMC_SA, PUBLIC_BUS, BMC_LUN, idata, 1, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; if (fdebug) printf("b0 00 returned %d\n",rv); /* if (rv != 0) return(rv); */ if (mode == 2) { /* (get_system_guid) */ rlen = sizeof(rdata); rv = ipmi_cmdraw(0x37, (0x18 >> 2), BMC_SA, PUBLIC_BUS, BMC_LUN, idata, 0, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; if (fdebug) printf("get_guid returned %d\n",rv); if (rv != 0) return(rv); } /* reset factory defaults */ rlen = sizeof(rdata); if (mode == 3) { /* cmd=0x40 netfn=0x3c (netfn/lun=0xF0) */ rv = ipmi_cmdraw(0x40, 0x3c, BMC_SA, PUBLIC_BUS, BMC_LUN, idata, 0, rdata, &rlen, &cc, fdebug); } else { /* cmd=0x41 netfn=0x30 (netfn/lun=0xC0) if X10 or less */ rv = ipmi_cmdraw(0x41, (0xc0 >> 2), BMC_SA, PUBLIC_BUS, BMC_LUN, idata, 0, rdata, &rlen, &cc, fdebug); } if ((rv == 0) && (cc != 0)) rv = cc; if (fdebug) printf("factory default reset returned %d\n",rv); if (rv != 0) return(rv); return(rv); } static void usage(void) { printf("Usage: %s [arg]\n",progname); printf(" intrusion = reset chassis intrusion\n"); printf(" bmcstatus [enable| disable] = get/set BMC status\n"); printf(" firmware = get extra firmware info\n"); printf(" factory = reset to factory defaults\n"); printf(" lanport [dedicated| lan1| failover] = get/set IPMI LAN port\n"); printf(" powersupply = get PMBus PowerSupply status\n"); printf("These commands may not work on all SuperMicro systems\n"); } static int ipmi_smcoem_main(int argc, char **argv) { int n,rv = 0; char msg[80]; uchar val; if ((vend_id != VENDOR_SUPERMICRO) && (vend_id != VENDOR_SUPERMICROX)) { printf("Not SuperMicro firmware, ignoring smcoem\n"); usage(); return(ERR_USAGE); } if (strncmp(argv[0],"intrusion",9) == 0) { printf("Clearing Chassis Intrusion ...\n"); rv = oem_supermicro_reset_intrusion(); } else if (strncmp(argv[0],"bmcstatus",9) == 0) { printf("Getting BMC status ...\n"); rv = oem_supermicro_get_health(msg, sizeof(msg)); if (rv != 0) return(rv); printf("%s\n",msg); if (argv[1] != NULL) { if (strncmp(argv[1],"disable",7) == 0) { val = 0; } else if (strncmp(argv[1],"enable",6) == 0) { val = 1; } else { usage(); return(ERR_USAGE); } printf("Setting BMC status to %s ...\n",argv[1]); rv = oem_supermicro_set_bmc_status(val); if (rv != 0) return(rv); rv = oem_supermicro_get_health(msg, sizeof(msg)); if (rv == 0) printf("%s\n",msg); } } else if (strncmp(argv[0],"firmware",8) == 0) { printf("Getting SMC Firmare Information ...\n"); rv = oem_supermicro_get_firmware_str(msg, sizeof(msg)); if (rv == 0) printf("%s\n",msg); } else if (strncmp(argv[0],"factory",7) == 0) { rv = factory_defaults(0); if (rv == 0) printf("Reset firmware to factory defaults\n"); else printf("Error %d resetting firmware to factory defaults\n",rv); } else if (strncmp(argv[0],"lanport",7) == 0) { rv = oem_supermicro_get_lan_port(&val); if (rv == 0) { oem_supermicro_show_lan_port(val); if (argv[1] != NULL) { if (strncmp(argv[1],"dedicated",9) == 0) { val = 0; } else if (strncmp(argv[1],"lan1",4) == 0) { val = 1; } else if (strncmp(argv[1],"failover",8) == 0) { val = 2; } else { usage(); return(ERR_USAGE); } printf("Setting LAN interface to %s ...\n",argv[1]); rv = oem_supermicro_set_lan_port(val); if (rv != 0) return(rv); rv = oem_supermicro_get_lan_port(&val); if (rv == 0) oem_supermicro_show_lan_port(val); } } } else if (strncmp(argv[0],"powersupply",11) == 0) { if (argv[1] == NULL) { usage(); rv = ERR_USAGE; } else { char DevRec[16]; int xver = 9; n = atoi(argv[1]); /* power supply number */ rv = ipmi_getdeviceid( DevRec, sizeof(DevRec),fdebug); if (rv == 0) { int vend_id, prod_id; /* 1562 (0x061A) = X8SIU */ /* 1572 (0x0624) = X9SCM */ /* 1797 (0x0705) = X9DR7 */ /* 2137 (0x0859) = X10DRH */ vend_id = DevRec[6] + (DevRec[7] << 8) + (DevRec[8] << 16); prod_id = DevRec[9] + (DevRec[10] << 8); if (prod_id > 0x0800) xver = 10; else if (prod_id > 1570) xver = 9; else xver = 8; } if (xver == 10) rv = oem_supermicro_psstatus3(n, &val); else if (xver == 9) rv = oem_supermicro_psstatus2(n, &val); else /*xver==8*/ rv = oem_supermicro_psstatus1(n, &val); if (rv == 0) { if (val == 0x00) strcpy(msg,"good"); else if (val == 0x02) strcpy(msg,"ok"); else sprintf(msg,"bad 0x%02x",val); printf("X%d Power Supply %d status = %d (%s)\n",xver,n,val,msg); } else { printf("X%d Power Supply %d error = %d\n",xver,n,rv); } } } else { usage(); rv = ERR_USAGE; } return(rv); } #ifdef METACOMMAND int i_smcoem(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int rv = 0; uchar devrec[16]; int c, i; char *s1; printf("%s ver %s\n", progname,progver); set_loglevel(LOG_NOTICE); parse_lan_options('V',"4",0); /*default to admin priv*/ while ( (c = getopt( argc, argv,"m:xzEF:J:N:P:R:T:U:V:YZ:?")) != EOF ) switch(c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'x': fdebug = 2; /* normal (dbglog if isol) */ verbose = 1; break; case 'z': fdebug = 3; /*full debug (for isol)*/ verbose = 1; break; case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: usage(); return(ERR_USAGE); break; } for (i = 0; i < optind; i++) { argv++; argc--; } if (argc == 0) { usage(); return(ERR_USAGE); } rv = ipmi_getdeviceid(devrec,16,fdebug); if (rv == 0) { char ipmi_maj, ipmi_min; ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16); prod_id = devrec[9] + (devrec[10] << 8); show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); } rv = ipmi_smcoem_main(argc, argv); ipmi_close_(); return(rv); } /* end oem_supermicro.c */ ipmiutil-3.1.5/util/oem_dell.c0000644000076400007640000055642713566765324016402 0ustar mgportalloggers/* * oem_dell.c * Handle Dell OEM command functions * * Change history: * 08/17/2011 ARCress - included in ipmiutil source tree * */ /****************************************************************** Copyright (c) 2008, Dell 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: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 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. - Neither the name of Dell Inc 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. ******************************************************************/ /* * Thursday Oct 7 17:30:12 2009 * * * This code implements a dell OEM proprietary commands. * This Code is edited and Implemented the License feature for Delloem * Author Harsha S */ #include #include #include #ifdef WIN32 #include #define int8_t char #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int #define uint64_t unsigned long #include "getopt.h" #else #include #include #include #include #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #include #else #include #endif #endif #include #include "ipmicmd.h" #include "isensor.h" #include "ievents.h" #include "oem_dell.h" // #ifdef METACOMMAND is assumed extern int i_sol(int argc, char **argv); /*isol.c*/ extern void lprintf(int level, const char * format, ...); /*ipmilanplus.c*/ extern void set_loglevel(int level); extern void printbuf(const uint8_t * buf, int len, const char * desc); #define IPMI_DELL_OEM_NETFN (uint8_t)(0x30) #define GET_CHASSIS_LED_STATE (uint8_t)(0x32) #define GET_IDRAC_VIRTUAL_MAC (uint8_t)(0xC9) // 11g Support Macros #define INVALID -1 #define SHARED 0 #define SHARED_WITH_FAILOVER_LOM2 1 #define DEDICATED 2 #define SHARED_WITH_FAILOVER_ALL_LOMS 3 char ActiveLOM_String[6][10] = {"None","LOM1","LOM2","LOM3","LOM4","dedicated"}; #define INVAILD_FAILOVER_MODE -2 #define INVAILD_FAILOVER_MODE_SETTINGS -3 #define INVAILD_SHARED_MODE -4 #define INVAILD_FAILOVER_MODE_STRING "ERROR: Cannot set shared with failover lom same as current shared lom.\n" #define INVAILD_FAILOVER_MODE_SET "ERROR: Cannot set shared with failover loms when NIC is set to dedicated Mode.\n" #define INVAILD_SHARED_MODE_SET_STRING "ERROR: Cannot set shared Mode for Blades.\n" // 11g Support Strings for nic selection char NIC_Selection_Mode_String [4] [50] = { "shared", "shared with failover lom2", "dedicated", "shared with Failover all loms" }; // 11g Support Macros (dups) //#define SHARED 0 //#define SHARED_WITH_FAILOVER_LOM2 1 //#define DEDICATED 2 //#define SHARED_WITH_FAILOVER_ALL_LOMS 3 // 12g Support Strings for nic selection char NIC_Selection_Mode_String_12g[] [50] = { "dedicated", "shared with lom1", "shared with lom2", "shared with lom3", "shared with lom4", "shared with failover lom1", "shared with failover lom2", "shared with failover lom3", "shared with failover lom4", "shared with failover all loms" }; #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil delloem"; #else static char * progver = "3.08"; static char * progname = "idelloem"; #endif static int verbose = 0; static char fdebug = 0; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static uchar *sdrcache = NULL; static char *sdrfile = NULL; static int argc_sav; static char **argv_sav; static int current_arg =0; uint8_t iDRAC_FLAG=0; LCD_MODE lcd_mode; static uint8_t LcdSupported=0; static uint8_t SetLEDSupported=0; volatile uint8_t IMC_Type = IMC_IDRAC_10G; const struct vFlashstr vFlash_completion_code_vals[] = { {0x00, "SUCCESS"}, {0x01, "NO_SD_CARD"}, {0x63, "UNKNOWN_ERROR"}, {0x00, NULL} }; POWER_HEADROOM powerheadroom; uint8_t PowercapSetable_flag=0; uint8_t PowercapstatusFlag=0; static void usage(void); /* LCD Function prototypes */ static int ipmi_delloem_lcd_main (void * intf, int argc, char ** argv); static int ipmi_lcd_get_platform_model_name (void * intf,char* lcdstring, uint8_t max_length,uint8_t field_type); static int ipmi_idracvalidator_command (void * intf); static int ipmi_lcd_get_configure_command_wh (void * intf); static int ipmi_lcd_get_configure_command (void * intf,uint8_t *command); static int ipmi_lcd_set_configure_command (void * intf, int command); static int ipmi_lcd_set_configure_command_wh (void * intf, uint32_t mode, uint16_t lcdqualifier,uint8_t errordisp); static int ipmi_lcd_get_single_line_text (void * intf, char* lcdstring, uint8_t max_length); static int ipmi_lcd_get_info_wh(void * intf); static int ipmi_lcd_get_info(void * intf); static int ipmi_lcd_get_status_val(void * intf, LCD_STATUS* lcdstatus); static int IsLCDSupported (); static void CheckLCDSupport(void * intf); static void ipmi_lcd_status_print( LCD_STATUS lcdstatus); static int ipmi_lcd_get_status(void * intf ); static int ipmi_lcd_set_kvm(void * intf, char status); static int ipmi_lcd_set_lock(void * intf, char lock); static int ipmi_lcd_set_single_line_text (void * intf, char * text); static int ipmi_lcd_set_text(void * intf, char * text, int line_number); static int ipmi_lcd_configure_wh (void * intf, uint32_t mode , uint16_t lcdqualifier, uint8_t errordisp, int8_t line_number, char * text); static int ipmi_lcd_configure (void * intf, int command, int8_t line_number, char * text); static void ipmi_lcd_usage(void); /* MAC Function prototypes */ static int ipmi_delloem_mac_main (void * intf, int argc, char ** argv); static int make_int(const char *str, int *value); static void InitEmbeddedNICMacAddressValues (); static int ipmi_macinfo_drac_idrac_virtual_mac(void* intf,uint8_t NicNum); static int ipmi_macinfo_drac_idrac_mac(void* intf,uint8_t NicNum); static int ipmi_macinfo_10g (void* intf, uint8_t NicNum); static int ipmi_macinfo_11g (void* intf, uint8_t NicNum); static int ipmi_macinfo (void* intf, uint8_t NicNum); static void ipmi_mac_usage(void); /* LAN Function prototypes */ static int ipmi_delloem_lan_main (void * intf, int argc, char ** argv); static int IsLANSupported (); static int get_nic_selection_mode (int current_arg, char ** argv); static int ipmi_lan_set_nic_selection (void* intf, uint8_t nic_selection); static int ipmi_lan_get_nic_selection (void* intf); static int get_nic_selection_mode_12g (void* intf,int iarg, char **argv, char *nic_set); static int ipmi_lan_get_active_nic (void* intf); static void ipmi_lan_usage(void); static int ipmi_lan_set_nic_selection_12g (void* intf, uint8_t* nic_selection); /* POwer monitor Function prototypes */ static int ipmi_delloem_powermonitor_main (void * intf, int argc, char **argv); static void ipmi_time_to_str(time_t rawTime, char* strTime); static int ipmi_get_power_capstatus_command (void * intf); static int ipmi_set_power_capstatus_command (void * intf,uint8_t val); static int ipmi_powermgmt(void* intf); static int ipmi_powermgmt_clear(void* intf,uint8_t clearValue); static uint64_t watt_to_btuphr_conversion(uint32_t powerinwatt); static uint32_t btuphr_to_watt_conversion(uint64_t powerinbtuphr); static int ipmi_get_power_headroom_command (void * intf,uint8_t unit); static int ipmi_get_power_consumption_data(void* intf,uint8_t unit); static int ipmi_get_instan_power_consmpt_data(void* intf, IPMI_INST_POWER_CONSUMPTION_DATA* instpowerconsumptiondata); static void ipmi_print_get_instan_power_Amps_data(IPMI_INST_POWER_CONSUMPTION_DATA instpowerconsumptiondata); static int ipmi_print_get_power_consmpt_data(void* intf,uint8_t unit); static int ipmi_get_avgpower_consmpt_history(void* intf,IPMI_AVGPOWER_CONSUMP_HISTORY* pavgpower ); static int ipmi_get_peakpower_consmpt_history(void* intf,IPMI_POWER_CONSUMP_HISTORY * pstPeakpower); static int ipmi_get_minpower_consmpt_history(void* intf,IPMI_POWER_CONSUMP_HISTORY * pstMinpower); static int ipmi_print_power_consmpt_history(void* intf,int unit ); static int ipmi_get_power_cap(void* intf,IPMI_POWER_CAP* ipmipowercap ); static int ipmi_print_power_cap(void* intf,uint8_t unit ); static int ipmi_set_power_cap(void* intf,int unit,int val ); static void ipmi_powermonitor_usage(void); /* vFlash Function prototypes */ static int ipmi_delloem_vFlash_main(void * intf, int argc, char ** argv); const char * get_vFlash_compcode_str(uint8_t vflashcompcode, const struct vFlashstr *vs); static int ipmi_get_sd_card_info(void* intf); static int ipmi_delloem_vFlash_process(void* intf, int current_arg, char ** argv); static void ipmi_vFlash_usage(void); /* windbg Function prototypes */ volatile uint8_t windbgsession = 0; static int ipmi_delloem_windbg_main (void * intf, int argc, char ** argv); static int ipmi_windbg_start (void * intf); static int ipmi_windbg_end (void * intf); static void ipmi_windbg_usage (void); /* LED Function prototypes */ static int ipmi_getsesmask(int, char **); static int CheckSetLEDSupport(void * intf); static int IsSetLEDSupported(void); static void ipmi_setled_usage(void); static int ipmi_delloem_setled_main(void *intf, int argc, char ** argv); static int ipmi_delloem_getled_main(void *intf, int argc, char ** argv); static int ipmi_setled_state (void * intf, int bayId, int slotId, int state); static int ipmi_getdrivemap (void * intf, int b, int d, int f, int *bayId, int *slotId); //extern int optind; /*from getopt*/ static int ipmi_sol_activate(void *intf, int j, int k) { char **args; int rv, i, n; int x = 0; n = argc_sav; args = argv_sav; /* use the user-specified args, but switch to sol */ for (i = 0; i < n; i++) { if (strcmp(args[i],"ipmiutil") == 0) { x = 1; } else if (strcmp(args[i],"delloem") == 0) args[i] = "sol"; else if (strcmp(args[i],"windbg") == 0) args[i] = "-a"; else if (strcmp(args[i],"start") == 0) args[i] = "-a"; } ipmi_close_(); if (x == 1) { args++; n--; } optind = 0; rv = i_sol(n, args); return rv; } static int ipmi_sol_deactivate(void *intf) { char **args; int rv, i, n; int x = 0; n = argc_sav; args = argv_sav; /* use the user-specified args, but switch to sol */ for (i = 0; i < n; i++) { if (strcmp(args[i],"ipmiutil") == 0) { x = 1; } else if (strcmp(args[i],"delloem") == 0) args[i] = "sol"; else if (strcmp(args[i],"windbg") == 0) args[i] = "-d"; else if (strcmp(args[i],"end") == 0) args[i] = "-d"; } ipmi_close_(); if (x == 1) { args++; n--; } optind = 0; rv = i_sol(n, args); return rv; } static int sysinfo_param(const char *str) { // SysInfo Parameters // 1 = system firmware version // 2 = system hostname // 3 = primary operating system name (non-volatile) // 4 = operating system name (volatile) // 0xe3 = dell: os version // 0xde = dell: url if (!strcmp(str, "system_name")) return 0x02; if (!strcmp(str, "primary_os_name")) return 0x03; if (!strcmp(str, "os_name")) return 0x04; if (!strcmp(str, "dell_os_version")) return 0xe4; if (!strcmp(str, "dell_url")) return 0xde; return strtoul(str, 0, 16); } static void ipmi_sysinfo_usage() { lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " getsysinfo (os_name|primary_os_name|dell_os_version|dell_url)"); lprintf(LOG_NOTICE, " Retrieves system info from bmc for given argument"); lprintf(LOG_NOTICE, " setsysinfo (os_name|primary_os_name|dell_os_version|dell_url)"); lprintf(LOG_NOTICE, " Stores system Info for given argument to bmc"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " primary_os_name = primary operating system name"); lprintf(LOG_NOTICE, " os_name = secondary operating system name"); lprintf(LOG_NOTICE, " system_name = system hostname of server"); lprintf(LOG_NOTICE, " dell_os_version = running version of operating system (Dell)"); lprintf(LOG_NOTICE, " dell_url = url of bmc webserver (Dell)"); lprintf(LOG_NOTICE, ""); } static int ipmi_delloem_sysinfo_main(void * intf, int argc, char ** argv) { int param, isset; char *str; unsigned char infostr[256], *pos; int j, ret; /* Is this a setsysinfo or getsysinfo */ isset = !strncmp(argv[current_arg], "setsysinfo\0",10); current_arg++; if (argc < current_arg) { usage(); return -1; } if (argc == 1 || strcmp(argv[current_arg], "help") == 0 || argc < (isset ? current_arg+2 : current_arg+1)) { ipmi_sysinfo_usage(); return 0; } memset(infostr, 0, sizeof(infostr)); param = sysinfo_param(argv[current_arg++]); if (isset) { str = argv[current_arg]; j = strlen_(str); ret = set_system_info(param,str,j); } else { pos = infostr; j = sizeof(infostr); ret = get_system_info(param,infostr,&j); printf("%s\n", infostr); } return ret; } static void ipmi_password_policy_usage(void) { lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " passwordpolicy "); lprintf(LOG_NOTICE, " Set the OEM Password Policy Check on or off"); lprintf(LOG_NOTICE, " This parameter is write-only"); lprintf(LOG_NOTICE, ""); } static int ipmi_delloem_password_policy(void * intf, int argc, char ** argv) { int rv = 0; int rsp_len; struct ipmi_rq req; uint8_t data[4]; uint8_t rsp[IPMI_RSPBUF_SIZE]; uint8_t bval; current_arg++; if (argc < current_arg) { usage(); return -1; } if (strcmp(argv[current_arg], "on") == 0) { bval = 0x01; } else if (strcmp(argv[current_arg], "off") == 0) { bval = 0x00; } else { /* other or "help" */ ipmi_password_policy_usage(); return 0; } printf("Setting OEM Password Policy Check to %s ...\n", argv[current_arg]); req.msg.netfn = 0x30; /*Dell OEM netfn*/ req.msg.lun = 0; req.msg.cmd = 0x51; req.msg.data_len = 1; req.msg.data = data; data[0] = bval; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error setting OEM password policy: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); } if (rv == 0) printf("successful\n"); /* This works for DELL C6220 with firmware >= 1.23 */ return(rv); } /***************************************************************** * Function Name: ipmi_delloem_main * * Description: This function processes the delloem command * Input: intf - ipmi interface argc - no of arguments argv - argument string array * Output: * * Return: return code 0 - success * -1 - failure * ******************************************************************/ int ipmi_delloem_main(void * intf, int argc, char ** argv) { int rc = 0; // ipmi_idracvalidator_command(intf); // CheckLCDSupport (intf); // CheckSetLEDSupport (intf); if (argc == 0 || strncmp(argv[0], "help\0", 5) == 0) { usage(); return 0; } if (0 ==strncmp(argv[current_arg], "lcd\0", 4) ) { rc = ipmi_delloem_lcd_main (intf,argc,argv); } /* mac address*/ else if (strncmp(argv[current_arg], "mac\0", 4) == 0) { rc = ipmi_delloem_mac_main (intf,argc,argv); } /* lan address*/ else if (strncmp(argv[current_arg], "lan\0", 4) == 0) { rc = ipmi_delloem_lan_main (intf,argc,argv); } /* SetLED support */ else if (strncmp(argv[current_arg], "setled\0", 7) == 0) { rc = ipmi_delloem_setled_main (intf,argc,argv); } else if (strncmp(argv[current_arg], "getled\0", 13) == 0) { rc = ipmi_delloem_getled_main (intf,argc,argv); } else if (strncmp(argv[current_arg], "passwordpolicy\0", 14) == 0) { rc = ipmi_delloem_password_policy (intf,argc,argv); } /*Powermanagement report processing*/ else if (strncmp(argv[current_arg], "powermonitor\0", 13) == 0) { rc = ipmi_delloem_powermonitor_main (intf,argc,argv); } /* vFlash Support */ else if (strncmp(argv[current_arg], "vFlash\0", 7) == 0) { rc = ipmi_delloem_vFlash_main (intf,argc,argv); } else if (strncmp(argv[current_arg], "windbg\0", 7) == 0) { rc = ipmi_delloem_windbg_main (intf,argc,argv); } else if ((strncmp(argv[current_arg], "getsysinfo\0", 10) == 0) || (strncmp(argv[current_arg], "setsysinfo\0", 10) == 0)) { rc = ipmi_delloem_sysinfo_main (intf,argc,argv); } else { usage(); return ERR_USAGE; } return rc; } /***************************************************************** * Function Name: usage * * Description: This function prints help message for delloem command * Input: * Output: * * Return: * ******************************************************************/ static void usage(void) { lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, "usage: delloem [option...]"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, "commands:"); lprintf(LOG_NOTICE, " lcd"); lprintf(LOG_NOTICE, " mac"); lprintf(LOG_NOTICE, " lan"); lprintf(LOG_NOTICE, " setled"); lprintf(LOG_NOTICE, " getled"); lprintf(LOG_NOTICE, " powermonitor"); lprintf(LOG_NOTICE, " windbg"); lprintf(LOG_NOTICE, " vFlash"); lprintf(LOG_NOTICE, " getsysinfo"); lprintf(LOG_NOTICE, " setsysinfo"); lprintf(LOG_NOTICE, " passwordpolicy"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, "For help on individual commands type:"); lprintf(LOG_NOTICE, "delloem help"); } /***************************************************************** * Function Name: ipmi_delloem_lcd_main * * Description: This function processes the delloem lcd command * Input: intf - ipmi interface argc - no of arguments argv - argument string array * Output: * * Return: return code 0 - success * -1 - failure * ******************************************************************/ static int ipmi_delloem_lcd_main (void * intf, int argc, char ** argv) { int rc = 0; current_arg++; if (argc < current_arg) { usage(); return -1; } /* ipmitool delloem lcd info*/ if (argc == 1 || strcmp(argv[current_arg], "help") == 0) { ipmi_lcd_usage(); return 0; } CheckLCDSupport (intf); ipmi_idracvalidator_command(intf); if (!IsLCDSupported()) { printf("lcd is not supported on this system.\n"); return -1; } else if (strncmp(argv[current_arg], "info\0", 5) == 0) { if((iDRAC_FLAG==IDRAC_11G) || (iDRAC_FLAG==IDRAC_12G) ) rc = ipmi_lcd_get_info_wh(intf); else rc = ipmi_lcd_get_info(intf); } else if (strncmp(argv[current_arg], "status\0", 7) == 0) { rc = ipmi_lcd_get_status(intf); } /* ipmitool delloem lcd set*/ else if (strncmp(argv[current_arg], "set\0", 4) == 0) { uint8_t line_number = 0; current_arg++; if (argc <= current_arg) { ipmi_lcd_usage(); return -1; } if (strncmp(argv[current_arg], "line\0", 5) == 0) { current_arg++; if (argc <= current_arg) {usage();return -1;} line_number = (uint8_t)strtoul(argv[current_arg], NULL, 0); current_arg++; if (argc <= current_arg) {usage();return -1;} } if ((strncmp(argv[current_arg], "mode\0", 5) == 0)&&((iDRAC_FLAG==IDRAC_11G) || (iDRAC_FLAG==IDRAC_12G) )) { current_arg++; if (argc <= current_arg) { ipmi_lcd_usage(); return -1; } if (argv[current_arg] == NULL) { ipmi_lcd_usage(); return -1; } if (strncmp(argv[current_arg], "none\0", 5) == 0) { rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_CONFIG_NONE,0xFF,0XFF, 0, NULL); } else if (strncmp(argv[current_arg], "modelname\0", 10) == 0) { rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_CONFIG_DEFAULT,0xFF,0XFF, 0, NULL); } else if (strncmp(argv[current_arg], "userdefined\0", 12) == 0) { current_arg++; if (argc <= current_arg) { ipmi_lcd_usage();return -1; } rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_CONFIG_USER_DEFINED,0xFF,0XFF, line_number, argv[current_arg]); } else if (strncmp(argv[current_arg], "ipv4address\0", 12) == 0) { rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_iDRAC_IPV4ADRESS ,0xFF,0XFF, 0, NULL); } else if (strncmp(argv[current_arg], "macaddress\0", 11) == 0) { rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_IDRAC_MAC_ADDRESS,0xFF,0XFF, 0, NULL); } else if (strncmp(argv[current_arg], "systemname\0", 11) == 0) { rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_OS_SYSTEM_NAME,0xFF,0XFF, 0, NULL); } else if (strncmp(argv[current_arg], "servicetag\0", 11) == 0) { rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_SERVICE_TAG, 0xFF,0XFF,0, NULL); } else if (strncmp(argv[current_arg], "ipv6address\0", 12) == 0) { rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_iDRAC_IPV6ADRESS ,0xFF,0XFF, 0, NULL); } else if (strncmp(argv[current_arg], "ambienttemp\0", 12) == 0) { rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_AMBEINT_TEMP, 0xFF,0XFF,0, NULL); } else if (strncmp(argv[current_arg], "systemwatt\0", 11) == 0) { rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_SYSTEM_WATTS , 0xFF,0XFF,0, NULL); } else if (strncmp(argv[current_arg], "assettag\0", 9) == 0) { rc = ipmi_lcd_configure_wh (intf, IPMI_DELL_LCD_ASSET_TAG , 0xFF,0XFF,0, NULL); } else if (strncmp(argv[current_arg], "help\0", 5) == 0) { ipmi_lcd_usage(); } else { ipmi_lcd_usage(); } } else if ((strncmp(argv[current_arg], "lcdqualifier\0", 13)== 0) &&((iDRAC_FLAG==IDRAC_11G) || (iDRAC_FLAG==IDRAC_12G) ) ) { current_arg++; if (argc <= current_arg) { ipmi_lcd_usage(); return -1; } if (argv[current_arg] == NULL) { ipmi_lcd_usage(); return -1; } if (strncmp(argv[current_arg], "watt\0", 5) == 0) { rc = ipmi_lcd_configure_wh (intf, 0xFF,0x00,0XFF, 0, NULL); } else if (strncmp(argv[current_arg], "btuphr\0",7) == 0) { rc = ipmi_lcd_configure_wh (intf, 0xFF,0x01,0XFF, 0, NULL); } else if (strncmp(argv[current_arg], "celsius\0", 8) == 0) { rc = ipmi_lcd_configure_wh (intf, 0xFF,0x02,0xFF, 0, NULL); } else if (strncmp(argv[current_arg], "fahrenheit", 11) == 0) { rc = ipmi_lcd_configure_wh (intf, 0xFF,0x03,0xFF, 0, NULL); }else if (strncmp(argv[current_arg], "help\0", 5) == 0) { ipmi_lcd_usage(); } else { ipmi_lcd_usage(); } } else if( (strncmp(argv[current_arg], "errordisplay\0", 13) == 0)&&((iDRAC_FLAG==IDRAC_11G) || (iDRAC_FLAG==IDRAC_12G) )) { current_arg++; if (argc <= current_arg) { ipmi_lcd_usage(); return -1; } if (argv[current_arg] == NULL) { ipmi_lcd_usage(); return -1; } if (strncmp(argv[current_arg], "sel\0", 4) == 0) { rc = ipmi_lcd_configure_wh (intf, 0xFF,0xFF,IPMI_DELL_LCD_ERROR_DISP_SEL , 0, NULL); } else if (strncmp(argv[current_arg], "simple\0", 7) == 0) { rc = ipmi_lcd_configure_wh (intf, 0xFF,0xFF,IPMI_DELL_LCD_ERROR_DISP_VERBOSE , 0, NULL); } else if (strncmp(argv[current_arg], "help\0", 5) == 0) { ipmi_lcd_usage(); } else { ipmi_lcd_usage(); } } else if ((strncmp(argv[current_arg], "none\0", 5) == 0)&&(iDRAC_FLAG==0)) { rc = ipmi_lcd_configure (intf, IPMI_DELL_LCD_CONFIG_NONE, 0, NULL); } else if ((strncmp(argv[current_arg], "default\0", 8) == 0)&&(iDRAC_FLAG==0)) { rc = ipmi_lcd_configure (intf, IPMI_DELL_LCD_CONFIG_DEFAULT, 0, NULL); } else if ((strncmp(argv[current_arg], "custom\0", 7) == 0)&&(iDRAC_FLAG==0)) { current_arg++; if (argc <= current_arg) { ipmi_lcd_usage(); return -1; } rc = ipmi_lcd_configure (intf, IPMI_DELL_LCD_CONFIG_USER_DEFINED, line_number, argv[current_arg]); } else if (strncmp(argv[current_arg], "vkvm\0", 5) == 0) { current_arg++; if (argc <= current_arg) { ipmi_lcd_usage(); return -1; } if (strncmp(argv[current_arg], "active\0", 7) == 0) { rc = ipmi_lcd_set_kvm (intf, 1); } else if (strncmp(argv[current_arg], "inactive\0", 9)==0) { rc = ipmi_lcd_set_kvm (intf, 0); } else if (strncmp(argv[current_arg], "help\0", 5) == 0) { ipmi_lcd_usage(); } else { ipmi_lcd_usage(); } } else if (strncmp(argv[current_arg], "frontpanelaccess\0", 17) == 0) { current_arg++; if (argc <= current_arg) { ipmi_lcd_usage(); return -1; } if (strncmp(argv[current_arg], "viewandmodify\0", 14) == 0) { rc = ipmi_lcd_set_lock (intf, 0); } else if (strncmp(argv[current_arg], "viewonly\0", 9)==0) { rc = ipmi_lcd_set_lock (intf, 1); } else if (strncmp(argv[current_arg], "disabled\0", 9)==0) { rc = ipmi_lcd_set_lock (intf, 2); } else if (strncmp(argv[current_arg], "help\0", 5) == 0) { ipmi_lcd_usage(); } else { ipmi_lcd_usage(); } } else if( (strncmp(argv[current_arg], "help\0", 5) == 0)&&(iDRAC_FLAG==0)) { ipmi_lcd_usage(); } else { ipmi_lcd_usage(); return -1; } } else { ipmi_lcd_usage(); return -1; } return(rc); } /***************************************************************** * Function Name: ipmi_lcd_get_platform_model_name * * Description: This function retrieves the platform model name, or any other parameter * which stores data in the same format * Input: intf - pointer to interface * max_length - length of the platform model string * field_type - either hostname / platform model * Output: lcdstring - hostname / platform model string * * Return: * ******************************************************************/ static int ipmi_lcd_get_platform_model_name (void * intf, char* lcdstring, uint8_t max_length, uint8_t field_type) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[4]; IPMI_DELL_LCD_STRING * lcdstringblock; int lcdstring_len = 0; int bytes_copied = 0; int ii; for (ii = 0; ii < 4; ii++) { int bytes_to_copy; memset (&req,0,sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_GET_SYS_INFO; req.msg.data_len = 4; req.msg.data = data; data[0] = 0; /* get parameter*/ data[1] = field_type; data[2] = ii; data[3] = 0; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error getting platform model name: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } lcdstringblock = (IPMI_DELL_LCD_STRING *) (void *) rsp; /* first block is different - 14 bytes*/ if (0 == ii) { lcdstring_len = lcdstringblock->lcd_string.selector_0_string.length; lcdstring_len = MIN (lcdstring_len,max_length); bytes_to_copy = MIN(lcdstring_len, IPMI_DELL_LCD_STRING1_SIZE); memcpy (lcdstring, lcdstringblock->lcd_string.selector_0_string.data, bytes_to_copy); } else { int string_offset; bytes_to_copy = MIN(lcdstring_len - bytes_copied, IPMI_DELL_LCD_STRINGN_SIZE); if (bytes_to_copy < 1) break; string_offset = IPMI_DELL_LCD_STRING1_SIZE + IPMI_DELL_LCD_STRINGN_SIZE * (ii-1); memcpy (lcdstring+string_offset, lcdstringblock->lcd_string.selector_n_data, bytes_to_copy); } bytes_copied += bytes_to_copy; if (bytes_copied >= lcdstring_len) break; } return rv; } /***************************************************************** * Function Name: ipmi_idracvalidator_command * * Description: This function returns the iDRAC6 type * Input: intf - ipmi interface * Output: * * Return: iDRAC6 type 1 - whoville * 0 - others * ******************************************************************/ static int ipmi_idracvalidator_command (void * intf) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[4]; memset (&req,0,sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_GET_SYS_INFO; req.msg.data_len = 4; req.msg.data = data; data[0] = 0; data[1] = IPMI_DELL_IDRAC_VALIDATOR; data[2] = 2; data[3] = 0; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv && fdebug) { printf(" Error getting IMC type"); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x\n", rv); return rv; } IMC_Type = rsp[10]; if( (IMC_Type == IMC_IDRAC_11G_MONOLITHIC) || (IMC_Type == IMC_IDRAC_11G_MODULAR) ) { iDRAC_FLAG=IDRAC_11G; } else if( (IMC_Type == IMC_IDRAC_12G_MONOLITHIC) || (IMC_Type == IMC_IDRAC_12G_MODULAR) ) { iDRAC_FLAG=IDRAC_12G; } else { iDRAC_FLAG=0; } return 0; } /***************************************************************** * Function Name: ipmi_lcd_get_configure_command_wh * * Description: This function returns current lcd configuration for Dell OEM LCD command * Input: intf - ipmi interface * Global: lcd_mode - lcd mode setting * Output: * * Return: returns the current lcd configuration * 0 = User defined * 1 = Default * 2 = None * ******************************************************************/ static int ipmi_lcd_get_configure_command_wh (void * intf) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[4]; req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_GET_SYS_INFO; req.msg.data_len = 4; req.msg.data = data; data[0] = 0; data[1] = IPMI_DELL_LCD_CONFIG_SELECTOR; data[2] = 0; data[3] = 0; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error getting LCD configuration: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x\n", rv); return rv; } lcd_mode= *((LCD_MODE*)(&rsp[0])); return 0; } /***************************************************************** * Function Name: ipmi_lcd_get_configure_command * * Description: This function returns current lcd configuration for Dell OEM LCD command * Input: intf - ipmi interface * Output: command - user defined / default / none / ipv4 / mac address / system name / service tag / ipv6 / temp / system watt / asset tag * * Return: * ******************************************************************/ static int ipmi_lcd_get_configure_command (void * intf, uint8_t *command) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[4]; req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_GET_SYS_INFO; req.msg.data_len = 4; req.msg.data = data; data[0] = 0; data[1] = IPMI_DELL_LCD_CONFIG_SELECTOR; data[2] = 0; data[3] = 0; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error getting LCD configuration: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x\n", rv); return rv; } /* rsp->data[0] is the rev */ *command = rsp[1]; return 0; } /***************************************************************** * Function Name: ipmi_lcd_set_configure_command * * Description: This function updates current lcd configuration * Input: intf - ipmi interface * command - user defined / default / none / ipv4 / mac address / * system name / service tag / ipv6 / temp / system watt / asset tag * Output: * Return: * ******************************************************************/ static int ipmi_lcd_set_configure_command (void * intf, int command) { #define LSCC_DATA_LEN 2 uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[2]; req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_SET_SYS_INFO; req.msg.data_len = 2; req.msg.data = data; data[0] = IPMI_DELL_LCD_CONFIG_SELECTOR; data[1] = command; /* command - custom, default, none */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error setting LCD configuration: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x\n", rv); return rv; } return 0; } /***************************************************************** * Function Name: ipmi_lcd_set_configure_command * * Description: This function updates current lcd configuration * Input: intf - ipmi interface * mode - user defined / default / none * lcdqualifier - lcd quallifier id * errordisp - error number * Output: * Return: * ******************************************************************/ static int ipmi_lcd_set_configure_command_wh (void * intf, uint32_t mode, uint16_t lcdqualifier, uint8_t errordisp) { #define LSCC_DATA_LEN 2 uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[13]; ipmi_lcd_get_configure_command_wh(intf); req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_SET_SYS_INFO; req.msg.data_len = 13; req.msg.data = data; data[0] = IPMI_DELL_LCD_CONFIG_SELECTOR; if(mode!=0xFF) { data[1] = mode&0xFF; /* command - custom, default, none*/ data[2]=(mode&0xFF00)>>8; data[3]=(mode&0xFF0000)>>16; data[4]=(mode&0xFF000000)>>24; } else { data[1] = (lcd_mode.lcdmode)&0xFF; /* command - custom, default, none*/ data[2]=((lcd_mode.lcdmode)&0xFF00)>>8; data[3]=((lcd_mode.lcdmode)&0xFF0000)>>16; data[4]=((lcd_mode.lcdmode)&0xFF000000)>>24; } if(lcdqualifier!=0xFF) { if(lcdqualifier==0x01) { data[5] =(lcd_mode.lcdqualifier)|0x01; /* command - custom, default, none*/ } else if(lcdqualifier==0x00) { data[5] =(lcd_mode.lcdqualifier)&0xFE; /* command - custom, default, none*/ } else if (lcdqualifier==0x03) { data[5] =(lcd_mode.lcdqualifier)|0x02; /* command - custom, default, none*/ } else if (lcdqualifier==0x02) { data[5] =(lcd_mode.lcdqualifier)&0xFD; } } else { data[5]=(uchar)lcd_mode.lcdqualifier; } if(errordisp!=0xFF) { data[11]=errordisp; } else { data[11]=lcd_mode.error_display; } rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error setting LCD configuration: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x\n", rv); return rv; } return 0; } /***************************************************************** * Function Name: ipmi_lcd_get_single_line_text * * Description: This function updates current lcd configuration * Input: intf - ipmi interface * lcdstring - new string to be updated * max_length - length of the string * Output: * Return: * ******************************************************************/ static int ipmi_lcd_get_single_line_text (void * intf, char* lcdstring, uint8_t max_length) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[4]; IPMI_DELL_LCD_STRING * lcdstringblock; int lcdstring_len = 0; int bytes_copied = 0; int ii; for (ii = 0; ii < 4; ii++) { int bytes_to_copy; req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_GET_SYS_INFO; req.msg.data_len = 4; req.msg.data = data; data[0] = 0; /* get parameter*/ data[1] = IPMI_DELL_LCD_STRING_SELECTOR; data[2] = ii; /* block selector*/ data[3] = 0; /* set selector (n/a)*/ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error getting text data: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x\n", rv); return rv; } lcdstringblock = (IPMI_DELL_LCD_STRING *) (void *) rsp; /* first block is different - 14 bytes*/ if (0 == ii) { lcdstring_len = lcdstringblock->lcd_string.selector_0_string.length; if (lcdstring_len < 1 || lcdstring_len > max_length) break; bytes_to_copy = MIN(lcdstring_len, IPMI_DELL_LCD_STRING1_SIZE); memcpy (lcdstring, lcdstringblock->lcd_string.selector_0_string.data, bytes_to_copy); } else { int string_offset; bytes_to_copy = MIN(lcdstring_len - bytes_copied, IPMI_DELL_LCD_STRINGN_SIZE); if (bytes_to_copy < 1) break; string_offset = IPMI_DELL_LCD_STRING1_SIZE + IPMI_DELL_LCD_STRINGN_SIZE * (ii-1); memcpy (lcdstring+string_offset, lcdstringblock->lcd_string.selector_n_data, bytes_to_copy); } bytes_copied += bytes_to_copy; if (bytes_copied >= lcdstring_len) break; } return 0; } /***************************************************************** * Function Name: ipmi_lcd_get_info_wh * * Description: This function prints current lcd configuration for whoville platform * Input: intf - ipmi interface * Output: * Return: * ******************************************************************/ static int ipmi_lcd_get_info_wh(void * intf) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[4]; IPMI_DELL_LCD_CAPS* lcd_caps; char lcdstring[IPMI_DELL_LCD_STRING_LENGTH_MAX+1] = {0}; printf("LCD info\n"); if (ipmi_lcd_get_configure_command_wh (intf) != 0) { return -1; } else { if (lcd_mode.lcdmode== IPMI_DELL_LCD_CONFIG_DEFAULT) { char text[IPMI_DELL_LCD_STRING_LENGTH_MAX+1] = {0}; ipmi_lcd_get_platform_model_name(intf, text, IPMI_DELL_LCD_STRING_LENGTH_MAX, IPMI_DELL_PLATFORM_MODEL_NAME_SELECTOR); if (text == NULL) return -1; printf(" Setting:Model name\n"); printf(" Line 1: %s\n", text); } else if (lcd_mode.lcdmode == IPMI_DELL_LCD_CONFIG_NONE) { printf(" Setting: none\n"); } else if (lcd_mode.lcdmode == IPMI_DELL_LCD_CONFIG_USER_DEFINED) { req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_GET_SYS_INFO; req.msg.data_len = 4; req.msg.data = data; data[0] = 0; /* get parameter*/ data[1] = IPMI_DELL_LCD_GET_CAPS_SELECTOR; data[2] = 0; /* set selector (n/a)*/ data[3] = 0; /* block selector (n/a)*/ printf(" Setting: User defined\n"); rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error getting LCD capabilities: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x\n", rv); return rv; } lcd_caps = (IPMI_DELL_LCD_CAPS *)rsp; if (lcd_caps->number_lines > 0) { memset(lcdstring, 0, IPMI_DELL_LCD_STRING_LENGTH_MAX+1); rv = ipmi_lcd_get_single_line_text (intf, lcdstring, lcd_caps->max_chars[0]); printf(" Text: %s\n", lcdstring); } else { printf(" No lines to show\n"); } } else if (lcd_mode.lcdmode == IPMI_DELL_LCD_iDRAC_IPV4ADRESS) { printf(" Setting: IPV4 Address\n"); } else if (lcd_mode.lcdmode == IPMI_DELL_LCD_IDRAC_MAC_ADDRESS) { printf(" Setting: MAC Address\n"); } else if (lcd_mode.lcdmode == IPMI_DELL_LCD_OS_SYSTEM_NAME) { printf(" Setting: OS System Name\n"); } else if (lcd_mode.lcdmode == IPMI_DELL_LCD_SERVICE_TAG) { printf(" Setting: System Tag\n"); } else if (lcd_mode.lcdmode == IPMI_DELL_LCD_iDRAC_IPV6ADRESS) { printf(" Setting: IPV6 Address\n"); } else if (lcd_mode.lcdmode == IPMI_DELL_LCD_AMBEINT_TEMP) { printf(" Setting: Ambient Temp\n"); if(lcd_mode.lcdqualifier&0x02) printf(" Unit: F\n"); else printf(" Unit: C\n"); } else if (lcd_mode.lcdmode == IPMI_DELL_LCD_SYSTEM_WATTS) { printf(" Setting: System Watts\n"); if(lcd_mode.lcdqualifier&0x01) printf(" Unit: BTU/hr\n"); else printf(" Unit: Watt\n"); } if(lcd_mode.error_display==IPMI_DELL_LCD_ERROR_DISP_SEL) printf(" Error Display: SEL\n"); else if(lcd_mode.error_display==IPMI_DELL_LCD_ERROR_DISP_VERBOSE) printf(" Error Display: Simple\n"); } return 0; } /***************************************************************** * Function Name: ipmi_lcd_get_info * * Description: This function prints current lcd configuration for platform other than whoville * Input: intf - ipmi interface * Output: * Return: * ******************************************************************/ static int ipmi_lcd_get_info(void * intf) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[4]; IPMI_DELL_LCD_CAPS * lcd_caps; uint8_t command = 0; char lcdstring[IPMI_DELL_LCD_STRING_LENGTH_MAX+1] = {0}; printf("LCD info\n"); if (ipmi_lcd_get_configure_command (intf, &command) != 0) { return -1; } else { if (command == IPMI_DELL_LCD_CONFIG_DEFAULT) { memset (lcdstring,0,IPMI_DELL_LCD_STRING_LENGTH_MAX+1); ipmi_lcd_get_platform_model_name(intf, lcdstring, IPMI_DELL_LCD_STRING_LENGTH_MAX, IPMI_DELL_PLATFORM_MODEL_NAME_SELECTOR); printf(" Setting: default\n"); printf(" Line 1: %s\n", lcdstring); } else if (command == IPMI_DELL_LCD_CONFIG_NONE) { printf(" Setting: none\n"); } else if (command == IPMI_DELL_LCD_CONFIG_USER_DEFINED) { req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_GET_SYS_INFO; req.msg.data_len = 4; req.msg.data = data; data[0] = 0; /* get parameter */ data[1] = IPMI_DELL_LCD_GET_CAPS_SELECTOR; data[2] = 0; /* set selector (n/a) */ data[3] = 0; /* block selector (n/a) */ printf(" Setting: custom\n"); rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error getting LCD capabilities: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x\n", rv); return rv; } lcd_caps = (IPMI_DELL_LCD_CAPS *)(void *)rsp; if (lcd_caps->number_lines > 0) { memset (lcdstring,0,IPMI_DELL_LCD_STRING_LENGTH_MAX+1); rv = ipmi_lcd_get_single_line_text (intf, lcdstring, lcd_caps->max_chars[0]); printf(" Text: %s\n", lcdstring); } else { printf(" No lines to show\n"); } } } return 0; } /***************************************************************** * Function Name: ipmi_lcd_get_status_val * * Description: This function gets current lcd configuration * Input: intf - ipmi interface * Output: lcdstatus - KVM Status & Lock Status * Return: * ******************************************************************/ static int ipmi_lcd_get_status_val(void * intf, LCD_STATUS* lcdstatus) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[4]; req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_GET_SYS_INFO; req.msg.data_len = 4; req.msg.data = data; data[0] = 0; /* get parameter */ data[1] = IPMI_DELL_LCD_STATUS_SELECTOR; data[2] = 0; /* block selector */ data[3] = 0; /* set selector (n/a) */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error getting LCD status: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x\n", rv); return rv; } /*lcdstatus= (LCD_STATUS* ) rsp->data; */ lcdstatus->vKVM_status=rsp[1]; lcdstatus->lock_status=rsp[2]; return 0; } /***************************************************************** * Function Name: IsLCDSupported * * Description: This function returns whether lcd supported or not * Input: * Output: * Return: * ******************************************************************/ static int IsLCDSupported () { return LcdSupported; } /***************************************************************** * Function Name: CheckLCDSupport * * Description: This function checks whether lcd supported or not * Input: intf - ipmi interface * Output: * Return: * ******************************************************************/ static void CheckLCDSupport(void * intf) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[4]; LcdSupported = 0; req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_GET_SYS_INFO; req.msg.data_len = 4; req.msg.data = data; data[0] = 0; /* get parameter */ data[1] = IPMI_DELL_LCD_STATUS_SELECTOR; data[2] = 0; /* block selector */ data[3] = 0; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { return; } LcdSupported = 1; } /***************************************************************** * Function Name: ipmi_lcd_status_print * * Description: This function prints current lcd configuration KVM Status & Lock Status * Input: lcdstatus - KVM Status & Lock Status * Output: * Return: * ******************************************************************/ static void ipmi_lcd_status_print( LCD_STATUS lcdstatus) { switch (lcdstatus.vKVM_status) { case 0x00: printf("LCD KVM Status :Inactive\n"); break; case 0x01: printf("LCD KVM Status :Active\n"); break; default: printf("LCD KVM Status :Invalid Status\n"); break; } switch (lcdstatus.lock_status) { case 0x00: printf("LCD lock Status :View and modify\n"); break; case 0x01: printf("LCD lock Status :View only\n"); break; case 0x02: printf("LCD lock Status :disabled\n"); break; default: printf("LCD lock Status :Invalid\n"); break; } } /***************************************************************** * Function Name: ipmi_lcd_get_status * * Description: This function gets current lcd KVM active status & lcd access mode * Input: intf - ipmi interface * Output: * Return: -1 on error * 0 if successful * ******************************************************************/ static int ipmi_lcd_get_status(void * intf ) { int rc=0; LCD_STATUS lcdstatus; rc =ipmi_lcd_get_status_val( intf, &lcdstatus); if (rc <0) return -1; ipmi_lcd_status_print(lcdstatus); return rc; } /***************************************************************** * Function Name: ipmi_lcd_set_kvm * * Description: This function sets lcd KVM active status * Input: intf - ipmi interface * status - Inactive / Active * Output: * Return: -1 on error * 0 if successful * ******************************************************************/ static int ipmi_lcd_set_kvm(void * intf, char status) { #define LSCC_DATA_LEN 2 LCD_STATUS lcdstatus; int rc=0; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[5]; rc=ipmi_lcd_get_status_val(intf,&lcdstatus); if (rc < 0) return -1; req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_SET_SYS_INFO; req.msg.data_len = 5; req.msg.data = data; data[0] = IPMI_DELL_LCD_STATUS_SELECTOR; data[1] = status; /* active- incative*/ data[2] = lcdstatus.lock_status; /* full-veiw-locked */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error setting LCD status: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x\n", rv); return rv; } return rc; } /***************************************************************** * Function Name: ipmi_lcd_set_lock * * Description: This function sets lcd access mode * Input: intf - ipmi interface * lock - View and modify / View only / Diabled * Output: * Return: -1 on error * 0 if successful * ******************************************************************/ static int ipmi_lcd_set_lock(void * intf, char lock) { #define LSCC_DATA_LEN 2 LCD_STATUS lcdstatus; int rc =0; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[5]; rc=ipmi_lcd_get_status_val(intf,&lcdstatus); if (rc < 0) return -1; req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_SET_SYS_INFO; req.msg.data_len = 5; req.msg.data = data; data[0] = IPMI_DELL_LCD_STATUS_SELECTOR; data[1] = lcdstatus.vKVM_status; /* active- incative */ data[2] = lock; /* full- veiw-locked */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error setting LCD status: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x\n", rv); return rv; } return rc; } /***************************************************************** * Function Name: ipmi_lcd_set_single_line_text * * Description: This function sets lcd line text * Input: intf - ipmi interface * text - lcd string * Output: * Return: -1 on error * 0 if successful * ******************************************************************/ static int ipmi_lcd_set_single_line_text (void * intf, char * text) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[18]; int bytes_to_store = strlen_(text); int bytes_stored = 0; int ii; int rc = 0; if (bytes_to_store>IPMI_DELL_LCD_STRING_LENGTH_MAX) { lprintf(LOG_ERR, " Out of range Max limit is 62 characters"); return 1; } else { bytes_to_store = MIN(bytes_to_store, IPMI_DELL_LCD_STRING_LENGTH_MAX); for (ii = 0; ii < 4; ii++) { /*first block, 2 bytes parms and 14 bytes data*/ if (0 == ii) { int size_of_copy = MIN((bytes_to_store - bytes_stored), IPMI_DELL_LCD_STRING1_SIZE); if (size_of_copy < 0) /* allow 0 string length*/ break; req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_SET_SYS_INFO; req.msg.data_len = size_of_copy + 4; /* chars, selectors and sizes*/ req.msg.data = data; data[0] = IPMI_DELL_LCD_STRING_SELECTOR; data[1] = ii; /* block number to use (0)*/ data[2] = 0; /*string encoding*/ data[3] = bytes_to_store; /* total string length*/ memcpy (data+4, text+bytes_stored, size_of_copy); bytes_stored += size_of_copy; } else { int size_of_copy = MIN((bytes_to_store - bytes_stored), IPMI_DELL_LCD_STRINGN_SIZE); if (size_of_copy <= 0) break; req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_SET_SYS_INFO; req.msg.data_len = size_of_copy + 2; req.msg.data = data; data[0] = IPMI_DELL_LCD_STRING_SELECTOR; data[1] = ii; /* block number to use (1,2,3)*/ memcpy (data+2, text+bytes_stored, size_of_copy); bytes_stored += size_of_copy; } rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error setting text data: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x\n", rv); return rv; } } } return rc; } /***************************************************************** * Function Name: ipmi_lcd_set_text * * Description: This function sets lcd line text * Input: intf - ipmi interface * text - lcd string * line_number- line number * Output: * Return: -1 on error * 0 if successful * ******************************************************************/ static int ipmi_lcd_set_text(void * intf, char * text, int line_number) { int rc = 0; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[4]; IPMI_DELL_LCD_CAPS * lcd_caps; req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_GET_SYS_INFO; req.msg.data_len = 4; req.msg.data = data; data[0] = 0; /* get parameter*/ data[1] = IPMI_DELL_LCD_GET_CAPS_SELECTOR; data[2] = 0; /* set selector (n/a)*/ data[3] = 0; /* block selector (n/a)*/ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error getting LCD capabilities: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x\n", rv); return rv; } lcd_caps = (IPMI_DELL_LCD_CAPS *)(void *)rsp; if (lcd_caps->number_lines > 0) { rc = ipmi_lcd_set_single_line_text (intf, text); } else { lprintf(LOG_ERR, "LCD does not have any lines that can be set"); rc = -1; } return rc; } /***************************************************************** * Function Name: ipmi_lcd_configure_wh * * Description: This function updates the current lcd configuration * Input: intf - ipmi interface * lcdqualifier- lcd quallifier * errordisp - error number * line_number-line number * text - lcd string * Output: * Return: -1 on error * 0 if successful * ******************************************************************/ static int ipmi_lcd_configure_wh (void * intf, uint32_t mode , uint16_t lcdqualifier, uint8_t errordisp, int8_t line_number, char * text) { int rc = 0; if (IPMI_DELL_LCD_CONFIG_USER_DEFINED == mode) /* Any error was reported earlier. */ rc = ipmi_lcd_set_text(intf, text, line_number); if (rc == 0) rc = ipmi_lcd_set_configure_command_wh (intf, mode ,lcdqualifier,errordisp); return rc; } /***************************************************************** * Function Name: ipmi_lcd_configure * * Description: This function updates the current lcd configuration * Input: intf - ipmi interface * command- lcd command * line_number-line number * text - lcd string * Output: * Return: -1 on error * 0 if successful * ******************************************************************/ static int ipmi_lcd_configure (void * intf, int command, int8_t line_number, char * text) { int rc = 0; if (IPMI_DELL_LCD_CONFIG_USER_DEFINED == command) rc = ipmi_lcd_set_text(intf, text, line_number); if (rc == 0) rc = ipmi_lcd_set_configure_command (intf, command); return rc; } /***************************************************************** * Function Name: ipmi_lcd_usage * * Description: This function prints help message for lcd command * Input: * Output: * * Return: * ******************************************************************/ static void ipmi_lcd_usage(void) { lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, "Generic DELL HW:"); lprintf(LOG_NOTICE, " lcd set {none}|{default}|{custom }"); lprintf(LOG_NOTICE, " Set LCD text displayed during non-fault conditions"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, "iDRAC 11g or iDRAC 12g:"); lprintf(LOG_NOTICE, " lcd set {mode}|{lcdqualifier}|{errordisplay}"); lprintf(LOG_NOTICE, " Allows you to set the LCD mode and user-definedstring."); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " lcd set mode {none}|{modelname}|{ipv4address}|{macaddress}|"); lprintf(LOG_NOTICE, " {systemname}|{servicetag}|{ipv6address}|{ambienttemp}"); lprintf(LOG_NOTICE, " {systemwatt }|{assettag}|{userdefined}"); lprintf(LOG_NOTICE, " Allows you to set the LCD display mode to any of the preceding parameters"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " lcd set lcdqualifier {watt}|{btuphr}|{celsius}|{fahrenheit}"); lprintf(LOG_NOTICE, " Allows you to set the unit for the system ambient temperature mode."); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " lcd set errordisplay {sel}|{simple}"); lprintf(LOG_NOTICE, " Allows you to set the error display."); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " lcd info"); lprintf(LOG_NOTICE, " Show LCD text that is displayed during non-fault conditions"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " lcd set vkvm{active}|{inactive}"); lprintf(LOG_NOTICE, " Set vKVM active and inactive, message will be displayed on lcd"); lprintf(LOG_NOTICE, " when vKVM is active and vKVM session is in progress"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " lcd set frontpanelaccess {viewandmodify}|{viewonly}|{disabled}"); lprintf(LOG_NOTICE, " Set LCD mode to view and modify, view only or disabled "); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " lcd status"); lprintf(LOG_NOTICE, " Show LCD Status for vKVM display"); lprintf(LOG_NOTICE, " and Front Panel access mode {viewandmodify}|{viewonly}|{disabled} "); lprintf(LOG_NOTICE, ""); } /***************************************************************** * Function Name: ipmi_delloem_mac_main * * Description: This function processes the delloem mac command * Input: intf - ipmi interface argc - no of arguments argv - argument string array * Output: * * Return: return code 0 - success * -1 - failure * ******************************************************************/ static int ipmi_delloem_mac_main (void * intf, int argc, char ** argv) { int rc = 0; current_arg++; if (argc > 1 && strcmp(argv[current_arg], "help") == 0) { ipmi_mac_usage(); return 0; } ipmi_idracvalidator_command(intf); if (argc == 1) /*( || (strncmp(argv[current_arg], "list\0", 5) == 0) )*/ { rc = ipmi_macinfo(intf, 0xff); } else if (strncmp(argv[current_arg], "get\0", 4) == 0) { int currIdInt; current_arg++; if (argv[current_arg] == NULL) { ipmi_mac_usage(); return -1; } if(make_int(argv[current_arg],&currIdInt) < 0) { lprintf(LOG_ERR, "Invalid NIC number. The NIC number should be between 0-8\n"); return -1; } if( (currIdInt > 8) || (currIdInt < 0) ) { lprintf(LOG_ERR, "Invalid NIC number. The NIC number should be between 0-8\n"); return -1; } rc = ipmi_macinfo(intf, currIdInt); } else { ipmi_mac_usage(); } return(rc); } /***************************************************************** * Function Name: make_int * * Description: This function convert string into integer * Input: str - decimal number string * Output: value - integer value * Return: * ******************************************************************/ static int make_int(const char *str, int *value) { char *tmp=NULL; *value = (int)strtol(str,&tmp,0); if ( tmp-str != strlen(str) ) { return -1; } return 0; } EmbeddedNICMacAddressType EmbeddedNICMacAddress; EmbeddedNICMacAddressType_10G EmbeddedNICMacAddress_10G; static void InitEmbeddedNICMacAddressValues () { uint8_t i; uint8_t j; for (i=0;i> 6); lom_mactype = ((EmbeddedNICMacAddress.LOMMacAddress[i].b0 & 0x30) >> 4); /* lom_bladslot = (b0 & 0x0f); */ lom_nicnum = (EmbeddedNICMacAddress.LOMMacAddress[i].b1 & 0x1f); lom_mac = &EmbeddedNICMacAddress.LOMMacAddress[i].MacAddressByte[0]; if (fdebug) { printf("\n\rlom_ethstat=%x lom_mactype=%x lom_nicnum=%x\n", lom_ethstat,lom_mactype,lom_nicnum); printf("MacAdrB=%02x:%02x:%02x:%02x:%02x:%02x\n", lom_mac[0], lom_mac[1], lom_mac[2], lom_mac[3], lom_mac[4], lom_mac[5]); printf("\n\rrsp_mac=%02x:%02x:%02x:%02x:%02x:%02x\n", rsp[3], rsp[4], rsp[5], rsp[6], rsp[7], rsp[8]); } lom_mac = &rsp[3]; #endif if (LOM_MACTYPE_ETHERNET == lom_mactype) { if ( (0xff==NicNum) || (NicNum == lom_nicnum) ) { printf ("\n\r%d",lom_nicnum); printf ("\t\t"); for (j=0;j<5;j++) printf("%02x:",lom_mac[j]); printf("%02x",lom_mac[j]); if (LOM_ETHERNET_ENABLED == lom_ethstat) printf ("\tEnabled"); else printf ("\tDisabled"); } } } printf ("\n\r"); } ipmi_macinfo_drac_idrac_mac(intf,NicNum); return 0; } /***************************************************************** * Function Name: ipmi_macinfo * * Description: This function retrieves the mac address of LOMs * Input: intf - ipmi interface * Output: * Return: * ******************************************************************/ static int ipmi_macinfo (void* intf, uint8_t NicNum) { if (IMC_IDRAC_10G == IMC_Type) { return ipmi_macinfo_10g (intf,NicNum); } else if ((IMC_IDRAC_11G_MODULAR == IMC_Type || IMC_IDRAC_11G_MONOLITHIC== IMC_Type ) || (IMC_IDRAC_12G_MODULAR == IMC_Type || IMC_IDRAC_12G_MONOLITHIC== IMC_Type ) ) { return ipmi_macinfo_11g (intf,NicNum); } else { lprintf(LOG_ERR, " Error in getting MAC Address : Not supported platform"); return 0; } } /***************************************************************** * Function Name: ipmi_mac_usage * * Description: This function prints help message for mac command * Input: * Output: * * Return: * ******************************************************************/ static void ipmi_mac_usage(void) { lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " mac list"); lprintf(LOG_NOTICE, " Lists the MAC address of LOMs"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " mac get "); lprintf(LOG_NOTICE, " Shows the MAC address of specified LOM. 0-7 System LOM, 8- DRAC/iDRAC."); lprintf(LOG_NOTICE, ""); } /***************************************************************** * Function Name: ipmi_delloem_lan_main * * Description: This function processes the delloem lan command * Input: intf - ipmi interface argc - no of arguments argv - argument string array * Output: * * Return: return code 0 - success * -1 - failure * ******************************************************************/ static int ipmi_delloem_lan_main (void * intf, int argc, char ** argv) { int rc = 0; int nic_selection = 0; char nic_set[2] = {0}; current_arg++; if (argv[current_arg] == NULL || strcmp(argv[current_arg], "help") == 0) { ipmi_lan_usage(); return 0; } ipmi_idracvalidator_command(intf); if (!IsLANSupported()) { printf("lan is not supported on this system.\n"); return -1; } else if (strncmp(argv[current_arg], "set\0", 4) == 0) { current_arg++; if (argv[current_arg] == NULL) { ipmi_lan_usage(); return -1; } if(iDRAC_FLAG == IDRAC_12G) { nic_selection = get_nic_selection_mode_12g(intf,current_arg,argv,nic_set); if (INVALID == nic_selection) { ipmi_lan_usage(); return -1; } else if(INVAILD_FAILOVER_MODE == nic_selection) { printf(INVAILD_FAILOVER_MODE_STRING); return 0; } else if(INVAILD_FAILOVER_MODE_SETTINGS == nic_selection){ printf(INVAILD_FAILOVER_MODE_SET); return 0; } else if(INVAILD_SHARED_MODE == nic_selection){ printf(INVAILD_SHARED_MODE_SET_STRING); return 0; } rc = ipmi_lan_set_nic_selection_12g(intf,nic_set); } else { nic_selection = get_nic_selection_mode(current_arg,argv); if (INVALID == nic_selection) { ipmi_lan_usage(); return -1; } if(IMC_IDRAC_11G_MODULAR == IMC_Type) { printf(INVAILD_SHARED_MODE_SET_STRING); return 0; } rc = ipmi_lan_set_nic_selection(intf,nic_selection); } return 0; } else if (strncmp(argv[current_arg], "get\0", 4) == 0) { current_arg++; if (argv[current_arg] == NULL) { rc = ipmi_lan_get_nic_selection(intf); return rc; } else if (strncmp(argv[current_arg], "active\0", 7) == 0) { rc = ipmi_lan_get_active_nic(intf); return rc; } else { ipmi_lan_usage(); } } else { ipmi_lan_usage(); return -1; } return(rc); } static int IsLANSupported () { if (IMC_IDRAC_11G_MODULAR == IMC_Type) return 0; return 1; } int get_nic_selection_mode_12g (void* intf,int current_arg, char ** argv, char *nic_set) { int failover = 0; // First get the current settings. uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t msg_data[30]; uint8_t input_length=0; input_length = 0; req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; req.msg.cmd = GET_NIC_SELECTION_12G_CMD; req.msg.data = msg_data; req.msg.data_len = input_length; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error in getting NIC selection: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n", rv,decode_cc(0,rv)); return rv; } nic_set[0] = rsp[0]; nic_set[1] = rsp[1]; if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "dedicated\0", 10)) { nic_set[0] = 1; nic_set[1] = 0; return 0; } if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "shared\0", 7)) { } else return INVALID; current_arg++; if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "with\0", 5)) { } else return INVALID; current_arg++; if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "failover\0", 9)) { failover = 1; } if(failover) current_arg++; if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "lom1\0", 5)) { if(IMC_IDRAC_12G_MODULAR == IMC_Type) { return INVAILD_SHARED_MODE; } if(failover) { if(nic_set[0] == 2) { return INVAILD_FAILOVER_MODE; } else if(nic_set[0] == 1) { return INVAILD_FAILOVER_MODE_SETTINGS; } nic_set[1] = 2; } else { nic_set[0] = 2; if(nic_set[1] == 2) nic_set[1] = 0; } return 0; } else if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "lom2\0", 5)) { if(IMC_IDRAC_12G_MODULAR == IMC_Type) { return INVAILD_SHARED_MODE; } if(failover) { if(nic_set[0] == 3) { return INVAILD_FAILOVER_MODE; } else if(nic_set[0] == 1) { return INVAILD_FAILOVER_MODE_SETTINGS; } nic_set[1] = 3; } else { nic_set[0] = 3; if(nic_set[1] == 3) nic_set[1] = 0; } return 0; } else if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "lom3\0", 5)) { if(IMC_IDRAC_12G_MODULAR == IMC_Type) { return INVAILD_SHARED_MODE; } if(failover) { if(nic_set[0] == 4) { return INVAILD_FAILOVER_MODE; } else if(nic_set[0] == 1) { return INVAILD_FAILOVER_MODE_SETTINGS; } nic_set[1] = 4; } else { nic_set[0] = 4; if(nic_set[1] == 4) nic_set[1] = 0; } return 0; } else if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "lom4\0", 5)) { if(IMC_IDRAC_12G_MODULAR == IMC_Type) { return INVAILD_SHARED_MODE; } if(failover) { if(nic_set[0] == 5) { return INVAILD_FAILOVER_MODE; } else if(nic_set[0] == 1) { return INVAILD_FAILOVER_MODE_SETTINGS; } nic_set[1] = 5; } else { nic_set[0] = 5; if(nic_set[1] == 5) nic_set[1] = 0; } return 0; } else if (failover && NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "none\0", 5)) { if(IMC_IDRAC_12G_MODULAR == IMC_Type) { return INVAILD_SHARED_MODE; } if(failover) { if(nic_set[0] == 1) { return INVAILD_FAILOVER_MODE_SETTINGS; } nic_set[1] = 0; } return 0; } else if (failover && NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "all\0", 4)) { } else return INVALID; current_arg++; if (failover && NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "loms\0", 5)) { if(IMC_IDRAC_12G_MODULAR == IMC_Type) { return INVAILD_SHARED_MODE; } if(nic_set[0] == 1) { return INVAILD_FAILOVER_MODE_SETTINGS; } nic_set[1] = 6; return 0; } return INVALID; } static int get_nic_selection_mode (int current_arg, char ** argv) { if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "dedicated\0", 10)) { return DEDICATED; } if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "shared\0", 7)) { if (NULL == argv[current_arg+1] ) return SHARED; } current_arg++; if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "with\0", 5)) { } else return INVALID; current_arg++; if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "failover\0", 9)) { } else return INVALID; current_arg++; if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "lom2\0", 5)) { return SHARED_WITH_FAILOVER_LOM2; } else if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "all\0", 4)) { } else return INVALID; current_arg++; if (NULL!= argv[current_arg] && 0 == strncmp(argv[current_arg], "loms\0", 5)) { return SHARED_WITH_FAILOVER_ALL_LOMS; } return INVALID; } static int ipmi_lan_set_nic_selection_12g (void* intf, uint8_t* nic_selection) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t msg_data[30]; uint8_t input_length=0; input_length = 0; msg_data[input_length++] = nic_selection[0]; msg_data[input_length++] = nic_selection[1]; req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; req.msg.cmd = SET_NIC_SELECTION_12G_CMD; req.msg.data = msg_data; req.msg.data_len = input_length; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error in setting NIC selection: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n", rv,decode_cc(0,rv)); return rv; } printf("configured successfully"); return 0; } static int ipmi_lan_set_nic_selection (void* intf, uint8_t nic_selection) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t msg_data[30]; uint8_t input_length=0; //uint8_t j; input_length = 0; msg_data[input_length++] = nic_selection; req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; req.msg.cmd = SET_NIC_SELECTION_CMD; req.msg.data = msg_data; req.msg.data_len = input_length; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error in setting NIC selection: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n", rv,decode_cc(0,rv)); return rv; } printf("configured successfully"); return 0; } static int ipmi_lan_get_nic_selection (void* intf) { uint8_t nic_selection=-1; uint8_t nic_selection_failover = 0; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t msg_data[30]; uint8_t input_length=0; //uint8_t j; input_length = 0; req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; if(iDRAC_FLAG == IDRAC_12G) req.msg.cmd = GET_NIC_SELECTION_12G_CMD; else req.msg.cmd = GET_NIC_SELECTION_CMD; req.msg.data = msg_data; req.msg.data_len = input_length; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error in getting NIC selection: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n", rv,decode_cc(0,rv)); return rv; } nic_selection = rsp[0]; if(iDRAC_FLAG == IDRAC_12G) { nic_selection_failover = rsp[1]; if ((nic_selection < 6) && (nic_selection > 0) && (nic_selection_failover < 7)) { if(nic_selection == 1) { printf ("%s\n",NIC_Selection_Mode_String_12g[nic_selection-1]); } else if(nic_selection) { printf ("Shared LOM : %s\n",NIC_Selection_Mode_String_12g[nic_selection-1]); if(nic_selection_failover == 0) printf ("Failover LOM : None\n"); else if(nic_selection_failover >= 2 && nic_selection_failover <= 6) printf ("Failover LOM : %s\n",NIC_Selection_Mode_String_12g[nic_selection_failover + 3]); } } else { lprintf(LOG_ERR, " Error Outof bond Value received (%d) (%d) \n",nic_selection,nic_selection_failover); return -1; } } else { printf ("%s\n",NIC_Selection_Mode_String[nic_selection]); } return 0; } static int ipmi_lan_get_active_nic (void* intf) { uint8_t active_nic=0; uint8_t current_lom =0; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t msg_data[30]; uint8_t input_length=0; input_length = 0; msg_data[input_length++] = 0; /*Get current LOM*/ msg_data[input_length++] = 0; /*Reserved*/ msg_data[input_length++] = 0; /*Reserved*/ req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; req.msg.cmd = GET_ACTIVE_NIC_CMD; req.msg.data = msg_data; req.msg.data_len = input_length; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error in getting Current LOM: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n", rv,decode_cc(0,rv)); return rv; } current_lom = rsp[0]; input_length = 0; msg_data[input_length++] = 1; //Get Link status msg_data[input_length++] = 0; //Reserved msg_data[input_length++] = 0; //Reserved req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; req.msg.cmd = GET_ACTIVE_NIC_CMD; req.msg.data = msg_data; req.msg.data_len = input_length; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error in getting Active LOM Status: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n", rv,decode_cc(0,rv)); return rv; } active_nic = rsp[1]; if (current_lom < 5 && active_nic) printf ("\n%s\n",ActiveLOM_String[current_lom]); else printf ("\n%s\n",ActiveLOM_String[5]); return 0; } static void ipmi_lan_usage(void) { lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " lan set "); lprintf(LOG_NOTICE, " sets the NIC Selection Mode :"); lprintf(LOG_NOTICE, " on iDRAC12g :"); lprintf(LOG_NOTICE, " dedicated, shared with lom1, shared with lom2,shared with lom3,shared "); lprintf(LOG_NOTICE, " with lom4,shared with failover lom1,shared with failover lom2,shared "); lprintf(LOG_NOTICE, " with failover lom3,shared with failoverlom4,shared with Failover all "); lprintf(LOG_NOTICE, " loms, shared with Failover None)."); lprintf(LOG_NOTICE, " on other systems :"); lprintf(LOG_NOTICE, " dedicated, shared, shared with failoverlom2,"); lprintf(LOG_NOTICE, " shared with Failover all loms."); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " lan get "); lprintf(LOG_NOTICE, " on iDRAC12g :"); lprintf(LOG_NOTICE, " returns the current NIC Selection Mode (dedicated, shared with lom1, shared "); lprintf(LOG_NOTICE, " with lom2, shared with lom3, shared with lom4,shared with failover lom1,"); lprintf(LOG_NOTICE, " shared with failover lom2,shared with failover lom3,shared with failover "); lprintf(LOG_NOTICE, " lom4,shared with Failover all loms,shared with Failover None)."); lprintf(LOG_NOTICE, " on other systems :"); lprintf(LOG_NOTICE, " dedicated, shared, shared with failover,"); lprintf(LOG_NOTICE, " lom2, shared with Failover all loms."); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " lan get active"); lprintf(LOG_NOTICE, " Get the current active LOMs (LOM1, LOM2, LOM3, LOM4, NONE)."); lprintf(LOG_NOTICE, ""); } /***************************************************************** * Function Name: ipmi_delloem_powermonitor_main * * Description: This function processes the delloem powermonitor command * Input: intf - ipmi interface argc - no of arguments argv - argument string array * Output: * * Return: return code 0 - success * -1 - failure * ******************************************************************/ static int ipmi_delloem_powermonitor_main (void * intf, int argc, char ** argv) { int rc = 0; current_arg++; if (argc > 1 && strcmp(argv[current_arg], "help") == 0) { ipmi_powermonitor_usage(); return 0; } ipmi_idracvalidator_command(intf); if (argc == 1) { rc = ipmi_powermgmt(intf); } else if (strncmp(argv[current_arg], "status\0", 7) == 0) { rc = ipmi_powermgmt(intf); } else if (strncmp(argv[current_arg], "clear\0", 6) == 0) { current_arg++; if (argv[current_arg] == NULL) { ipmi_powermonitor_usage(); return -1; } else if (strncmp(argv[current_arg], "peakpower\0", 10) == 0) { rc = ipmi_powermgmt_clear(intf, 1); } else if (strncmp(argv[current_arg], "cumulativepower\0", 16) == 0) { rc = ipmi_powermgmt_clear(intf, 0); } else { ipmi_powermonitor_usage(); return -1; } } else if (strncmp(argv[current_arg], "powerconsumption\0", 17) == 0) { current_arg++; if (argv[current_arg] == NULL) { rc=ipmi_print_get_power_consmpt_data(intf,watt); } else if (strncmp(argv[current_arg], "watt\0", 5) == 0) { rc = ipmi_print_get_power_consmpt_data(intf, watt); } else if (strncmp(argv[current_arg], "btuphr\0", 7) == 0) { rc = ipmi_print_get_power_consmpt_data(intf, btuphr); } else { ipmi_powermonitor_usage(); return -1; } } else if (strncmp(argv[current_arg], "powerconsumptionhistory\0", 23) == 0) { current_arg++; if (argv[current_arg] == NULL) { rc=ipmi_print_power_consmpt_history(intf,watt); } else if (strncmp(argv[current_arg], "watt\0", 5) == 0) { rc = ipmi_print_power_consmpt_history(intf, watt); } else if (strncmp(argv[current_arg], "btuphr\0", 7) == 0) { rc = ipmi_print_power_consmpt_history(intf, btuphr); } else { ipmi_powermonitor_usage(); return -1; } } else if (strncmp(argv[current_arg], "getpowerbudget\0", 15) == 0) { current_arg++; if (argv[current_arg] == NULL) { rc=ipmi_print_power_cap(intf,watt); } else if (strncmp(argv[current_arg], "watt\0", 5) == 0) { rc = ipmi_print_power_cap(intf, watt); } else if (strncmp(argv[current_arg], "btuphr\0", 7) == 0) { rc = ipmi_print_power_cap(intf, btuphr); } else { ipmi_powermonitor_usage(); return -1; } } else if (strncmp(argv[current_arg], "setpowerbudget\0", 15) == 0) { int val; current_arg++; if (argv[current_arg] == NULL) { ipmi_powermonitor_usage(); return -1; } if (strchr(argv[current_arg], '.')) { lprintf(LOG_ERR, " Cap value in Watts, Btu/hr or percent should be whole number"); return -1; } make_int(argv[current_arg],&val); current_arg++; if (argv[current_arg] == NULL) { ipmi_powermonitor_usage(); } else if (strncmp(argv[current_arg], "watt\0", 5) == 0) { rc=ipmi_set_power_cap(intf,watt,val); } else if (strncmp(argv[current_arg], "btuphr\0", 7) == 0) { rc=ipmi_set_power_cap(intf, btuphr,val); } else if (strncmp(argv[current_arg], "percent\0", 8) == 0) { rc=ipmi_set_power_cap(intf,percent,val); } else { ipmi_powermonitor_usage(); return -1; } } else if (strncmp(argv[current_arg], "enablepowercap\0", 15) == 0) { rc = ipmi_set_power_capstatus_command(intf,1); } else if (strncmp(argv[current_arg], "disablepowercap\0", 16) == 0) { rc = ipmi_set_power_capstatus_command(intf,0); } else { ipmi_powermonitor_usage(); return -1; } if (sdrcache != NULL) free_sdr_cache(sdrcache); return(rc); } /***************************************************************** * Function Name: ipmi_time_to_str * * Description: This function converts ipmi time format into gmtime format * Input: rawTime - ipmi time format * Output: strTime - gmtime format * * Return: * ******************************************************************/ static void ipmi_time_to_str(time_t rawTime, char* strTime) { struct tm * tm; char *temp; tm = gmtime(&rawTime); temp = asctime(tm); strcpy(strTime,temp); } #ifdef NOT_USED static int ipmi_get_sensor_reading(void *intf , unsigned char sensorNumber, SensorReadingType* pSensorReadingData); /***************************************************************** * Function Name: ipmi_get_sensor_reading * * Description: This function retrieves a raw sensor reading * Input: sensorOwner - sensor owner id * sensorNumber - sensor id * intf - ipmi interface * Output: sensorReadingData - ipmi response structure * Return: 1 on error * 0 if successful * ******************************************************************/ static int ipmi_get_sensor_reading(void *intf , unsigned char sensorNumber, SensorReadingType* pSensorReadingData) { struct ipmi_rq req; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len; int rc = 0; // uint8_t save_addr; memset(&req, 0, sizeof (req)); req.msg.netfn = IPMI_NETFN_SE; req.msg.lun = 0; req.msg.cmd = (uint8_t)(GET_SENSOR_READING | 0x0ff); req.msg.data = &sensorNumber; req.msg.data_len = 1; if (NULL == pSensorReadingData) return -1; memset(pSensorReadingData,0, sizeof(SensorReadingType)); rc = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rc) return 1; memcpy(pSensorReadingData, rsp, sizeof(SensorReadingType)); /* if sensor messages are disabled, return error*/ if ((!(rsp[1]& 0xC0)) || ((rsp[1] & 0x20))) { rc =1; } return rc; } #endif /***************************************************************** * Function Name: ipmi_get_power_capstatus_command * * Description: This function gets the power cap status * Input: intf - ipmi interface * Global: PowercapSetable_flag - power cap status * Output: * * Return: * ******************************************************************/ static int ipmi_get_power_capstatus_command (void * intf) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[2]; req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; req.msg.cmd = IPMI_DELL_POWER_CAP_STATUS; req.msg.data_len = 2; req.msg.data = data; data[0] = 01; data[1] = 0xFF; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error getting powercap status: "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n", rv,decode_cc(0,rv)); return rv; } if (rsp[0]&0x02) PowercapSetable_flag=1; if(rsp[0]&0x01) PowercapstatusFlag=1; return 0; } /***************************************************************** * Function Name: ipmi_set_power_capstatus_command * * Description: This function sets the power cap status * Input: intf - ipmi interface * val - power cap status * Output: * * Return: * ******************************************************************/ static int ipmi_set_power_capstatus_command (void * intf,uint8_t val) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[2]; if(ipmi_get_power_capstatus_command(intf) < 0) return -1; if (PowercapSetable_flag!=1) { lprintf(LOG_ERR, " Can not set powercap on this system"); return -1; } req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; req.msg.cmd = IPMI_DELL_POWER_CAP_STATUS; req.msg.data_len = 2; req.msg.data = data; data[0] = 00; data[1] = val; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error setting powercap status: "); if (rv < 0) printf("no response\n"); else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) { printf("FM001 : A required license is missing or expired\n"); return rv; //return unlicensed Error code } else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } return 0; } /***************************************************************** * Function Name: ipmi_powermgmt * * Description: This function print the powermonitor details * Input: intf - ipmi interface * Output: * * Return: * ******************************************************************/ static int ipmi_powermgmt(void* intf) { time_t now; struct tm* tm; char* dte; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t msg_data[2]; uint32_t cumStartTimeConv; uint32_t cumReadingConv; uint32_t maxPeakStartTimeConv; uint32_t ampPeakTimeConv; uint16_t ampReadingConv; uint32_t wattPeakTimeConv; uint32_t wattReadingConv; uint32_t bmctimeconv; uint32_t * bmctimeconvval; IPMI_POWER_MONITOR* pwrMonitorInfo; char cumStartTime[26]; char maxPeakStartTime[26]; char ampPeakTime[26]; char wattPeakTime[26]; char bmctime[26]; // float cumReading; int ampReading; int wattReading; int ampReadingRemainder; // int round; // int round2; int remainder; now = time(0); tm = gmtime(&now); dte = asctime(tm); memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_STORAGE; req.msg.lun = 0; req.msg.cmd = IPMI_CMD_GET_SEL_TIME; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error getting BMC time info "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } bmctimeconvval=(uint32_t*)rsp; #if WORDS_BIGENDIAN bmctimeconv=BSWAP_32(*bmctimeconvval); #else bmctimeconv=*bmctimeconvval; #endif /* get powermanagement info*/ req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0x0; req.msg.cmd = GET_PWRMGMT_INFO_CMD; req.msg.data = msg_data; req.msg.data_len = 2; memset(msg_data, 0, 2); msg_data[0] = 0x07; msg_data[1] = 0x01; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error getting power management info "); if (rv < 0) printf("no response\n"); else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) { printf("FM001 : A required license is missing or expired\n"); return rv; } else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } pwrMonitorInfo = (IPMI_POWER_MONITOR*)rsp; #if WORDS_BIGENDIAN cumStartTimeConv = BSWAP_32(pwrMonitorInfo->cumStartTime); cumReadingConv = BSWAP_32(pwrMonitorInfo->cumReading); maxPeakStartTimeConv = BSWAP_32(pwrMonitorInfo->maxPeakStartTime); ampPeakTimeConv = BSWAP_32(pwrMonitorInfo->ampPeakTime); ampReadingConv = BSWAP_16(pwrMonitorInfo->ampReading); wattPeakTimeConv = BSWAP_32(pwrMonitorInfo->wattPeakTime); wattReadingConv = BSWAP_16(pwrMonitorInfo->wattReading); #else cumStartTimeConv = pwrMonitorInfo->cumStartTime; cumReadingConv = pwrMonitorInfo->cumReading; maxPeakStartTimeConv = pwrMonitorInfo->maxPeakStartTime; ampPeakTimeConv = pwrMonitorInfo->ampPeakTime; ampReadingConv = pwrMonitorInfo->ampReading; wattPeakTimeConv = pwrMonitorInfo->wattPeakTime; wattReadingConv = pwrMonitorInfo->wattReading; #endif ipmi_time_to_str(cumStartTimeConv, cumStartTime); ipmi_time_to_str(maxPeakStartTimeConv, maxPeakStartTime); ipmi_time_to_str(ampPeakTimeConv, ampPeakTime); ipmi_time_to_str(wattPeakTimeConv, wattPeakTime); ipmi_time_to_str(bmctimeconv, bmctime); now = time(0); remainder = (cumReadingConv % 1000); cumReadingConv = cumReadingConv / 1000; remainder = (remainder + 50) / 100; ampReading = ampReadingConv; ampReadingRemainder = ampReading%10; ampReading = ampReading/10; wattReading = wattReadingConv; printf("Power Tracking Statistics\n"); printf("Statistic : Cumulative Energy Consumption\n"); printf("Start Time : %s", cumStartTime); printf("Finish Time : %s", bmctime); printf("Reading : %d.%d kWh\n\n", cumReadingConv, remainder); printf("Statistic : System Peak Power\n"); printf("Start Time : %s", maxPeakStartTime); printf("Peak Time : %s", wattPeakTime); printf("Peak Reading : %d W\n\n", wattReading); printf("Statistic : System Peak Amperage\n"); printf("Start Time : %s", maxPeakStartTime); printf("Peak Time : %s", ampPeakTime); printf("Peak Reading : %d.%d A\n", ampReading, ampReadingRemainder); return 0; } /***************************************************************** * Function Name: ipmi_powermgmt_clear * * Description: This function clears peakpower / cumulativepower value * Input: intf - ipmi interface * clearValue - peakpower / cumulativepower * Output: * * Return: * ******************************************************************/ static int ipmi_powermgmt_clear(void* intf,uint8_t clearValue) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t clearType; uint8_t msg_data[3]; if (clearValue) { clearType = 2; } else { clearType = 1; } /* clear powermanagement info*/ req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; req.msg.cmd = CLEAR_PWRMGMT_INFO_CMD; req.msg.data = msg_data; req.msg.data_len = 3; memset(msg_data, 0, 3); msg_data[0] = 0x07; msg_data[1] = 0x01; msg_data[2] = clearType; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error clearing power values: "); if (rv < 0) printf("no response\n"); else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) { printf("FM001 : A required license is missing or expired\n"); return rv; } else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } return 0; } /***************************************************************** * Function Name: watt_to_btuphr_conversion * * Description: This function converts the power value in watt to btuphr * Input: powerinwatt - power in watt * * Output: power in btuphr * * Return: * ******************************************************************/ static uint64_t watt_to_btuphr_conversion(uint32_t powerinwatt) { uint64_t powerinbtuphr; powerinbtuphr=(uint64_t)(3.413*powerinwatt); return(powerinbtuphr); } /***************************************************************** * Function Name: btuphr_to_watt_conversion * * Description: This function converts the power value in btuphr to watt * Input: powerinbtuphr - power in btuphr * * Output: power in watt * * Return: * ******************************************************************/ static uint32_t btuphr_to_watt_conversion(uint64_t powerinbtuphr) { uint32_t powerinwatt; /*returning the floor value*/ powerinwatt= (uint32_t)(powerinbtuphr/3.413); return (powerinwatt); } /***************************************************************** * Function Name: ipmi_get_power_headroom_command * * Description: This function prints the Power consumption information * Input: intf - ipmi interface * unit - watt / btuphr * Output: * * Return: * ******************************************************************/ static int ipmi_get_power_headroom_command (void * intf,uint8_t unit) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint64_t peakpowerheadroombtuphr; uint64_t instantpowerhearoom; req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; req.msg.cmd = GET_PWR_HEADROOM_CMD; req.msg.data_len = 0; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error getting power headroom status: "); if (rv < 0) printf("no response\n"); else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) { printf("FM001 : A required license is missing or expired\n"); return rv; } else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } if(verbose>1) printf("power headroom Data : %x %x %x %x ", /*need to look into */ rsp[0], rsp[1], rsp[2], rsp[3]); powerheadroom= *(( POWER_HEADROOM *)rsp); #if WORDS_BIGENDIAN powerheadroom.instheadroom = BSWAP_16(powerheadroom.instheadroom); powerheadroom.peakheadroom = BSWAP_16(powerheadroom.peakheadroom); #endif printf ("Headroom\n\r"); printf ("Statistic Reading\n\r"); if(unit == btuphr) { peakpowerheadroombtuphr=watt_to_btuphr_conversion(powerheadroom.peakheadroom); instantpowerhearoom= watt_to_btuphr_conversion(powerheadroom.instheadroom); printf ("System Instantaneous Headroom : %ld BTU/hr\n",instantpowerhearoom); printf ("System Peak Headroom : %ld BTU/hr\n",peakpowerheadroombtuphr); } else { printf ("System Instantaneous Headroom : %d W\n",powerheadroom.instheadroom); printf ("System Peak Headroom : %d W\n",powerheadroom.peakheadroom); } return 0; } /***************************************************************** * Function Name: ipmi_get_power_consumption_data * * Description: This function updates the instant Power consumption information * Input: intf - ipmi interface * Output: power consumption current reading * Assumption value will be in Watt. * * Return: * ******************************************************************/ static int ipmi_get_power_consumption_data(void* intf,uint8_t unit) { int rc = 0; SensorReadingType sensorReadingData; uint8_t rsp[IPMI_RSPBUF_SIZE]; struct sdr_record_list *sdr = NULL; uchar sdrbuf[SDR_SZ]; double readingf, warningf, failuref; int readingbtuphr=0; int warning_threshbtuphr=0; int failure_thresbtuphr=0; int status=0; int sensor_number = 0; if (sdrfile != NULL) { rc = get_sdr_file(sdrfile,&sdrcache); if (rc) printf ("Error 0x%02x: Cannot get SDRs from %s\n",rc,sdrfile); } else if (sdrcache == NULL) { rc = get_sdr_cache(&sdrcache); if (rc) printf ("Error 0x%02x: Cannot get SDRs\n",rc); } rc = find_sdr_by_tag(sdrbuf, sdrcache, "System Level", fdebug); if (rc != 0) { printf ("Error %d: Cannot access the System Level sensor data\n",rc); return rc; } sdr = (struct sdr_record_list *)sdrbuf; sensor_number = sdrbuf[7]; // sdr->record.full->keys.sensor_num; if (fdebug) printf("calling GetSensorReading(%x)\n",sensor_number); rc = GetSensorReading(sensor_number, sdrbuf, (uchar *)&sensorReadingData.sensorReading); if (rc != 0) printf("Error %d getting sensor %x reading\n",rc,sensor_number); rc = GetSensorThresholds( sensor_number, rsp); if (fdebug) printf("GetSensorThresholds(%x) rc = %d\n",sensor_number,rc); if (rc == 0) { readingf = RawToFloat(sensorReadingData.sensorReading,sdrbuf); warningf = RawToFloat(rsp[4], sdrbuf); failuref = RawToFloat(rsp[5], sdrbuf); readingbtuphr = (int)readingf; warning_threshbtuphr = (int)warningf; failure_thresbtuphr = (int)failuref; if (fdebug) { printf("Reading 0x%02x = %.2f, Warning 0x%02x = %.2f, Failure 0x%02x = %.2f\n", sensorReadingData.sensorReading, readingf, rsp[4], warningf, rsp[5], failuref); } printf ("System Board System Level\n\r"); if (unit==btuphr) { readingbtuphr= watt_to_btuphr_conversion(readingbtuphr); warning_threshbtuphr= watt_to_btuphr_conversion(warning_threshbtuphr); failure_thresbtuphr= watt_to_btuphr_conversion( failure_thresbtuphr); printf ("Reading : %d BTU/hr\n",readingbtuphr); printf ("Warning threshold : %d BTU/hr\n",warning_threshbtuphr); printf ("Failure threshold : %d BTU/hr\n",failure_thresbtuphr); } else { printf ("Reading : %d W \n",readingbtuphr); printf ("Warning threshold : %d W \n",(warning_threshbtuphr)); printf ("Failure threshold : %d W \n",(failure_thresbtuphr)); } } else { printf ("Error %d: Cannot access the System Level threshold data\n",rc); return -1; } return status; } /***************************************************************** * Function Name: ipmi_get_instan_power_consmpt_data * * Description: This function updates the instant Power consumption information * Input: intf - ipmi interface * Output: instpowerconsumptiondata - instant Power consumption information * * Return: * ******************************************************************/ static int ipmi_get_instan_power_consmpt_data(void* intf, IPMI_INST_POWER_CONSUMPTION_DATA* instpowerconsumptiondata) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t msg_data[2]; /*get instantaneous power consumption command*/ req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; req.msg.cmd = GET_PWR_CONSUMPTION_CMD; req.msg.data = msg_data; req.msg.data_len = 2; memset(msg_data, 0, 2); msg_data[0] = 0x0A; msg_data[1] = 0x00; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error getting power consumption data: "); if (rv < 0) printf("no response\n"); else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) { printf("FM001 : A required license is missing or expired\n"); return rv; } else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } * instpowerconsumptiondata = * ( (IPMI_INST_POWER_CONSUMPTION_DATA*) (rsp)); #if WORDS_BIGENDIAN instpowerconsumptiondata->instanpowerconsumption = BSWAP_16(instpowerconsumptiondata->instanpowerconsumption); instpowerconsumptiondata->instanApms = BSWAP_16(instpowerconsumptiondata->instanApms); instpowerconsumptiondata->resv1 = BSWAP_16(instpowerconsumptiondata->resv1); #endif return 0; } /***************************************************************** * Function Name: ipmi_print_get_instan_power_Amps_data * * Description: This function prints the instant Power consumption information * Input: instpowerconsumptiondata - instant Power consumption information * Output: * * Return: * ******************************************************************/ static void ipmi_print_get_instan_power_Amps_data(IPMI_INST_POWER_CONSUMPTION_DATA instpowerconsumptiondata) { uint16_t intampsval=0; uint16_t decimalampsval=0; if (instpowerconsumptiondata.instanApms>0) { decimalampsval=(instpowerconsumptiondata.instanApms%10); intampsval=instpowerconsumptiondata.instanApms/10; } printf("\nAmperage value: %d.%d A \n",intampsval,decimalampsval); } /***************************************************************** * Function Name: ipmi_print_get_power_consmpt_data * * Description: This function prints the Power consumption information * Input: intf - ipmi interface * unit - watt / btuphr * Output: * * Return: * ******************************************************************/ static int ipmi_print_get_power_consmpt_data(void* intf,uint8_t unit) { int rc = 0; IPMI_INST_POWER_CONSUMPTION_DATA instpowerconsumptiondata = {0,0,0,0}; // int i; //uint16_t inputwattageL=0; //int sensorIndex = 0; //uint32_t readingbtuphr; //uint32_t warning_threshbtuphr; //uint32_t failure_thresbtuphr; printf ("\nPower consumption information\n"); rc=ipmi_get_power_consumption_data(intf,unit); if (-1 == rc) return rc; rc=ipmi_get_instan_power_consmpt_data(intf,&instpowerconsumptiondata); if (-1 == rc) return rc; ipmi_print_get_instan_power_Amps_data(instpowerconsumptiondata); rc=ipmi_get_power_headroom_command(intf,unit); if (-1 == rc) return rc; return rc; } /***************************************************************** * Function Name: ipmi_get_avgpower_consmpt_history * * Description: This function updates the average power consumption information * Input: intf - ipmi interface * Output: pavgpower- average power consumption information * * Return: * ******************************************************************/ static int ipmi_get_avgpower_consmpt_history(void* intf,IPMI_AVGPOWER_CONSUMP_HISTORY* pavgpower ) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[4]; req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_GET_SYS_INFO; req.msg.data_len = 4; req.msg.data = data; data[0] = 0; data[1] = 0xeb; data[2] = 0; data[3] = 0; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error getting average power consumption data: "); if (rv < 0) printf("no response\n"); else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) { printf("FM001 : A required license is missing or expired\n"); return rv; } else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } if (verbose > 1) { printf("Average power consumption history Data :%x %x %x %x %x %x %x %x\n\n", rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5], rsp[6], rsp[7]); } *pavgpower = *( (IPMI_AVGPOWER_CONSUMP_HISTORY*) rsp); #if WORDS_BIGENDIAN pavgpower->lastminutepower = BSWAP_16(pavgpower->lastminutepower); pavgpower->lasthourpower = BSWAP_16(pavgpower->lasthourpower); pavgpower->lastdaypower = BSWAP_16(pavgpower->lastdaypower); pavgpower->lastweakpower = BSWAP_16(pavgpower->lastweakpower); #endif return 0; } /***************************************************************** * Function Name: ipmi_get_peakpower_consmpt_history * * Description: This function updates the peak power consumption information * Input: intf - ipmi interface * Output: pavgpower- peak power consumption information * * Return: * ******************************************************************/ static int ipmi_get_peakpower_consmpt_history(void* intf,IPMI_POWER_CONSUMP_HISTORY * pstPeakpower) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[4]; req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_GET_SYS_INFO; req.msg.data_len = 4; req.msg.data = data; data[0] = 0; data[1] = 0xec; data[2] = 0; data[3] = 0; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error getting peak power consumption history: "); if (rv < 0) printf("no response\n"); else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) { printf("FM001 : A required license is missing or expired\n"); return rv; } else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } if (verbose > 1) { printf("Peak power consmhistory Data : %x %x %x %x %x %x %x %x %x %x\n %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n\n", rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5], rsp[6], rsp[7], rsp[8], rsp[9], rsp[10], rsp[11], rsp[12], rsp[13], rsp[14], rsp[15], rsp[16], rsp[17], rsp[18], rsp[19], rsp[20], rsp[21], rsp[22], rsp[23] ); } *pstPeakpower =* ((IPMI_POWER_CONSUMP_HISTORY*)rsp); #if WORDS_BIGENDIAN pstPeakpower->lastminutepower = BSWAP_16(pstPeakpower->lastminutepower); pstPeakpower->lasthourpower = BSWAP_16(pstPeakpower->lasthourpower); pstPeakpower->lastdaypower = BSWAP_16(pstPeakpower->lastdaypower); pstPeakpower->lastweakpower = BSWAP_16(pstPeakpower->lastweakpower); pstPeakpower->lastminutepowertime = BSWAP_32(pstPeakpower->lastminutepowertime); pstPeakpower->lasthourpowertime = BSWAP_32(pstPeakpower->lasthourpowertime); pstPeakpower->lastdaypowertime = BSWAP_32(pstPeakpower->lastdaypowertime); pstPeakpower->lastweekpowertime = BSWAP_32(pstPeakpower->lastweekpowertime); #endif return 0; } /***************************************************************** * Function Name: ipmi_get_minpower_consmpt_history * * Description: This function updates the peak power consumption information * Input: intf - ipmi interface * Output: pavgpower- peak power consumption information * * Return: * ******************************************************************/ static int ipmi_get_minpower_consmpt_history(void* intf,IPMI_POWER_CONSUMP_HISTORY * pstMinpower) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[4]; req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_GET_SYS_INFO; req.msg.data_len = 4; req.msg.data = data; data[0] = 0; data[1] = 0xed; data[2] = 0; data[3] = 0; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error getting min power consumption history: "); if (rv < 0) printf("no response\n"); else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) { printf("FM001 : A required license is missing or expired\n"); return rv; } else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } if (verbose > 1) { printf("Peak power consmhistory Data : %x %x %x %x %x %x %x %x %x %x\n %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n\n", rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5], rsp[6], rsp[7], rsp[8], rsp[9], rsp[10], rsp[11], rsp[12], rsp[13], rsp[14], rsp[15], rsp[16], rsp[17], rsp[18], rsp[19], rsp[20], rsp[21], rsp[22], rsp[23] ); } *pstMinpower =* ((IPMI_POWER_CONSUMP_HISTORY*)rsp); #if WORDS_BIGENDIAN pstMinpower->lastminutepower = BSWAP_16(pstMinpower->lastminutepower); pstMinpower->lasthourpower = BSWAP_16(pstMinpower->lasthourpower); pstMinpower->lastdaypower = BSWAP_16(pstMinpower->lastdaypower); pstMinpower->lastweakpower = BSWAP_16(pstMinpower->lastweakpower); pstMinpower->lastminutepowertime = BSWAP_32(pstMinpower->lastminutepowertime); pstMinpower->lasthourpowertime = BSWAP_32(pstMinpower->lasthourpowertime); pstMinpower->lastdaypowertime = BSWAP_32(pstMinpower->lastdaypowertime); pstMinpower->lastweekpowertime = BSWAP_32(pstMinpower->lastweekpowertime); #endif return 0; } /***************************************************************** * Function Name: ipmi_print_power_consmpt_history * * Description: This function print the average and peak power consumption information * Input: intf - ipmi interface * unit - watt / btuphr * Output: * * Return: * ******************************************************************/ static int ipmi_print_power_consmpt_history(void* intf,int unit ) { char timestr[30]; uint32_t lastminutepeakpower; uint32_t lasthourpeakpower; uint32_t lastdaypeakpower; uint32_t lastweekpeakpower; IPMI_AVGPOWER_CONSUMP_HISTORY avgpower; IPMI_POWER_CONSUMP_HISTORY stMinpower; IPMI_POWER_CONSUMP_HISTORY stPeakpower; int rc=0; uint64_t tempbtuphrconv; //uint16_t temp; rc= ipmi_get_avgpower_consmpt_history(intf,&avgpower); if (-1 == rc) return rc; rc= ipmi_get_peakpower_consmpt_history(intf,&stPeakpower); if (-1 == rc) return rc; rc= ipmi_get_minpower_consmpt_history(intf,&stMinpower); if (-1 == rc) return rc; if(rc==0) { printf ("Power Consumption History\n\r\n\r"); /* The fields are alligned manually changing the spaces will alter the alignment*/ printf ("Statistic Last Minute Last Hour Last Day Last Week\n\r\n\r"); if (unit ==btuphr) { printf ("Average Power Consumption "); tempbtuphrconv=watt_to_btuphr_conversion(avgpower.lastminutepower); printf ("%4d BTU/hr ",tempbtuphrconv); tempbtuphrconv=watt_to_btuphr_conversion(avgpower.lasthourpower); printf ("%4d BTU/hr ",tempbtuphrconv); tempbtuphrconv=watt_to_btuphr_conversion(avgpower.lastdaypower); printf ("%4d BTU/hr ",tempbtuphrconv); tempbtuphrconv=watt_to_btuphr_conversion(avgpower.lastweakpower); printf ("%4d BTU/hr\n\r",tempbtuphrconv); printf ("Max Power Consumption "); tempbtuphrconv=watt_to_btuphr_conversion(stPeakpower.lastminutepower); printf ("%4d BTU/hr ",tempbtuphrconv); tempbtuphrconv=watt_to_btuphr_conversion(stPeakpower.lasthourpower); printf ("%4d BTU/hr ",tempbtuphrconv); tempbtuphrconv=watt_to_btuphr_conversion(stPeakpower.lastdaypower); printf ("%4d BTU/hr ",tempbtuphrconv); tempbtuphrconv=watt_to_btuphr_conversion(stPeakpower.lastweakpower); printf ("%4d BTU/hr\n\r",tempbtuphrconv); printf ("Min Power Consumption "); tempbtuphrconv=watt_to_btuphr_conversion(stMinpower.lastminutepower); printf ("%4d BTU/hr ",tempbtuphrconv); tempbtuphrconv=watt_to_btuphr_conversion(stMinpower.lasthourpower); printf ("%4d BTU/hr ",tempbtuphrconv); tempbtuphrconv=watt_to_btuphr_conversion(stMinpower.lastdaypower); printf ("%4d BTU/hr ",tempbtuphrconv); tempbtuphrconv=watt_to_btuphr_conversion(stMinpower.lastweakpower); printf ("%4d BTU/hr\n\r\n\r",tempbtuphrconv); } else { printf ("Average Power Consumption "); tempbtuphrconv=(avgpower.lastminutepower); printf ("%4ld W ",tempbtuphrconv); tempbtuphrconv=(avgpower.lasthourpower); printf ("%4ld W ",tempbtuphrconv); tempbtuphrconv=(avgpower.lastdaypower); printf ("%4ld W ",tempbtuphrconv); tempbtuphrconv=(avgpower.lastweakpower); printf ("%4ld W \n\r",tempbtuphrconv); printf ("Max Power Consumption "); tempbtuphrconv=(stPeakpower.lastminutepower); printf ("%4ld W ",tempbtuphrconv); tempbtuphrconv=(stPeakpower.lasthourpower); printf ("%4ld W ",tempbtuphrconv); tempbtuphrconv=(stPeakpower.lastdaypower); printf ("%4ld W ",tempbtuphrconv); tempbtuphrconv=(stPeakpower.lastweakpower); printf ("%4ld W \n\r",tempbtuphrconv); printf ("Min Power Consumption "); tempbtuphrconv=(stMinpower.lastminutepower); printf ("%4ld W ",tempbtuphrconv); tempbtuphrconv=(stMinpower.lasthourpower); printf ("%4ld W ",tempbtuphrconv); tempbtuphrconv=(stMinpower.lastdaypower); printf ("%4ld W ",tempbtuphrconv); tempbtuphrconv=(stMinpower.lastweakpower); printf ("%4ld W \n\r\n\r",tempbtuphrconv); } lastminutepeakpower=stPeakpower.lastminutepowertime; lasthourpeakpower=stPeakpower.lasthourpowertime; lastdaypeakpower=stPeakpower.lastdaypowertime; lastweekpeakpower=stPeakpower.lastweekpowertime; printf ("Max Power Time\n\r"); ipmi_time_to_str(lastminutepeakpower, timestr); printf ("Last Minute : %s",timestr); ipmi_time_to_str(lasthourpeakpower, timestr); printf ("Last Hour : %s",timestr); ipmi_time_to_str(lastdaypeakpower, timestr); printf ("Last Day : %s",timestr); ipmi_time_to_str(lastweekpeakpower, timestr); printf ("Last Week : %s",timestr); lastminutepeakpower=stMinpower.lastminutepowertime; lasthourpeakpower=stMinpower.lasthourpowertime; lastdaypeakpower=stMinpower.lastdaypowertime; lastweekpeakpower=stMinpower.lastweekpowertime; printf ("Min Power Time\n\r"); ipmi_time_to_str(lastminutepeakpower, timestr); printf ("Last Minute : %s",timestr); ipmi_time_to_str(lasthourpeakpower, timestr); printf ("Last Hour : %s",timestr); ipmi_time_to_str(lastdaypeakpower, timestr); printf ("Last Day : %s",timestr); ipmi_time_to_str(lastweekpeakpower, timestr); printf ("Last Week : %s",timestr); } return rc; } /***************************************************************** * Function Name: ipmi_get_power_cap * * Description: This function updates the power cap information * Input: intf - ipmi interface * Output: ipmipowercap - power cap information * * Return: * ******************************************************************/ static int ipmi_get_power_cap(void* intf,IPMI_POWER_CAP* ipmipowercap ) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; //uint64_t tempbtuphrconv; uint8_t data[4]; /* power supply rating command*/ req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_GET_SYS_INFO; req.msg.data_len = 4; req.msg.data = data; data[0] = 0; data[1] = IPMI_DELL_POWER_CAP; data[2] = 0; data[3] = 0; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error getting power cap: "); if (rv < 0) printf("no response\n"); else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) { printf("FM001 : A required license is missing or expired\n"); return rv; } else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } if (verbose > 1){ printf("power cap Data :%x %x %x %x %x %x %x %x %x %x %x", rsp[1], rsp[2], rsp[3], rsp[4], rsp[5], rsp[6], rsp[7], rsp[8], rsp[9], rsp[10],rsp[11]); } * ipmipowercap = *((IPMI_POWER_CAP*)(rsp)); #if WORDS_BIGENDIAN ipmipowercap->PowerCap = BSWAP_16(ipmipowercap->PowerCap); ipmipowercap->MaximumPowerConsmp = BSWAP_16(ipmipowercap->MaximumPowerConsmp); ipmipowercap->MinimumPowerConsmp = BSWAP_16(ipmipowercap->MinimumPowerConsmp); ipmipowercap->totalnumpowersupp = BSWAP_16(ipmipowercap->totalnumpowersupp); ipmipowercap->AvailablePower = BSWAP_16(ipmipowercap->AvailablePower); ipmipowercap->SystemThrottling = BSWAP_16(ipmipowercap->SystemThrottling); ipmipowercap->Resv = BSWAP_16(ipmipowercap->Resv); #endif return 0; } /***************************************************************** * Function Name: ipmi_print_power_cap * * Description: This function print the power cap information * Input: intf - ipmi interface * unit - watt / btuphr * Output: * Return: * ******************************************************************/ static int ipmi_print_power_cap(void* intf,uint8_t unit ) { uint64_t tempbtuphrconv; int rc; IPMI_POWER_CAP ipmipowercap; memset(&ipmipowercap,0,sizeof(ipmipowercap)); rc=ipmi_get_power_cap(intf,&ipmipowercap); if (rc==0) { if (unit ==btuphr){ tempbtuphrconv=watt_to_btuphr_conversion(ipmipowercap.MaximumPowerConsmp); printf ("Maximum power: %ld BTU/hr\n",tempbtuphrconv); tempbtuphrconv=watt_to_btuphr_conversion(ipmipowercap.MinimumPowerConsmp); printf ("Minimum power: %ld BTU/hr\n",tempbtuphrconv); tempbtuphrconv=watt_to_btuphr_conversion(ipmipowercap.PowerCap); printf ("Power cap : %ld BTU/hr\n",tempbtuphrconv); }else{ printf ("Maximum power: %d Watt\n",ipmipowercap.MaximumPowerConsmp); printf ("Minimum power: %d Watt\n",ipmipowercap.MinimumPowerConsmp); printf ("Power cap : %d Watt\n",ipmipowercap.PowerCap); } } return rc; } /***************************************************************** * Function Name: ipmi_set_power_cap * * Description: This function updates the power cap information * Input: intf - ipmi interface * unit - watt / btuphr * val - new power cap value * Output: * Return: * ******************************************************************/ static int ipmi_set_power_cap(void* intf,int unit,int val ) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[13]; uint16_t powercapval; uint64_t maxpowerbtuphr; uint64_t maxpowerbtuphr1; uint64_t minpowerbtuphr; IPMI_POWER_CAP ipmipowercap; if(ipmi_get_power_capstatus_command(intf) < 0) return -1; // Adding the failed condition check if (PowercapSetable_flag!=1) { lprintf(LOG_ERR, " Can not set powercap on this system"); return -1; } else if(PowercapstatusFlag!=1) { lprintf(LOG_ERR, " Power cap set feature is not enabled"); return -1; } req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_GET_SYS_INFO; req.msg.data_len = 4; memset(data, 0, 4); req.msg.data = data; data[0] = 0; data[1] = IPMI_DELL_POWER_CAP; data[2] = 0; data[3] = 0; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error getting power cap: "); if (rv < 0) printf("no response\n"); else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) { printf("FM001 : A required license is missing or expired\n"); return rv; } else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } if (verbose > 1) { printf("power cap Data :%x %x %x %x %x %x %x %x %x %x %x", rsp[1], rsp[2], rsp[3], rsp[4], rsp[5], rsp[6], rsp[7], rsp[8], rsp[9], rsp[10],rsp[11]); } ipmipowercap.PowerCap=((rsp[1]<<8)+rsp[2]); ipmipowercap.unit=rsp[3]; ipmipowercap.MaximumPowerConsmp=((rsp[4]<<8)+rsp[5]); ipmipowercap.MinimumPowerConsmp=((rsp[6]<<8)+rsp[7]); /* ARC: need Dell to verify these 3 values */ ipmipowercap.totalnumpowersupp = rsp[8]; ipmipowercap.AvailablePower = ((rsp[9]<<8)+rsp[10]); ipmipowercap.SystemThrottling = rsp[11]; memset(data, 0, 13); req.msg.netfn = IPMI_NETFN_APP; req.msg.lun = 0; req.msg.cmd = IPMI_SET_SYS_INFO; req.msg.data_len = 13; req.msg.data = data; data[0] = IPMI_DELL_POWER_CAP; powercapval=val; data[1] = (powercapval&0XFF); data[2] = ((powercapval&0XFF00)>>8); data[3] = unit; data[4]=((ipmipowercap.MaximumPowerConsmp&0xFF)); data[5]=((ipmipowercap.MaximumPowerConsmp&0xFF00)>>8); data[6]=((ipmipowercap.MinimumPowerConsmp&0xFF)); data[7]=((ipmipowercap.MinimumPowerConsmp&0xFF00)>>8); data[8]=(uint8_t)(ipmipowercap.totalnumpowersupp); data[9]=((ipmipowercap.AvailablePower&0xFF)); data[10]=((ipmipowercap.AvailablePower&0xFF00)>>8); data[11]=(uint8_t)(ipmipowercap.SystemThrottling); data[12]=0x00; ipmipowercap.MaximumPowerConsmp = BSWAP_16(ipmipowercap.MaximumPowerConsmp); ipmipowercap.MinimumPowerConsmp = BSWAP_16(ipmipowercap.MinimumPowerConsmp); ipmipowercap.PowerCap = BSWAP_16(ipmipowercap.PowerCap); if(unit==btuphr) { val = btuphr_to_watt_conversion(val); } else if(unit ==percent) { if((val <0)||(val>100)) { lprintf(LOG_ERR, " Cap value is out of boundary conditon it should be between 0 - 100"); return -1; } val =( (val*(ipmipowercap.MaximumPowerConsmp -ipmipowercap.MinimumPowerConsmp))/100)+ipmipowercap.MinimumPowerConsmp; lprintf(LOG_ERR, " Cap value in percentage is %d ",val); data[1] = (val&0XFF); data[2] = ((val&0XFF00)>>8); data[3] = watt; } if(((valipmipowercap.MaximumPowerConsmp))&&(unit==watt)) { lprintf(LOG_ERR, " Cap value is out of boundary conditon it should be between %d - %d", ipmipowercap.MinimumPowerConsmp,ipmipowercap.MaximumPowerConsmp); return -1; } else if(((valipmipowercap.MaximumPowerConsmp))&&(unit==btuphr)) { minpowerbtuphr= watt_to_btuphr_conversion(ipmipowercap.MinimumPowerConsmp); maxpowerbtuphr=watt_to_btuphr_conversion(ipmipowercap.MaximumPowerConsmp); maxpowerbtuphr1= watt_to_btuphr_conversion(ipmipowercap.MaximumPowerConsmp); lprintf(LOG_ERR, " Cap value is out of boundary conditon it should be between %d", minpowerbtuphr); lprintf(LOG_ERR, " -%d", maxpowerbtuphr1); return -1; } rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error setting power cap: "); if (rv < 0) printf("no response\n"); else if((iDRAC_FLAG == IDRAC_12G) && (rv == LICENSE_NOT_SUPPORTED)) { printf("FM001 : A required license is missing or expired\n"); return rv; } else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } if (verbose > 1) { printf("CC for setpowercap :%d ",rv); } return 0; } #ifdef NOT_USED static int getpowersupplyfruinfo(void *intf, uint8_t id, struct fru_header header, struct fru_info fru); /***************************************************************** * Function Name: getpowersupplyfruinfo * * Description: This function retrieves the FRU header * Input: intf - ipmi interface * header - watt / btuphr * fru - FRU information * Output: header - FRU header * Return: * ******************************************************************/ static int getpowersupplyfruinfo(void *intf, uint8_t id, struct fru_header header, struct fru_info fru) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t msg_data[4]; memset(&fru, 0, sizeof(struct fru_info)); memset(&header, 0, sizeof(struct fru_header)); /* * get info about this FRU */ memset(msg_data, 0, 4); msg_data[0] = id; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_STORAGE; req.msg.lun = 0; req.msg.cmd = GET_FRU_INFO; req.msg.data = msg_data; req.msg.data_len = 1; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Device not present, "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } fru.size = (rsp[1] << 8) | rsp[0]; fru.access = rsp[2] & 0x1; lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)", fru.size, fru.access ? "words" : "bytes"); if (fru.size < 1) { printf(" Invalid FRU size %d", fru.size); return -1; } /* * retrieve the FRU header */ msg_data[0] = id; msg_data[1] = 0; msg_data[2] = 0; msg_data[3] = 8; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_STORAGE; req.msg.lun = 0; req.msg.cmd = GET_FRU_DATA; req.msg.data = msg_data; req.msg.data_len = 4; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Device not present, "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } if (verbose > 1) printbuf(rsp, rsp_len, "FRU DATA"); memcpy(&header, &rsp[1], 8); return 0; } #endif /***************************************************************** * Function Name: ipmi_powermonitor_usage * * Description: This function prints help message for powermonitor command * Input: * Output: * * Return: * ******************************************************************/ static void ipmi_powermonitor_usage(void) { lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " powermonitor"); lprintf(LOG_NOTICE, " Shows power tracking statistics "); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " powermonitor clear cumulativepower"); lprintf(LOG_NOTICE, " Reset cumulative power reading"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " powermonitor clear peakpower"); lprintf(LOG_NOTICE, " Reset peak power reading"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " powermonitor powerconsumption"); lprintf(LOG_NOTICE, " Displays power consumption in "); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " powermonitor powerconsumptionhistory "); lprintf(LOG_NOTICE, " Displays power consumption history "); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " powermonitor getpowerbudget"); lprintf(LOG_NOTICE, " Displays power cap in "); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " powermonitor setpowerbudget "); lprintf(LOG_NOTICE, " Allows user to set the power cap in "); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " powermonitor enablepowercap "); lprintf(LOG_NOTICE, " To enable set power cap"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " powermonitor disablepowercap "); lprintf(LOG_NOTICE, " To disable set power cap"); lprintf(LOG_NOTICE, ""); } /***************************************************************** * Function Name: ipmi_delloem_vFlash_main * * Description: This function processes the delloem vFlash command * Input: intf - ipmi interface argc - no of arguments argv - argument string array * Output: * * Return: return code 0 - success * -1 - failure * ******************************************************************/ static int ipmi_delloem_vFlash_main (void * intf, int argc, char ** argv) { int rc = 0; current_arg++; rc = ipmi_delloem_vFlash_process(intf, current_arg, argv); return(rc); } /***************************************************************** * Function Name: get_vFlash_compcode_str * * Description: This function maps the vFlash completion code * to a string * Input : vFlash completion code and static array of codes vs strings * Output: - * Return: returns the mapped string * ******************************************************************/ const char * get_vFlash_compcode_str(uint8_t vflashcompcode, const struct vFlashstr *vs) { static char un_str[32]; int i; for (i = 0; vs[i].str != NULL; i++) { if (vs[i].val == vflashcompcode) return vs[i].str; } memset(un_str, 0, 32); snprintf(un_str, 32, "Unknown (0x%02X)", vflashcompcode); return un_str; } /***************************************************************** * Function Name: ipmi_get_sd_card_info * * Description: This function prints the vFlash Extended SD card info * Input : ipmi interface * Output: prints the sd card extended info * Return: 0 - success -1 - failure * ******************************************************************/ static int ipmi_get_sd_card_info(void* intf) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t msg_data[2]; uint8_t input_length=0; uint8_t cardstatus=0x00; IPMI_DELL_SDCARD_INFO * sdcardinfoblock; input_length = 2; msg_data[0] = msg_data[1] = 0x00; req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; req.msg.cmd = IPMI_GET_EXT_SD_CARD_INFO; req.msg.data = msg_data; req.msg.data_len = input_length; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error getting SD Card Extended info, "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n",rv,decode_cc(0,rv)); return rv; } sdcardinfoblock = (IPMI_DELL_SDCARD_INFO *) (void *) rsp; if( (iDRAC_FLAG == IDRAC_12G) && (sdcardinfoblock->vflashcompcode == VFL_NOT_LICENSED)) { printf("FM001 : A required license is missing or expired\n"); return -1; } else if (sdcardinfoblock->vflashcompcode != 0x00) { lprintf(LOG_ERR, " Error in getting SD Card Extended Information (%s) \n", get_vFlash_compcode_str(sdcardinfoblock->vflashcompcode, vFlash_completion_code_vals)); return -1; } if (!(sdcardinfoblock->sdcardstatus & 0x04)) { lprintf(LOG_ERR, " vFlash SD card is unavailable, please insert the card\n of size 256MB or greater\n"); return 0; } printf("vFlash SD Card Properties\n"); printf("SD Card size : %8dMB\n",sdcardinfoblock->sdcardsize); printf("Available size : %8dMB\n",sdcardinfoblock->sdcardavailsize); printf("Initialized : %10s\n", (sdcardinfoblock->sdcardstatus & 0x80) ? "Yes" : "No"); printf("Licensed : %10s\n", (sdcardinfoblock->sdcardstatus & 0x40) ? "Yes" : "No"); printf("Attached : %10s\n", (sdcardinfoblock->sdcardstatus & 0x20) ? "Yes" : "No"); printf("Enabled : %10s\n", (sdcardinfoblock->sdcardstatus & 0x10) ? "Yes" : "No"); printf("Write Protected : %10s\n", (sdcardinfoblock->sdcardstatus & 0x08) ? "Yes" : "No"); cardstatus = sdcardinfoblock->sdcardstatus & 0x03; printf("Health : %10s\n", ((0x00 == cardstatus ) ? "OK" : ((cardstatus == 0x03) ? "Undefined" : ((cardstatus == 0x02) ? "Critical" : "Warning")))); printf("Bootable partition : %10d\n",sdcardinfoblock->bootpartion); return 0; } /***************************************************************** * Function Name: ipmi_delloem_vFlash_process * * Description: This function processes the args for vFlash subcmd * Input : intf - ipmi interface, arg index, argv array * Output: prints help or error with help * Return: 0 - Success -1 - failure * ******************************************************************/ static int ipmi_delloem_vFlash_process(void* intf, int current_arg, char ** argv) { int rc = 0; int drv; drv = get_driver_type(); if (drv != DRV_MV) /* MV open driver */ { lprintf(LOG_ERR, " vFlash support is enabled only for wmi and open interface.\n Its not enabled for lan and lanplus interface."); return -1; } if (argv[current_arg] == NULL || strcmp(argv[current_arg], "help") == 0) { ipmi_vFlash_usage(); return 0; } ipmi_idracvalidator_command(intf); if (!strncmp(argv[current_arg], "info\0", 5)) { current_arg++; if (argv[current_arg] == NULL) { ipmi_vFlash_usage(); return -1; } else if (strncmp(argv[current_arg], "Card\0", 5) == 0) { current_arg++; if (argv[current_arg] != NULL) { ipmi_vFlash_usage(); return -1; } rc = ipmi_get_sd_card_info(intf); return rc; } else /* TBD: many sub commands are present */ { ipmi_vFlash_usage(); return -1; } } /* TBD other vFlash subcommands */ else { ipmi_vFlash_usage(); return -1; } return(rc); } /***************************************************************** * Function Name: ipmi_vFlash_usage * * Description: This function displays the usage for using vFlash * Input : void * Output: prints help * Return: void * ******************************************************************/ static void ipmi_vFlash_usage(void) { lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " vFlash info Card"); lprintf(LOG_NOTICE, " Shows Extended SD Card information"); lprintf(LOG_NOTICE, ""); } /***************************************************************** * Function Name: ipmi_delloem_windbg_main * * Description: This function processes the delloem windbg command * Input: intf - ipmi interface argc - no of arguments argv - argument string array * Output: * * Return: return code 0 - success * -1 - failure * ******************************************************************/ static int ipmi_delloem_windbg_main (void * intf, int argc, char ** argv) { int rc = 0; current_arg++; if (argv[current_arg] == NULL) { ipmi_windbg_usage(); return -1; } if (strncmp(argv[current_arg], "start\0", 6) == 0) { rc = ipmi_windbg_start(intf); } else if (strncmp(argv[current_arg], "end\0", 4) == 0) { rc = ipmi_windbg_end(intf); } else { ipmi_windbg_usage(); } return(rc); } /***************************************************************** * Function Name: ipmi_windbg_start * * Description: This function Starts the windbg * Input : void * Output: Start the debug * Return: void * ******************************************************************/ static int ipmi_windbg_start (void * intf) { int rc; lprintf(LOG_NOTICE, "Issuing sol activate"); lprintf(LOG_NOTICE, ""); rc = ipmi_sol_activate(intf,0,0); if (rc) lprintf(LOG_NOTICE, "Can not issue sol activate"); else windbgsession = 1; return(rc); } /***************************************************************** * Function Name: ipmi_windbg_end * * Description: This function ends the windbg * Input : void * Output: End the debug * Return: void * ******************************************************************/ static int ipmi_windbg_end(void * intf) { int rc; lprintf(LOG_NOTICE, "Issuing sol deactivate"); lprintf(LOG_NOTICE, ""); rc = ipmi_sol_deactivate(intf); if (rc) lprintf(LOG_NOTICE, "Can not issue sol deactivate"); else windbgsession = 0; return(rc); } /***************************************************************** * Function Name: ipmi_windbg_usage * * Description: This function displays the usage for using windbg * Input : void * Output: prints help * Return: void * ******************************************************************/ static void ipmi_windbg_usage(void) { lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " windbg start"); lprintf(LOG_NOTICE, " Starts the windbg session (Cold Reset & SOL Activation)"); lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " windbg end"); lprintf(LOG_NOTICE, " Ends the windbg session (SOL Deactivation"); lprintf(LOG_NOTICE, ""); } /********************************************************************** * Function Name: ipmi_setled_usage * * Description: This function prints help message for setled command * Input: * Output: * * Return: * ***********************************************************************/ static void ipmi_setled_usage(void) { lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " setled "); lprintf(LOG_NOTICE, " Set backplane LED state"); lprintf(LOG_NOTICE, " b:d.f = PCI Bus:Device.Function of drive (lspci format)"); lprintf(LOG_NOTICE, " state = present|online|hotspare|identify|rebuilding|"); lprintf(LOG_NOTICE, " fault|predict|critical|failed"); lprintf(LOG_NOTICE, ""); } static void ipmi_delloem_getled_usage(void) { lprintf(LOG_NOTICE, ""); lprintf(LOG_NOTICE, " getled "); lprintf(LOG_NOTICE, " Get Chassis ID LED state"); lprintf(LOG_NOTICE, ""); } static int IsSetLEDSupported(void) { return SetLEDSupported; } static int CheckSetLEDSupport(void * intf) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[10]; SetLEDSupported = 0; req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; req.msg.cmd = 0xD5; /* Storage */ req.msg.data_len = sizeof(data); /*10*/ req.msg.data = data; memset(data, 0, sizeof(data)); data[0] = 0x01; // get data[1] = 0x00; // subcmd:get firmware version data[2] = 0x08; // length lsb data[3] = 0x00; // length msb data[4] = 0x00; // offset lsb data[5] = 0x00; // offset msb data[6] = 0x00; // bay id data[7] = 0x00; data[8] = 0x00; data[9] = 0x00; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv == 0) SetLEDSupported = 1; return(rv); } /***************************************************************** * Function Name: ipmi_getdrivemap * * Description: This function returns mapping of BDF to Bay:Slot * Input: intf - ipmi interface * bdf - PCI Address of drive * *bay - Returns bay ID *slot - Returns slot ID * Output: * * Return: * ******************************************************************/ static int ipmi_getdrivemap(void * intf, int b, int d, int f, int *bay, int *slot) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[8]; /* Get mapping of BDF to bay:slot */ req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; req.msg.cmd = 0xD5; req.msg.data_len = 8; req.msg.data = data; memset(data, 0, sizeof(data)); data[0] = 0x01; // get data[1] = 0x07; // storage map data[2] = 0x06; // length lsb data[3] = 0x00; // length msb data[4] = 0x00; // offset lsb data[5] = 0x00; // offset msb data[6] = b; // bus data[7] = (d << 3) + f; // devfn rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error issuing getdrivemap command, "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n", rv, decode_cc(0,rv)); return rv; } *bay = rsp[7]; *slot = rsp[8]; if (*bay == 0xFF || *slot == 0xFF) { lprintf(LOG_ERR, "Error could not get drive bay:slot mapping"); return -1; } return 0; } /***************************************************************** * Function Name: ipmi_setled_state * * Description: This function updates the LED on the backplane * Input: intf - ipmi interface * bdf - PCI Address of drive * state - SES Flags state of drive * Output: * * Return: * ******************************************************************/ static int ipmi_setled_state (void * intf, int bayId, int slotId, int state) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[20]; /* Issue Drive Status Update to bay:slot */ req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; req.msg.cmd = 0xD5; req.msg.data_len = 20; req.msg.data = data; memset(data, 0, sizeof(data)); data[0] = 0x00; // set data[1] = 0x04; // set drive status data[2] = 0x0e; // length lsb data[3] = 0x00; // length msb data[4] = 0x00; // offset lsb data[5] = 0x00; // offset msb data[6] = 0x0e; // length lsb data[7] = 0x00; // length msb data[8] = bayId; // bayid data[9] = slotId; // slotid data[10] = state & 0xff; // state LSB data[11] = state >> 8; // state MSB; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error issuing setled command, "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n", rv, decode_cc(0,rv)); return rv; } return 0; } int ipmi_delloem_getled_state (void * intf, uint8_t *state) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t data[2]; uint8_t led_state = 0; req.msg.netfn = IPMI_DELL_OEM_NETFN; req.msg.lun = 0; req.msg.cmd = GET_CHASSIS_LED_STATE; req.msg.data_len = 0; req.msg.data = data; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf(" Error issuing getled command, "); if (rv < 0) printf("no response\n"); else printf("Completion Code 0x%02x %s\n", rv, decode_cc(0,rv)); } else { led_state = rsp[0]; } *state = led_state; return rv; } /***************************************************************** * Function Name: ipmi_getsesmask * * Description: This function calculates bits in SES drive update * Return: Mask set with bits for SES backplane update * ******************************************************************/ static int ipmi_getsesmask(int argc, char **argv) { int mask = 0; //int idx; while (current_arg < argc) { if (!strcmp(argv[current_arg], "present")) mask |= (1L << 0); if (!strcmp(argv[current_arg], "online")) mask |= (1L << 1); if (!strcmp(argv[current_arg], "hotspare")) mask |= (1L << 2); if (!strcmp(argv[current_arg], "identify")) mask |= (1L << 3); if (!strcmp(argv[current_arg], "rebuilding")) mask |= (1L << 4); if (!strcmp(argv[current_arg], "fault")) mask |= (1L << 5); if (!strcmp(argv[current_arg], "predict")) mask |= (1L << 6); if (!strcmp(argv[current_arg], "critical")) mask |= (1L << 9); if (!strcmp(argv[current_arg], "failed")) mask |= (1L << 10); current_arg++; } return mask; } /***************************************************************** * Function Name: ipmi_delloem_setled_main * * Description: This function processes the delloem setled command * Input: intf - ipmi interface argc - no of arguments argv - argument string array * Output: * * Return: return code 0 - success * -1 - failure * ******************************************************************/ static int ipmi_delloem_setled_main(void * intf, int argc, char ** argv) { int rc = -1; int b,d,f, mask; int bayId, slotId; bayId = 0xFF; slotId = 0xFF; current_arg++; if (argc < current_arg) { usage(); return rc; } /* ipmitool delloem setled info*/ if (argc == 1 || strcmp(argv[current_arg], "help") == 0) { ipmi_setled_usage(); return 0; } CheckSetLEDSupport (intf); if (!IsSetLEDSupported()) { printf("'setled' is not supported on this system.\n"); return rc; } else if (sscanf(argv[current_arg], "%*x:%x:%x.%x", &b,&d,&f) == 3) { /* We have bus/dev/function of drive */ current_arg++; ipmi_getdrivemap (intf, b, d, f, &bayId, &slotId); } else if (sscanf(argv[current_arg], "%x:%x.%x", &b,&d,&f) == 3) { /* We have bus/dev/function of drive */ current_arg++; } else { ipmi_setled_usage(); return -1; } /* Get mask of SES flags */ mask = ipmi_getsesmask(argc, argv); /* Get drive mapping */ if (ipmi_getdrivemap (intf, b, d, f, &bayId, &slotId)) return -1; /* Set drive LEDs */ return ipmi_setled_state (intf, bayId, slotId, mask); } static int ipmi_delloem_getled_main(void * intf, int argc, char ** argv) { int rc = 0; uint8_t state; if (argc == 1 || strncmp(argv[0], "help\0", 5) == 0) { ipmi_delloem_getled_usage(); return(0); } else { rc = ipmi_delloem_getled_state (intf, &state); if (rc != 0) printf("getled_state error %d\n",rc); else { if (state == 0x01) printf("Chassis ID LED Status = ON\n"); else printf("Chassis ID LED Status = off\n"); } } return (rc); } /* * decode_sensor_dell * inputs: * sdr = the SDR buffer * reading = the 3 or 4 bytes of data from GetSensorReading * pstring = points to the output string buffer * slen = size of the output buffer * outputs: * rv = 0 if this sensor was successfully interpreted here, * non-zero otherwise, to use default interpretations. * pstring = contains the sensor reading interpretation string (if rv==0) */ int decode_sensor_dell(uchar *sdr,uchar *reading,char *pstring, int slen) { int rv = -1; uchar stype, evtype; if (sdr == NULL || reading == NULL) return(rv); if (pstring == NULL || slen == 0) return(rv); /* sdr[3] is SDR type: 1=full, 2=compact, 0xC0=oem */ if (sdr[3] != 0x02) return(rv); /*return if not compact SDR */ stype = sdr[12]; /*sensor type*/ evtype = sdr[13]; /*event type */ if (stype == 0x02) { /* Discrete Voltage */ /* Dell Discrete Voltage is opposite from normal */ if (evtype == 0x03) { /*oem interpretation */ if (reading[2] & 0x01) strncpy(pstring,"OK",slen); else strncpy(pstring,"Exceeded",slen); /*LimitExceeded*/ rv = 0; } } return(rv); } #define BIT(x) (1 << x) #define SIZE_OF_DESC 128 char * get_dell_evt_desc(uchar *sel_rec, int *psev) { struct sel_event_record * rec = (struct sel_event_record *)sel_rec; int data1, data2, data3; int code; char *desc = NULL; unsigned char count; unsigned char node; //unsigned char num; unsigned char dimmNum; unsigned char dimmsPerNode; char dimmStr[32]; //char cardStr[32]; //char numStr[32]; char tmpdesc[SIZE_OF_DESC]; static char rgdesc[SIZE_OF_DESC]; char* str; unsigned char incr = 0; unsigned char i = 0; //unsigned char postCode; // struct ipmi_rs *rsp; // struct ipmi_rq req; char tmpData; int version; // uint8_t devid[20]; /*usually 16 bytes*/ uint8_t iver; // int rv; data1 = rec->sel_type.standard_type.event_data[0]; data2 = rec->sel_type.standard_type.event_data[1]; data3 = rec->sel_type.standard_type.event_data[2]; if ( (rec->sel_type.standard_type.event_type == 0x0B) || (rec->sel_type.standard_type.event_type == 0x6F) || (rec->sel_type.standard_type.event_type == 0x07)) { code = rec->sel_type.standard_type.sensor_type; /* BDF or Slot */ desc = rgdesc; memset(desc,0,SIZE_OF_DESC); switch (code) { case 0x07: if( ((data1 & DATA_BYTE2_SPECIFIED_MASK) == 0x80)) { *psev = SEV_CRIT; if((data1 & 0x0f) == 0x00) snprintf(desc,SIZE_OF_DESC,"CPU Internal Err | "); if((data1 & 0x0f) == 0x06) { snprintf(desc,SIZE_OF_DESC,"CPU Protocol Err | "); } /* change bit location to a number */ for (count= 0; count < 8; count++) { if (BIT(count)& data2) { count++; if( ((data1 & 0x0f) == 0x06) && (rec->sel_type.standard_type.sensor_num == 0x0A)) snprintf(desc,SIZE_OF_DESC,"FSB %d ",count); else snprintf(desc,SIZE_OF_DESC,"CPU %d | APIC ID %d ",count,data3); break; } } } break; case 0x0C: if ( (rec->sel_type.standard_type.event_type == 0x0B) && !(data1 & 0x03) ) { *psev = SEV_INFO; if(data2 & 0x04) strcpy(desc,"Memory is in Spare Mode"); else if(data2 & 0x02) strcpy(desc,"Memory is in Raid Mode "); else if(data2 & 0x01) strcpy(desc,"Memory is in Mirror Mode "); break; } case 0x10: get_devid_ver(NULL,NULL,&iver); // rv = ipmi_getdeviceid(devid,sizeof(devid),fdbg); // if (rv != 0) return NULL; version = iver; /* Memory DIMMS */ *psev = SEV_MAJ; /*default severity for DIMM events*/ if( (data1 & 0x80) || (data1 & 0x20 ) ) { if( (code == 0x0c) && (rec->sel_type.standard_type.event_type == 0x0B) ) { if((data1 & 0x0f) == 0x00) { snprintf(desc,SIZE_OF_DESC," Redundancy Regained | "); *psev = SEV_INFO; } else if((data1 & 0x0f) == 0x01) { snprintf(desc,SIZE_OF_DESC,"Redundancy Lost | "); *psev = SEV_MAJ; } } else if(code == 0x0c) { if((data1 & 0x0f) == 0x00) { if(rec->sel_type.standard_type.sensor_num == 0x1C) { if((data1 & 0x80) && (data1 & 0x20 )) { count = 0; snprintf(desc,SIZE_OF_DESC,"CRC Error on:"); for(i=0;i<4;i++) { if((BIT(i))&(data2)) { if(count) { str = desc+strlen(desc); *str++ = ','; str = '\0'; count = 0; } switch(i) { case 0: snprintf(tmpdesc,SIZE_OF_DESC,"South Bound Memory"); strcat(desc,tmpdesc); count++; break; case 1: snprintf(tmpdesc,SIZE_OF_DESC,"South Bound Config"); strcat(desc,tmpdesc); count++; break; case 2: snprintf(tmpdesc,SIZE_OF_DESC,"North Bound memory"); strcat(desc,tmpdesc); count++; break; case 3: snprintf(tmpdesc,SIZE_OF_DESC,"North Bound memory-corr"); strcat(desc,tmpdesc); count++; break; default: break; } } } if(data3>=0x00 && data3<0xFF) { snprintf(tmpdesc,SIZE_OF_DESC,"|Failing_Channel:%d",data3); strcat(desc,tmpdesc); } } break; } snprintf(desc,SIZE_OF_DESC,"Correctable ECC | "); *psev = SEV_MAJ; } else if((data1 & 0x0f) == 0x01) { snprintf(desc,SIZE_OF_DESC,"UnCorrectable ECC | "); *psev = SEV_CRIT; } } else if(code == 0x10) { if((data1 & 0x0f) == 0x00) { snprintf(desc,SIZE_OF_DESC,"Corr Memory Log Disabled | "); *psev = SEV_INFO; } } } else { if(code == 0x12) { if((data1 & 0x0f) == 0x02) { snprintf(desc,SIZE_OF_DESC,"Unknown System Hardware Failure "); *psev = SEV_MAJ; } } if(code == 0x10) { if((data1 & 0x0f) == 0x03) { snprintf(desc,SIZE_OF_DESC,"All Even Logging Dissabled"); *psev = SEV_INFO; } } } if(data1 & 0x80 ) { if(((data2 >> 4) != 0x0f) && ((data2 >> 4) < 0x08)) { tmpData = ('A'+ (data2 >> 4)); if( (code == 0x0c) && (rec->sel_type.standard_type.event_type == 0x0B) ) { snprintf(tmpdesc, SIZE_OF_DESC, "Bad Card %c", tmpData); } else { snprintf(tmpdesc, SIZE_OF_DESC, "Card %c", tmpData); } strcat(desc, tmpdesc); } if (0x0F != (data2 & 0x0f)) { if(0x51 == version) { snprintf(tmpdesc, SIZE_OF_DESC, "Bank %d", ((data2 & 0x0f)+1)); strcat(desc, tmpdesc); } else { incr = (data2 & 0x0f) << 3; } } } if(data1 & 0x20 ) { strcat(desc, "ECC Error,"); if(0x51 == version) { snprintf(tmpdesc, SIZE_OF_DESC, "DIMM %c", (char)('A'+ data3)); strcat(desc, tmpdesc); } else if( ((data2 >> 4) > 0x07) && ((data2 >> 4) != 0x0F)) { strcpy(dimmStr, " DIMM_"); str = desc+strlen(desc); dimmsPerNode = 4; if( (data2 >> 4) == 0x09) dimmsPerNode = 6; else if( (data2 >> 4) == 0x0A) dimmsPerNode = 8; else if( (data2 >> 4) == 0x0B) dimmsPerNode = 9; else if( (data2 >> 4) == 0x0C) dimmsPerNode = 12; else if( (data2 >> 4) == 0x0D) dimmsPerNode = 24; else if( (data2 >> 4) == 0x0E) dimmsPerNode = 3; count = 0; for (i = 0; i < 8; i++) { if (BIT(i) & data3) { if (count) { *str++ = ','; count = 0; } node = (incr + i)/dimmsPerNode; dimmNum = ((incr + i)%dimmsPerNode)+1; dimmStr[6] = node + 'A'; sprintf(tmpdesc,"%d",dimmNum); dimmStr[7] = tmpdesc[0]; dimmStr[8] = '\0'; strcat(str,dimmStr); count++; } } } else { strcpy(dimmStr, " DIMM"); str = desc+strlen(desc); count = 0; for (i = 0; i < 8; i++) { if (BIT(i) & data3) { // check if more than one DIMM, if so add a comma to the string. if (count) { *str++ = ','; count = 0; } sprintf(tmpdesc,"%d",(i + incr + 1)); dimmStr[5] = tmpdesc[0]; dimmStr[6] = '\0'; strcat(str, dimmStr); count++; } } } } break; case 0x20: if(((data1 & 0x0f)== 0x00)&&((data1 & 0x80) && (data1 & 0x20))) { *psev = SEV_MAJ; if((data2 > 0x00)&&(data2<0xFF)) { //Add the code to display 194 entries.This sensor present only in ORCA } switch(data3) { case 0x01: snprintf(desc,SIZE_OF_DESC,"BIOS TXT Error"); break; case 0x02: snprintf(desc,SIZE_OF_DESC,"Processor/FIT TXT"); break; case 0x03: snprintf(desc,SIZE_OF_DESC,"BIOS ACM TXT Error"); break; case 0x04: snprintf(desc,SIZE_OF_DESC,"SINIT ACM TXT Error"); break; case 0xff: snprintf(desc,SIZE_OF_DESC,"Unrecognized TT Error12"); break; default: break; } } break; case 0x23: if(data1 == 0xC1) { if(data2 == 0x04) { *psev = SEV_CRIT; snprintf(desc,SIZE_OF_DESC,"Hard Reset|Interrupt type None,SMS/OS Timer used at expiration"); } } break; case 0x2B: if(((data1 & 0x0f)== 0x02)&&((data1 & 0x80) && (data1 & 0x20))) { if(data2 == 0x02) { *psev = SEV_MAJ; if(data3 == 0x00) { snprintf(desc, SIZE_OF_DESC, "between BMC/iDRAC Firmware and other hardware"); } else if(data3 == 0x01) { snprintf(desc, SIZE_OF_DESC, "between BMC/iDRAC Firmware and CPU"); } } } break; case 0xC1: if(rec->sel_type.standard_type.sensor_num == 0x25) { *psev = SEV_MAJ; if((data1 & 0x0f) == 0x01) { snprintf(desc, SIZE_OF_DESC, "Failed to program Virtual Mac Address"); if((data1 & 0x80)&&(data1 & 0x20)) { snprintf(tmpdesc, SIZE_OF_DESC, "PCI %.2x:%.2x.%x", data3 &0x7f, (data2 >> 3) & 0x1F, data2 & 0x7); } } else if((data1 & 0x0f) == 0x02) { snprintf(desc, SIZE_OF_DESC, "Device option ROM failed to support link tuning or flex address"); if((data1 & 0x80)&&(data1 & 0x20)) { //Add Mezzanine code here.DELLOEM SEL displayed unknown event } } else if((data1 & 0x0f) == 0x03) { snprintf(desc, SIZE_OF_DESC, "Failed to get link tuning or flex address data from BMC/iDRAC"); } strcat(desc,tmpdesc); } break; case 0x13: case 0xC2: case 0xC3: if(rec->sel_type.standard_type.sensor_num == 0x29) { *psev = SEV_MAJ; if(((data1 & 0x0f)== 0x02)&&((data1 & 0x80) && (data1 & 0x20))) { #if 1 /*This sensor is not implemented in iDRAC code*/ snprintf(tmpdesc, SIZE_OF_DESC, "Partner-(LinkId:%d,AgentId:%d)|",(data2 & 0xC0),(data2 & 0x30)); strcat(desc,tmpdesc); snprintf(tmpdesc, SIZE_OF_DESC, "ReportingAgent(LinkId:%d,AgentId:%d)|",(data2 & 0x0C),(data2 & 0x03)); strcat(desc,tmpdesc); if((data3 & 0xFC) == 0x00) { snprintf(tmpdesc, SIZE_OF_DESC, "LinkWidthDegraded|"); strcat(desc,tmpdesc); } if(BIT(1)& data3) { snprintf(tmpdesc,SIZE_OF_DESC,"PA_Type:IOH|"); } else { snprintf(tmpdesc,SIZE_OF_DESC,"PA-Type:CPU|"); } strcat(desc,tmpdesc); if(BIT(0)& data3) { snprintf(tmpdesc,SIZE_OF_DESC,"RA-Type:IOH"); } else { snprintf(tmpdesc,SIZE_OF_DESC,"RA-Type:CPU"); } strcat(desc,tmpdesc); #endif *psev = SEV_MAJ; } } else { *psev = SEV_MAJ; if((data1 & 0x0f) == 0x02) { sprintf(desc,"%s","IO channel Check NMI"); } else { if((data1 & 0x0f) == 0x00) { snprintf(desc, SIZE_OF_DESC, "%s","PCIe Error |"); } else if((data1 & 0x0f) == 0x01) { snprintf(desc, SIZE_OF_DESC, "%s","I/O Error |"); } else if((data1 & 0x0f) == 0x04) { snprintf(desc, SIZE_OF_DESC, "%s","PCI PERR |"); } else if((data1 & 0x0f) == 0x05) { snprintf(desc, SIZE_OF_DESC, "%s","PCI SERR |"); } else { snprintf(desc, SIZE_OF_DESC, "%s"," "); } if (data3 & 0x80) snprintf(tmpdesc, SIZE_OF_DESC, "Slot %d", data3 & 0x7f); else snprintf(tmpdesc, SIZE_OF_DESC, "PCI %.2x:%.2x.%x", data3 &0x7f, (data2 >> 3) & 0x1F, data2 & 0x7); strcat(desc,tmpdesc); } *psev = SEV_CRIT; } break; case 0x0F: if(((data1 & 0x0f)== 0x0F)&&(data1 & 0x80)) { *psev = SEV_CRIT; switch(data2) { case 0x80: snprintf(desc, SIZE_OF_DESC, "No memory is detected.");break; case 0x81: snprintf(desc,SIZE_OF_DESC, "Memory is detected but is not configurable.");break; case 0x82: snprintf(desc, SIZE_OF_DESC, "Memory is configured but not usable.");break; case 0x83: snprintf(desc, SIZE_OF_DESC, "System BIOS shadow failed.");break; case 0x84: snprintf(desc, SIZE_OF_DESC, "CMOS failed.");break; case 0x85: snprintf(desc, SIZE_OF_DESC, "DMA controller failed.");break; case 0x86: snprintf(desc, SIZE_OF_DESC, "Interrupt controller failed.");break; case 0x87: snprintf(desc, SIZE_OF_DESC, "Timer refresh failed.");break; case 0x88: snprintf(desc, SIZE_OF_DESC, "Programmable interval timer error.");break; case 0x89: snprintf(desc, SIZE_OF_DESC, "Parity error.");break; case 0x8A: snprintf(desc, SIZE_OF_DESC, "SIO failed.");break; case 0x8B: snprintf(desc, SIZE_OF_DESC, "Keyboard controller failed.");break; case 0x8C: snprintf(desc, SIZE_OF_DESC, "System management interrupt initialization failed.");break; case 0x8D: snprintf(desc, SIZE_OF_DESC, "TXT-SX Error.");break; case 0xC0: snprintf(desc, SIZE_OF_DESC, "Shutdown test failed.");break; case 0xC1: snprintf(desc, SIZE_OF_DESC, "BIOS POST memory test failed.");break; case 0xC2: snprintf(desc, SIZE_OF_DESC, "RAC configuration failed.");break; case 0xC3: snprintf(desc, SIZE_OF_DESC, "CPU configuration failed.");break; case 0xC4: snprintf(desc, SIZE_OF_DESC, "Incorrect memory configuration.");break; case 0xFE: snprintf(desc, SIZE_OF_DESC, "General failure after video."); break; } } break; default: break; } if (desc[0] == 0) { /* if no description specified above */ /* snprintf(desc,SIZE_OF_DESC,"%02x [%02x %02x %02x]", code,data1,date2,data3); // show raw data */ desc = NULL; /*if empty, handle with default logic*/ } } else { code = rec->sel_type.standard_type.event_type; } return desc; } /* * decode_sel_dell * inputs: * evt = the 16-byte IPMI SEL event * outbuf = points to the output string buffer * outsz = size of the output buffer * outputs: * rv = 0 if this event was successfully interpreted here, * non-zero otherwise, to use default interpretations. * outbuf = will contain the interpreted event text string (if rv==0) */ int decode_sel_dell(uint8_t *evt, char *outbuf, int outsz, char fdesc, char fdbg) { int rv = -1; uint16_t id, genid; uint8_t rectype; uint32_t timestamp; char *type_str = NULL; char *gstr = NULL; char *pstr = NULL; int sevid; uchar stype, snum; fdebug = fdbg; sevid = SEV_INFO; id = evt[0] + (evt[1] << 8); rectype = evt[2]; timestamp = evt[3] + (evt[4] << 8) + (evt[5] << 16) + (evt[6] << 24); genid = evt[7] | (evt[8] << 8); stype = evt[10]; snum = evt[11]; gstr = "BMC "; if (genid == 0x0033) gstr = "Bios"; #ifdef OTHER /* evt[13] is data1/offset*/ if ( ((evt[13] & DATA_BYTE2_SPECIFIED_MASK) == 0x80) || ((evt[13] & DATA_BYTE3_SPECIFIED_MASK) == 0x20) ) { // if (evt[13] & DATA_BYTE2_SPECIFIED_MASK) // evt->data = rec->sel_type.standard_type.event_data[1]; pstr = get_dell_evt_desc(evt,&sevid); } else if (evt[13] == 0xC1) { if (snum == 0x23) { // evt->data = rec->sel_type.standard_type.event_data[1]; pstr = get_dell_evt_desc(evt,&sevid); } } #endif pstr = get_dell_evt_desc(evt,&sevid); if (pstr != NULL) rv = 0; if (rv == 0) { type_str = ""; if (rectype == 0x02) type_str = get_sensor_type_desc(stype); format_event(id,timestamp, sevid, genid, type_str, snum,NULL,pstr,NULL,outbuf,outsz); } return rv; } #ifdef METACOMMAND int i_delloem(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int rv = 0; uchar devrec[16]; int c, i; char *s1; printf("%s ver %s\n", progname,progver); set_loglevel(LOG_NOTICE); argc_sav = argc; argv_sav = argv; parse_lan_options('V',"4",0); /*default to admin priv*/ while ( (c = getopt( argc, argv,"m:s:xzEF:J:N:P:R:T:U:V:YZ:?")) != EOF ) switch(c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 's': sdrfile = optarg; break; case 'x': fdebug = 2; /* normal (dbglog if isol) */ verbose = 1; break; case 'z': fdebug = 3; /*full debug (for isol)*/ verbose = 1; break; case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: usage(); rv = ERR_USAGE; goto do_exit; break; } rv = ipmi_getdeviceid(devrec,16,fdebug); if (rv == 0) { char ipmi_maj, ipmi_min; ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; // vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16); // prod_id = devrec[9] + (devrec[10] << 8); show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); } for (i = 0; i < optind; i++) { argv++; argc--; } rv = ipmi_delloem_main(NULL, argc, argv); do_exit: ipmi_close_(); return(rv); } /* end oem_dell.c */ ipmiutil-3.1.5/util/oem_intel.c0000644000076400007640000017520713566765324016566 0ustar mgportalloggers/* * oem_intel.c * * This module handles code specific to Intel platforms, * including the Intel/Kontron Telco Alarms panel. * * Note that the Intel BMC TAM will set these alarms * based on firmware-detected thresholds and events. * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2005 Intel Corporation * Copyright (c) 2010 Kontron America, Inc. * * Compile flags for oem_intel.c: * NO_CMD would be defined if linking with ievents.c only (no ipmicmd code) * NO_EVENTS would be defined if linking with ialarms.c (no ievents code) * * 09/02/10 Andy Cress - separated from ialarms.c */ /*M* Copyright (c) 2005 Intel Corporation Copyright (c) 2010 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 Kontron 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 #include #include #include #include #include #if defined(DOS) #include #endif #include "ipmicmd.h" #include "oem_intel.h" #ifdef METACOMMAND #include "ievents.h" extern char fsm_debug; /*mem_if.c*/ extern int sens_verbose; /*isensor.c*/ extern int get_sensdesc(uchar sa, int snum, char *sdesc, int *pstyp, int *pidx); extern int get_MemDesc(int array, int dimm, char *desc, int *psz); /*mem_if.c*/ #else static char fsm_debug = 0; static int sens_verbose = 0; static int get_MemDesc(int array, int dimm, char *desc, int *psz) { return -1;} #if !defined(NO_CMD) int get_sensdesc(uchar sa, int snum, char *sensdesc, int *pstyp, int *pidx) { return(-1); } #endif static char *get_sensor_type_desc(uchar stype) { static char tstr[12]; sprintf(tstr,"%02x",stype); return(tstr); } #endif extern char fdebug; /*ipmicmd.c*/ /* * Global variables */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil inteloem"; #else static char * progver = "3.08"; static char * progname = "iinteloem"; #endif static char fRelayBits = 0; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; //static uchar g_addrtype = ADDR_SMI; #ifdef OLD #ifdef WIN32 /* Windows tamutil is installed by the ipmirastools package from Kontron. */ static char *tam1cmd = "\"\"%ProgramFiles%\"\\Intel\\ipmirastools\\tamutil\" >NUL: 2>NUL:"; static char *tam2cmd = "\"\"%ProgramFiles%\"\\Intel\\ipmirastools\\tamutil\" |findstr TAM.Status >NUL:"; //static char * tam3cmd = "ipmiutil sensor |findstr BMC_TAM >NUL:"; //static char * tambcmd = "bmcTamActive"; /*old*/ #define RET_NOT_FOUND 1 /*command not found (%ERRORLEVE%=9009)*/ #else /* Linux tamutil is installed by the ipmimisc package from Kontron. */ static char *tam1cmd = "/usr/share/ipmimisc/tamutil >/dev/null 2>&1"; static char *tam2cmd = "/usr/share/ipmimisc/tamutil 2>/dev/null |grep TAM.Status >/dev/null"; //static char * tam3cmd = "ipmiutil sensor |grep BMC_TAM >/dev/null"; //static char * tambcmd = "/usr/local/tam/bin/bmcTamActive 2>/dev/null"; /*old*/ //#define RET_TAMB_ACTIVE 256 /*from bmcTamActive, if BMC TAM is enabled*/ #define RET_NOT_FOUND 32512 /*command not found ($?=127 if shell)*/ #endif #endif #ifdef NOT #define PRIVATE_BUS_ID 0x03 // w Sahalee, the 8574 is on Private Bus 1 #define PRIVATE_BUS_ID5 0x05 // for Intel TIGI2U #define PRIVATE_BUS_ID7 0x07 // for Intel S5000 #define PERIPHERAL_BUS_ID 0x24 // w mBMC, the 8574 is on the Peripheral Bus #define ALARMS_PANEL_WRITE 0x40 #define ALARMS_PANEL_READ 0x41 #define DISK_LED_WRITE 0x44 // only used for Chesnee mBMC #define DISK_LED_READ 0x45 // only used for Chesnee mBMC #endif #if defined(NO_CMD) const char * val2str(ushort val, const struct valstr *vs) { static char un_str[32]; int i; for (i = 0; vs[i].str != NULL; i++) if (vs[i].val == val) return vs[i].str; memset(un_str, 0, 32); snprintf(un_str, 32, "Unknown (0x%x)", val); return un_str; } #else uchar get_nsc_diskleds(uchar busid) { uchar inputData[4]; uchar rdata[16]; int responseLength = 4; uchar completionCode; int ret; inputData[0] = busid; inputData[1] = DISK_LED_READ; inputData[2] = 0x1; // return one byte of LED data inputData[3] = 0x00; // init data to zero ret = ipmi_cmd(MASTER_WRITE_READ, inputData, 3, rdata, &responseLength, &completionCode, fdebug); if (ret != 0) { printf("get_nsc_diskleds: ret = %d, ccode %02x, leds = %02x\n", ret, completionCode, rdata[0]); return(0); } return(rdata[0]); } /*end get_nsc_diskleds()*/ int set_nsc_diskleds(uchar val, uchar busid) { uchar inputData[4]; uchar rdata[16]; int responseLength = 4; uchar completionCode; int ret; inputData[0] = busid; inputData[1] = DISK_LED_WRITE; inputData[2] = 0x01; // len = one byte of LED data inputData[3] = val; ret = ipmi_cmd(MASTER_WRITE_READ, inputData, 4, rdata, &responseLength, &completionCode, fdebug); if (ret != 0) { printf("set_nsc_diskleds: ret = %d, ccode %02x, leds = %02x\n", ret, completionCode, val); return(0); } return(ret); } /*end set_nsc_diskleds()*/ void show_nsc_diskleds(uchar val) { if (fdebug) printf("diskled = %02x\n",val); printf("disk A: "); if ((val & 0x20) == 0) printf("present"); else printf("not present"); if ((val & 0x02) == 0) printf("/faulted "); printf("\ndisk B: "); if ((val & 0x10) == 0) printf("present"); else printf("not present"); if ((val & 0x01) == 0) printf("/faulted "); printf("\n"); } uchar get_alarms_intel(uchar busid) { uchar inputData[4]; uchar rdata[16]; int responseLength = 4; uchar completionCode; int ret; inputData[0] = busid; inputData[1] = ALARMS_PANEL_READ; inputData[2] = 0x1; // return one byte of alarms data inputData[3] = 0x00; // init data to zero ret = ipmi_cmd(MASTER_WRITE_READ, inputData, 3, rdata, &responseLength, &completionCode, fdebug); if (ret != 0 || completionCode != 0) { printf("get_alarms: ret = %d, ccode %02x, alarms = %02x\n", ret, completionCode, rdata[0]); return(0); } return(rdata[0]); } /*end get_alarms()*/ int set_alarms_intel(uchar val, uchar busid) { uchar inputData[4]; uchar rdata[16]; int responseLength = 4; uchar completionCode; int ret; inputData[0] = busid; inputData[1] = ALARMS_PANEL_WRITE; inputData[2] = 0x1; // one byte of alarms data inputData[3] = val; ret = ipmi_cmd(MASTER_WRITE_READ, inputData, 4, rdata, &responseLength, &completionCode, fdebug); if (ret != 0) { printf("set_alarms: ret = %d, ccode %02x, value = %02x\n", ret, completionCode, val); return(ret); } if (completionCode != 0) ret = completionCode; return(ret); } /*end set_alarms()*/ /* * show_alarms * * The alarm control/status byte is decoded as follows: * bit * 7 = reserved, always write 1 * 6 = LED colors, 1 = amber (default), 0 = red * Colors were added in some later firmware versions, but * not for all platforms. * 5 = Minor Relay bit, 0 = on, 1 = off, always write 1 * 4 = Major Relay bit, 0 = on, 1 = off, always write 1 * 3 = Minor LED bit, 0 = on, 1 = off * 2 = Major LED bit, 0 = on, 1 = off * 1 = Critical LED bit, 0 = on, 1 = off * 0 = Power LED bit, 0 = on, 1 = off * * Note that the Power LED is also wired to the System Fault LED * in the back of the system, so this state may be off for Power, * but the LED could be lit for a System Fault reason instead. */ void show_alarms_intel(uchar val) { char *scrit = "ON "; char *smaj = "ON "; char *smin = "ON "; char *spow = "ON "; char *rmaj = "ON"; char *rmin = "ON"; if (fdebug) printf("alarms = %02x\n",val); if (val & 0x01) spow = "off"; if (val & 0x02) scrit = "off"; if (val & 0x04) smaj = "off"; if (val & 0x08) smin = "off"; printf("Alarm LEDs: critical = %s major = %s minor = %s power = %s\n", scrit,smaj,smin,spow); if (fRelayBits == 1) { /*CG2100 platforms have Relay bits reversed*/ if (val & 0x10) rmin = "off "; if (val & 0x20) rmaj = "off "; } else { if (val & 0x10) rmaj = "off "; if (val & 0x20) rmin = "off "; } printf("Alarm Relays: major = %s minor = %s\n", rmaj, rmin); } /* * get_led_status_intel * uses Intel OEM command to get the status of the ID LED. * if success, rv=0, pstate: 0=off, 1=on, 2=blinking */ int get_led_status_intel(uchar *pstate) { uchar rdata[64]; int rv, rlen; uchar cc, b_leds, bstate; /* This command is only supported on Intel S5000 motherboards */ rlen = sizeof(rdata); rv = ipmi_cmdraw(0x40,0x32, g_sa,g_bus,g_lun, NULL, 0, rdata, &rlen, &cc, fdebug); if (fdebug) printf("get_led_status_intel: rv = %d, cc=%02x\n", rv,cc); if (rv == 0 && cc != 0) rv = cc; if (rv == 0) { b_leds = rdata[0]; bstate = 0; /*off*/ if (b_leds & 0x80) { bstate = 1; /*on*/ } else if (b_leds & 0x40) { bstate = 2; /*blink*/ } if (pstate != NULL) *pstate = bstate; } return(rv); } int detect_capab_intel(int vend_id,int prod_id, int *cap, int *ndisk,char fdbg) { int busid = PRIVATE_BUS_ID; int f = 0; char fbmctam = 0; char fHasAlarms = 0; char fHasEnc = 0; char fpicmg = 0; char fChesnee = 0; int styp, idx, rv; char desc[20]; fdebug = fdbg; if (vend_id == VENDOR_NSC) { /*NSC mBMC, Chesnee*/ busid = PERIPHERAL_BUS_ID; fHasAlarms = 1; fChesnee = 1; } else if (vend_id == VENDOR_INTEL) { /*Intel BMC*/ switch (prod_id) { case 0x0022: busid = PRIVATE_BUS_ID5; /* Intel TIGI2U */ fbmctam = 1; /* Intel TIGI2U may have bmc tam */ fHasAlarms = 1; fHasEnc = 2; break; case 0x000C: /* TSRLT2 or TSRMT2 */ busid = PRIVATE_BUS_ID; fbmctam = 0; /* no BMC TAM */ fHasAlarms = 1; fHasEnc = 0; break; case 0x001B: busid = PRIVATE_BUS_ID; fbmctam = 1; /* Intel TIGPR2U may have bmc tam */ fHasAlarms = 1; break; case 0x0808: case 0x0841: fpicmg = 1; /* Intel ATCA platform, supports PICMG */ fHasAlarms = 1; break; case 0x4311: busid = PERIPHERAL_BUS_ID; /* SJR2 (NSI2U) mBMC */ break; case 0x0026: /*BridgePort*/ case 0x0028: /*S5000PAL*/ case 0x0029: /*S5000PSL*/ case 0x0811: /*S5000PHB*/ busid = PRIVATE_BUS_ID7; /* Intel Harbision (TIGW1U/NSW1U) */ /* Check for SAS Drv Pres sensor on HSC, if TIGW1U */ rv = get_sensdesc(0xC0,0x09,desc,&styp, &idx); if (fdebug) printf("get_sensdesc rv = %d\n",rv); if (rv == ERR_NOT_FOUND) { /* NSW1U does not have alarm panel*/ fHasAlarms = 0; fHasEnc = 0; } else { /* has HSC, like TIGW1U */ fbmctam = 1; /* TIGW1U may have bmc tam */ fHasAlarms = 1; if (prod_id == 0x0811) fHasEnc = 3; else fHasEnc = 6; } break; case 0x003E: /*S5520UR*/ busid = PRIVATE_BUS_ID; fbmctam = 1; /* CG2100 has bmc tam */ fHasAlarms = 1; fHasEnc = 8; /* CG2100 has 8 disks */ fRelayBits = 1; set_max_kcs_loops(URNLOOPS); /*longer for cmds (default 300)*/ break; case 0x005D: /* Copper Pass, CG2200*/ busid = PRIVATE_BUS_ID; fbmctam = 1; /* CG2200 has bmc tam */ fHasAlarms = 1; fRelayBits = 1; fHasEnc = 6; /* 6 disks */ set_max_kcs_loops(URNLOOPS); /*longer for cmds (default 300)*/ break; case 0x0071: /* CG2300*/ busid = PRIVATE_BUS_ID; fbmctam = 1; /* CG2300 has bmc tam */ fHasAlarms = 1; fRelayBits = 1; fHasEnc = 6; /* 6 disks */ set_max_kcs_loops(URNLOOPS); /*longer for cmds (default 300)*/ break; case 0x0051: /* Eagle Pass */ busid = PRIVATE_BUS_ID; fbmctam = 1; /* CG1200 has bmc tam */ fHasAlarms = 1; fRelayBits = 1; fHasEnc = 4; /* 4 disks */ set_max_kcs_loops(URNLOOPS); /*longer for cmds (default 300)*/ break; case 0x0048: /* "(S1200BT)" *BearTooth Pass*/ case 0x004A: /* "(S2600CP)" *Canoe Pass*/ case 0x0055: /* Iron Pass */ case 0x005C: /* Lizard Head Pass */ fHasEnc = 8; set_max_kcs_loops(URNLOOPS); /*longer for cmds (default 300)*/ break; default: busid = PRIVATE_BUS_ID; fHasEnc = 8; break; } } if (fHasAlarms) f |= HAS_ALARMS_MASK; if (fbmctam) f |= HAS_BMCTAM_MASK; if (fHasEnc > 0) { f |= HAS_ENCL_MASK; if (ndisk != NULL) *ndisk = fHasEnc; } if (fpicmg) f |= HAS_PICMG_MASK; if (fChesnee) f |= HAS_NSC_MASK; if (is_romley(vend_id,prod_id)) { if (prod_id == 0x005D) fHasEnc = 6; /*CG2200*/ fHasEnc = 8; set_max_kcs_loops(URNLOOPS); /*longer for cmds (default 300)*/ f |= HAS_ROMLEY_MASK; } if (is_grantley(vend_id,prod_id)) { if (prod_id == 0x0071) fHasEnc = 6; /*CG2300*/ fHasEnc = 8; set_max_kcs_loops(URNLOOPS); /*longer for cmds (default 300)*/ f |= HAS_ROMLEY_MASK; } *cap = f; return(busid); } int check_bmctam_intel(void) { int ret, rlen; uchar rdata[16]; uchar cc; /* Check if BMC TAM is enabled */ rlen = sizeof(rdata); ret = ipmi_cmdraw(0x00, 0x36, g_sa,g_bus,g_lun, NULL, 0, rdata, &rlen, &cc, fdebug); if ((ret == 0) && (cc == 0)) { printf("Warning: BMC TAM is active and managing the LEDs.\n" "Use tamutil (from ipmimisc rpm) to set alarms instead.\n"); return(LAN_ERR_ABORT); } else return(0); #ifdef OLD ret = system(tam1cmd); if (fdebug) printf("%s ret = %d\n",tam1cmd,ret); if (ret == RET_NOT_FOUND) { /*command not found, no such file*/ /* Could also do "ipmiutil sensor |grep BMC_TAM" (tam3cmd), * but this would take a while to complete. */ printf("Warning: BMC TAM may be active and managing the LEDs.\n" "If so, use tamutil to set the alarm LEDs instead.\n"); } else if (ret == 0) { /*the command was found, check if BMC TAM enabled*/ ret = system(tam2cmd); if (fdebug) printf("%s ret = %d\n",tam2cmd,ret); if (ret == 0) { /*If so, print warning, use Intel tamutil instead.*/ printf("Warning: BMC TAM is active and managing the LEDs.\n" "Use tamutil or the Intel TAM API to set alarms instead.\n" "Aborting.\n"); return(LAN_ERR_ABORT); } } /* else tamutil was there but did not show BMC TAM active, so * assume BMC TAM is not active and do nothing. */ return(ret); #endif } int soft_reset_intel(uchar func) { int ret, rlen; uchar idata[16]; uchar rdata[16]; uchar cc; /* Do an Intel S5000 soft reset, via an OS bridge agent (ipmiutil_asy) */ rlen = sizeof(rdata); idata[0] = func; /* 0=read, 1=shutdown, 2=reset */ ret = ipmi_cmdraw(0x70, 0x30, g_sa,g_bus,g_lun, idata, 1, rdata, &rlen, &cc, fdebug); if ((ret == 0) && (cc != 0)) ret = cc; return(ret); } int lan_failover_intel(uchar func, uchar *mode) { int ret, rlen; uchar idata[16]; uchar rdata[16]; uchar cc; /* Do an Intel S2600 LAN Failover command, where func is: * 0x00=disable, * 0x01=enable with leash monitor, * 0x02=enable with ARP monitor if blade, * 0xFF=no set, just get current mode */ rlen = sizeof(rdata); idata[0] = func; /* 0=read, 1=shutdown, 2=reset */ ret = ipmi_cmdraw(0x40, 0x3E, g_sa,g_bus,g_lun, idata, 1, rdata, &rlen, &cc, fdebug); if ((ret == 0) && (cc != 0)) ret = cc; if (ret == 0 && mode != NULL) *mode = rdata[0]; return(ret); } int get_power_restore_delay_intel(int *delay) { int ret, rlen; uchar idata[16]; uchar rdata[16]; uchar cc; rlen = sizeof(rdata); ret = ipmi_cmdraw(0x55, 0x30, g_sa,g_bus,g_lun, idata, 0, rdata, &rlen, &cc, fdebug); if ((ret == 0) && (cc != 0)) ret = cc; if (ret == 0 && delay != NULL) *delay = ( rdata[1] + ((rdata[0] & 0x07) << 8) ); return(ret); } /* end-else NO_CMD not defined */ #endif #define NTAMSEV 8 static char *tam_sev[] = { /*0*/ "OFF", /*1*/ "MNR", /*2*/ "MNR+P", /*3*/ "MJR", /*4*/ "MJR+P", /*5*/ "CRT", /*6*/ "CRT+P", /*7*/ "UNK" }; int decode_sensor_intel_nm(uchar *sdr,uchar *reading,char *pstring, int slen) { int rv = -1; uchar stype; char mystr[60]; uchar nm_sa, chan, lun; if (sdr == NULL) return(rv); if (pstring == NULL || slen == 0) return(rv); switch(sdr[3]) { /*SDR type*/ case 0xC0: /*OEM sensor*/ if (sdr[8] == 0x0D) { /* OEM NM Reference SDR, no reading */ nm_sa = sdr[10]; chan = (sdr[11] & 0xf0) >> 4; lun = (sdr[11] & 0x0f); /* show NM location and sensor numbers for NM sensors */ sprintf(mystr,"NM(%x,%x,%x) health=%x excep=%x capab=%x thresh=%x", chan,nm_sa,lun, sdr[12],sdr[13],sdr[14],sdr[15]); strncpy(pstring, mystr, slen); if ((int)strlen(mystr) > slen) pstring[slen-1] = 0; /*string*/ rv = 0; } break; case 0x02: /*compact sensor*/ if (reading == NULL) return(rv); stype = sdr[12]; /*sensor type*/ if (stype == 0xDC) { /* NM Capabilities sensor, usu snum 0x1a (26.)*/ mystr[0] = 0; if (reading[2] == 0x00) strcat(mystr,"None"); else { if (reading[2] & 0x01) strcat(mystr,"Policy "); if (reading[2] & 0x02) strcat(mystr,"Monitor "); if (reading[2] & 0x04) strcat(mystr,"Power "); } strncpy(pstring, mystr, slen); if ((int)strlen(mystr) > slen) pstring[slen-1] = 0; /*string*/ rv = 0; } break; default: break; } return(rv); } static void show_oem_hex(uchar *sdr, int slen) { int i; for (i = 8; i < slen; i++) printf("%02x ",sdr[i]); printf("\n"); } void show_oemsdr_nm(uchar *sdr) { int rv, len; char mystr[60]; /* vendor id has already been shown */ len = sdr[4] + 5; rv = decode_sensor_intel_nm(sdr,NULL,mystr,sizeof(mystr)); if (rv == 0) printf("%s\n",mystr); else show_oem_hex(sdr, len); return; } /* * show_oemsdr_intel */ void show_oemsdr_intel(uchar *sdr) { uchar idx, len, c, i, n, j, k, t; int vend; len = sdr[4] + 5; /*double-check that this is an Intel OEM SDR*/ vend = sdr[5] | (sdr[6] << 8) | (sdr[7] << 16); if (vend != VENDOR_INTEL) { if (fdebug) printf("show_oemsdr_intel: vendor %x != %x (Intel)\n", vend,VENDOR_INTEL); return; } printf("Intel: "); switch(sdr[8]) { /*OEM subtype*/ case 0x53: /* SDR version subtype (has ASCII) */ for (i = 8; i < len; i++) { c = sdr[i]; if (c < 0x20 || c > 0x7f) printf("[%02x]",c); else printf("%c",c); } printf("\n"); break; case 0x60: /* BMC TAM subtype */ idx = (sdr[10] & 0xf0) >> 4; n = (sdr[10] & 0x0f) + 1; /*number of TAM records*/ printf("BMC_TAM%d ",idx); for (i = 8; i < len; i++) printf("%02x ",sdr[i]); if (idx == 0) { printf(" nrec=%d cfg=%02x",n,sdr[11]); } printf("\n"); if (fdebug || sens_verbose) { /* show decoded BMC_TAM rules */ if (idx > 0) { uchar map, off, sev, sa; const char *tstr; sa = sdr[12]; for (i = 13; i < len; ) { k = (sdr[i] & 0xf0) >> 4; t = sdr[i+1]; tstr = get_sensor_type_desc(t); printf("\tBMC_TAM%d sa=%02x %s (",idx,sa,tstr); for (j = 0; j < k; j++) { map = sdr[i+3+j]; off = (map & 0xf0) >> 4; sev = map & 0x0f; if (sev >= NTAMSEV) sev = NTAMSEV - 1; printf("%d=%s ",off,tam_sev[sev]); } printf(")\n"); i += 3 + k; } } } break; case 0x0C: /* Fan Speed Control */ printf("FanCtl "); show_oem_hex(sdr, len); break; case 0x0D: /* ME NM Reference SDR */ show_oemsdr_nm(sdr); break; case 0x02: /*S5500 Power Unit Redundancy subtype*/ case 0x05: /*S5500 Fan Redundancy subtype*/ case 0x06: /*S5000 System Information/Capab */ case 0x09: /*S5500 Voltage sensor scaling*/ case 0x0A: /*S5500 Fan sensor scaling*/ case 0x0B: /*S5500 Thermal Profile data*/ default: /* other subtypes 07,0e,15 etc. */ show_oem_hex(sdr, len); break; } /*end switch*/ } /*end show_oemsdr_intel*/ #ifdef NO_EVENTS /* if not linking with ievents.c, need to skip decode_sel_intel because it * would have unresolved externals for fmt_time, get_sev_str, get_sensor_tag */ #else /* * decode_sel_intel * inputs: * evt = the 16-byte IPMI SEL event * outbuf = points to the output string buffer * outsz = size of the output buffer * outputs: * rv = 0 if this event was successfully interpreted here, * non-zero otherwise, to use default interpretations. * outbuf = will contain the interpreted event text string (if rv==0) */ int decode_sel_intel(uchar *evt, char *outbuf, int outsz, char fdesc, char fdebug) { int rv = -1; ushort id; uchar rectype; ulong timestamp; char mybuf[64]; char oembuf[64]; char *type_str = NULL; char *pstr = NULL; int sevid; ushort genid; uchar snum; char *p1; int d, f; sevid = SEV_INFO; id = evt[0] + (evt[1] << 8); rectype = evt[2]; snum = evt[11]; timestamp = evt[3] + (evt[4] << 8) + (evt[5] << 16) + (evt[6] << 24); genid = evt[7] | (evt[8] << 8); if (rectype == 0x00) { if (snum == 0x0A && evt[12] == 0x03) rectype = 0x02; /*internal wdog*/ } if (rectype == 0x02) { type_str = ""; sprintf(mybuf,"%02x [%02x %02x %02x]", evt[12],evt[13],evt[14],evt[15]); pstr = ""; /*default*/ switch(evt[10]) { /*sensor type*/ case 0x00: /* type undefined */ // type_str = get_sensor_type_desc(0x28); type_str = "Management Subsystem Health"; if (snum == 0x0A && evt[12] == 0x03) { /*internal wd event*/ pstr = "BMC wd restart"; sevid = SEV_CRIT; rv = 0; } break; case 0x13: /* Critical Interrupt */ type_str = "Critical Interrupt"; if (evt[12] == 0x70) { /*event trigger/type = OEM AER events */ /* AER doc uses 'Fatal' here, but they are not really fatal.*/ pstr = &oembuf[0]; switch(evt[13]) { /*data1/offset*/ case 0xA0: p1 = "PCIe Data Link Protocol Error"; break; case 0xA1: p1 = "PCIe Surprise Link Down"; break; case 0xA2: p1 = "PCIe Unexpected Completion"; break; case 0xA3: p1 = "PCIe Unsupported Request"; break; case 0xA4: p1 = "PCIe Poisoned TLP"; break; case 0xA5: p1 = "PCIe Flow Control Protocol"; break; case 0xA6: p1 = "PCIe Completion Timeout"; break; case 0xA7: p1 = "PCIe Completer Abort"; break; case 0xA8: p1 = "PCIe Recv Buffer Overflow"; break; case 0xA9: p1 = "PCIe ACS Violation"; break; case 0xAA: p1 = "PCIe Malformed TLP"; break; case 0xAB: p1 = "PCIe Recvd Fatal Message"; break; case 0xAC: p1 = "PCIe Unexpected Completion Error"; break; case 0xAD: p1 = "PCIe Recvd Warning Message"; break; default: p1 = "PCIe Other AER"; break; } rv = 0; sevid = SEV_MAJ; /* also include the bus dev/func bytes (as shown by lspci) */ d = (evt[15] & 0xF8) >> 3; f = (evt[15] & 0x07); snprintf(oembuf,sizeof(oembuf),"%s on (%02x:%02x.%d)", p1,evt[14],d,f); } if (evt[12] == 0x71) { /*event trigger/type = OEM AER warnings */ pstr = &oembuf[0]; switch(evt[13]) { /*data1/offset*/ case 0xA0: p1 = "PCIe Warn Receiver Error"; break; case 0xA1: p1 = "PCIe Warn Bad DLLP"; break; case 0xA2: p1 = "PCIe Warn Bad TLLP"; break; case 0xA3: p1 = "PCIe Warn Replay Num Rollover"; break; case 0xA4: p1 = "PCIe Warn Replay Timeout"; break; case 0xA5: p1 = "PCIe Warn Advisory Non-Fatal"; break; case 0xA6: p1 = "PCIe Warn Link BW Changed"; break; default: p1 = "PCIe Warn Other AER"; break; } rv = 0; sevid = SEV_MIN; /* also include the bus dev/func bytes (as shown by lspci) */ d = (evt[15] & 0xF8) >> 3; f = (evt[15] & 0x07); snprintf(oembuf,sizeof(oembuf),"%s on (%02x:%02x.%d)", p1,evt[14],d,f); } break; case 0x2B: /* Version Change */ type_str = "Version Change"; if (evt[12] == 0x70) { /*event trigger/type */ switch(evt[13]) { /*data1/offset*/ case 0x00: pstr = "Update started"; break; case 0x01: pstr = "Update completed"; break; case 0x02: pstr = "Update failed"; sevid = SEV_MIN; break; default: pstr = "-"; break; } rv = 0; } break; default: break; } if (rv == 0) { format_event(id,timestamp, sevid, genid, type_str, snum,NULL,pstr,mybuf,outbuf,outsz); } } return rv; } /*end decode_sel_intel*/ #endif const struct valstr intel_mem_s2600[] = { { 0, "DIMM_A1" }, { 1, "DIMM_A2" }, { 2, "DIMM_A3" }, { 3, "DIMM_B1" }, { 4, "DIMM_B2" }, { 5, "DIMM_B3" }, { 6, "DIMM_C1" }, { 7, "DIMM_C2" }, { 8, "DIMM_C3" }, { 9, "DIMM_D1" }, { 10, "DIMM_D2" }, { 11, "DIMM_D3" }, { 12, "DIMM_E1" }, { 13, "DIMM_E2" }, { 14, "DIMM_E3" }, { 15, "DIMM_F1" }, { 16, "DIMM_F2" }, { 17, "DIMM_F3" }, { 18, "DIMM_G1" }, { 19, "DIMM_G2" }, { 20, "DIMM_G3" }, { 21, "DIMM_H1" }, { 22, "DIMM_H2" }, { 23, "DIMM_H3" }, { 24, "DIMM_I1" }, { 25, "DIMM_I2" }, { 26, "DIMM_I3" }, { 27, "DIMM_J1" }, { 28, "DIMM_J2" }, { 29, "DIMM_J3" }, { 30, "DIMM_K1" }, { 31, "DIMM_K2" }, { 32, "DIMM_K3" }, { 33 , NULL } /*end of list*/ }; const struct valstr intel_mem_s5520ur[] = { { 0, "DIMM_A1" }, { 1, "DIMM_A2" }, { 2, "DIMM_B1" }, { 3, "DIMM_B2" }, { 4, "DIMM_C1" }, { 5, "DIMM_C2" }, { 6, "DIMM_D1" }, { 7, "DIMM_D2" }, { 8, "DIMM_E1" }, { 9, "DIMM_E2" }, { 10, "DIMM_F1" }, { 11, "DIMM_F2" }, { 12 , NULL } /*end of list*/ }; const struct valstr intel_mem_s5000phb[] = { { 0, "DIMM_A1" }, { 1, "DIMM_A2" }, { 2, "DIMM_A3" }, { 3, "DIMM_B1" }, { 4, "DIMM_B2" }, { 5, "DIMM_B3" }, { 6 , NULL } /*end of list*/ }; const struct valstr intel_mem_s5000pal[] = { { 0, "DIMM_A1" }, { 1, "DIMM_A2" }, { 2, "DIMM_B1" }, { 3, "DIMM_B2" }, { 4, "DIMM_C1" }, { 5, "DIMM_C2" }, { 6, "DIMM_D1" }, { 7, "DIMM_D2" }, { 8 , NULL } /*end of list*/ }; const struct valstr intel_mem_tigi2u[] = { { 0, "DIMM_1B" }, { 1, "DIMM_1A" }, { 2, "DIMM_2B" }, { 3, "DIMM_2A" }, { 4, "DIMM_3B" }, { 5, "DIMM_3A" }, { 6 , NULL } /*end of list*/ }; #define LIDS 8 ushort lan2i_ids[LIDS] = { /*Intel prod_ids that use lan2i, rest use lan2*/ 0x0000, /*uninitialized */ 0x0022, /*TIGI2U */ 0x0026, /*Bridgeport */ 0x0028, /*S5000PAL, Alcolu*/ 0x0029, /*S5000PSL, StarLake*/ 0x002B, /*S5000VSA */ 0x002D, /*ClearBay*/ 0x0811 /*S5000PHB, TIGW1U*/ }; #define RIDS 21 /* Intel Romley product ids: */ struct { ushort id; char *desc; } romleys[RIDS] = { { 0x0048, "S1200BT" }, /* S1200BT, BearTooth Pass */ { 0x0049, "S2600GL" }, /* S2600GL, S2600GZ */ { 0x004A, "S2600CP" }, /* S2600CP, Canoe Pass */ { 0x004D, "S2600JF" }, /* S2600JF, Jefferson Pass, Appro 512X */ { 0x004E, "S2600WP" }, /* S2600WP */ { 0x004F, "S2400SC" }, /* S2400SC */ { 0x0050, "S2400LP" }, /* S2400LP */ { 0x0051, "S2400EP" }, /* S2400EP, Eagle Pass */ { 0x0052, "S1400FP" }, /* S1400FP */ { 0x0053, "S1400SP" }, /* S1400SP */ { 0x0054, "S2600KI" }, /* S2600KI */ { 0x0055, "S2600IP" }, /* S2600IP, Iron Pass */ { 0x0056, "W2600CR" }, /* W2600CR */ { 0x0057, "S2400GP" }, /* S2400GP */ { 0x0058, "Badger Pass" }, /* Badger Pass */ { 0x0059, "S2400BB" }, /* S2400BB */ { 0x005A, "Taylor Pass" }, /* Taylor Pass */ { 0x005B, "S1600JP" }, /* S1600JP */ { 0x005C, "S4600LH" }, /* S4600LH, Lizard Head Pass */ { 0x005D, "CG2200" }, /* S2600CO, Copper Pass, Kontron CG2200 */ { 0x005E, "Big Ridge"} /* Big Ridge */ }; #define GIDS 3 /* Intel Grantley product ids: */ struct { ushort id; char *desc; } grantleys[GIDS] = { { 0x006F, "AXXRMM4" }, /* S2600, AXXRMM4LITE */ { 0x0070, "S2600" }, /* S2600CO, KP, TP, */ { 0x0071, "S2600CW" } /* CG2300, Kontron CG2300 */ }; #define TIDS 5 ushort thurley_ids[TIDS] = { /* Intel Thurley product ids: */ 0x003A, /* Snow Hill */ 0x003B, /* Shoffner */ 0x003D, /* Melstone */ 0x003E, /* S5520UR, S5500WB, Kontron CG2100, Penguin Computing Relion 700 */ 0x0040 }; /* Stoutland, Quanta QSSC-S4R/Appro GB812X-CN (Nehalem-EX) */ int is_romley(int vend, int prod) { int ret = 0; int i; if (vend != VENDOR_INTEL) return(ret); for (i = 0; i < RIDS; i++) if ((ushort)prod == romleys[i].id) { ret = 1; break; } return(ret); } int intel_romley_desc(int vend, int prod, char **pdesc) { int ret = -1; int i; if (vend != VENDOR_INTEL) return(ret); if (pdesc == NULL) return(ret); for (i = 0; i < RIDS; i++) { if ((ushort)prod == romleys[i].id) { *pdesc = romleys[i].desc; ret = 0; break; } } return(ret); } int is_grantley(int vend, int prod) { int ret = 0; int i; if (vend != VENDOR_INTEL) return(ret); for (i = 0; i < GIDS; i++) if ((ushort)prod == grantleys[i].id) { ret = 1; break; } /* For now, assume all Intel prods > 0071 act same as Grantley */ if (((ushort)prod > grantleys[GIDS-1].id) && ((ushort)prod < 0x00FF)) ret = 1; return(ret); } int intel_grantley_desc(int vend, int prod, char **pdesc) { int ret = -1; int i; if (vend != VENDOR_INTEL) return(ret); if (pdesc == NULL) return(ret); for (i = 0; i < GIDS; i++) { if ((ushort)prod == grantleys[i].id) { *pdesc = grantleys[i].desc; ret = 0; break; } } if (ret == 0 && (**pdesc == '\0')) *pdesc = "S2600"; return(ret); } int is_thurley(int vend, int prod) { int ret = 0; int i; if (vend != VENDOR_INTEL) return(ret); for (i = 0; i < TIDS; i++) if ((ushort)prod == thurley_ids[i]) { ret = 1; break; } return(ret); } int is_lan2intel(int vend, int prod) { int ret = 0; int i; if (vend != VENDOR_INTEL) return(ret); if (is_thurley(vend,prod) || is_romley(vend,prod)) ret = 0; /*iBMC does not use lan2i*/ else { for (i = 0; i < LIDS; i++) if ((ushort)prod == lan2i_ids[i]) { ret = 1; break; } } return(ret); } int decode_mem_intel(int prod, uchar b2, uchar b3, char *desc, int *psz) { const char *pstr = NULL; int array, dimm; int node, chan, sock, n; int rv = -1; uchar bdata; int vend; int iBMC = 0; if ((desc == NULL) || (psz == NULL)) return -1; vend = VENDOR_INTEL; if (is_thurley(vend,prod)) iBMC = 1; if (is_romley(vend,prod)) iBMC = 2; if (iBMC != 0) { /* custom DIMM decoding for iBMC on Intel S5500 and S2600 */ // rank = (b2 & 0x03); /* psel->event_data2 & 0x03; */ node = (b3 & 0xE0) >> 5; /*socket*/ chan = (b3 & 0x18) >> 3; sock = (b3 & 0x07); array = 0; /* is 0 for Thurley & Romley currently, else see b2. */ if (iBMC == 1) dimm = (node * 6) + (chan * 2) + sock; else dimm = (node * 12) + (chan * 3) + sock; if (fdebug) printf("iBMC DIMM (%d,%d,%d) = idx %d\n", node,chan,sock,dimm); } else { /* use straight DIMM index */ /* for mini-BMC, data2 is dimm index, data3 is syndrome */ if (prod == 0x4311) bdata = b2; /*mini-BMC*/ else if (b3 == 0xff) bdata = b2; /*ff is reserved*/ else bdata = b3; /* normal case */ /* (data3 & 0xc0) = SMBIOS type 16 mem array */ array = (bdata & 0xc0) >> 6; /* (data3 & 0x3f) = SMBIOS type 17 dimm index */ dimm = bdata & 0x3f; } if (! is_remote()) { fsm_debug = fdebug; rv = get_MemDesc(array,dimm,desc,psz); /* if (rv != 0) desc has "DIMM(%d)" */ } if (rv != 0) { /* either remote, or get_MemDesc failed, use common product defaults*/ switch(prod) { case 0x0811: /*S5000PHB*/ pstr = val2str(dimm,intel_mem_s5000phb); break; case 0x0028: /*S5000PAL*/ pstr = val2str(dimm,intel_mem_s5000pal); break; case 0x0022: /*TIGI2U*/ pstr = val2str(dimm,intel_mem_tigi2u); break; default: if (iBMC == 1) pstr = val2str(dimm,intel_mem_s5520ur); else if (iBMC == 2) pstr = val2str(dimm,intel_mem_s2600); else rv = -2; /*do not guess, use raw index below*/ break; } if (pstr != NULL) rv = 0; if (rv == 0) { /* These strings are usually 7 chars, desc is 80 chars */ n = strlen_(pstr); strncpy(desc, pstr, n+1); } else { if (bdata == 0xFF) n = sprintf(desc,DIMM_UNKNOWN); /* invalid */ else n = sprintf(desc,DIMM_NUM,dimm); } *psz = n; } return(rv); } /*end decode_mem_intel*/ /* * decode_sensor_intel * inputs: * sdr = the SDR buffer * reading = the 3 or 4 bytes of data from GetSensorReading * pstring = points to the output string buffer * slen = size of the output buffer * outputs: * rv = 0 if this sensor was successfully interpreted here, * non-zero otherwise, to use default interpretations. * pstring = contains the sensor reading interpretation string (if rv==0) */ int decode_sensor_intel(uchar *sdr,uchar *reading,char *pstring, int slen) { int rv = -1; uchar stype; char *pstr = NULL; if (sdr == NULL || reading == NULL) return(rv); if (pstring == NULL || slen == 0) return(rv); if (sdr[3] == 0x02) { /*Compact SDR*/ stype = sdr[12]; switch(stype) { case 0xC0: /* SMI State, NMI State */ case 0xC7: /* FanBoost */ case 0xCC: /* Debug Info */ case 0xD8: /* BIST */ case 0xF0: /* ATCA HotSwap, TODO: refine this */ case 0xF3: /* SMI Timeout, etc. */ case 0xF6: /* Sensor Failure */ case 0xF7: /* FSB Mismatch */ if (reading[2] & 0x01) pstr = "Asserted"; /*Asserted, error*/ else pstr = "OK"; /*deasserted*/ strncpy(pstring, pstr, slen); rv = 0; break; case 0xDC: /* NM Capabilities sensor */ rv = decode_sensor_intel_nm(sdr,reading,pstring,slen); break; default: break; } } else if (sdr[3] == 0xC0) { /*OEM SDR*/ rv = decode_sensor_intel_nm(sdr,reading,pstring,slen); } return(rv); } const struct valstr intel_s5000_post[] = { /*from S5000 TPS*/ { 0x0012, "CMOS date/time not set" }, { 0x0048, "Password check failed" }, { 0x004C, "Keyboard/interface error" }, { 0x0108, "Keyboard locked error" }, { 0x0109, "Keyboard stuck key error" }, { 0x0113, "The SAS RAID firmware cannot run properly, reflash" }, { 0x0140, "PCI PERR detected" }, { 0x0141, "PCI resource conflict" }, { 0x0146, "Insufficient memory to shadow PCI ROM" }, { 0x0192, "L3 cache size mismatch" }, { 0x0194, "CPUID, processor family are different" }, { 0x0195, "Front side bus mismatch" }, { 0x0197, "Processor speeds mismatched" }, { 0x5220, "Configuration cleared by jumper" }, { 0x5221, "Passwords cleared by jumper" }, { 0x5223, "Configuration default loaded" }, { 0x8110, "Proc1 internal error (IERR) on last boot" }, { 0x8111, "Proc2 internal error (IERR) on last boot" }, { 0x8120, "Proc1 thermal trip error on last boot" }, { 0x8121, "Proc2 thermal trip error on last boot" }, { 0x8130, "Proc1 disabled" }, { 0x8131, "Proc2 disabled" }, { 0x8160, "Proc1 unable to apply BIOS update" }, { 0x8161, "Proc2 unable to apply BIOS update" }, { 0x8170, "Proc1 failed Self Test (BIST)" }, { 0x8171, "Proc2 failed Self Test (BIST)" }, { 0x8180, "Proc1 BIOS does not support current CPU stepping" }, { 0x8181, "Proc2 BIOS does not support current CPU stepping" }, { 0x8190, "Watchdog timer failed on last boot" }, { 0x8198, "OS boot watchdog timer expired on last boot" }, { 0x8300, "Baseboard management controller failed self-test" }, { 0x8306, "Front panel controller locked" }, { 0x8305, "Hot swap controller failed" }, { 0x84F2, "Baseboard management controller failed to respond" }, { 0x84F3, "Baseboard management controller in update mode" }, { 0x84F4, "Sensor data record empty" }, { 0x84FF, "System event log full" }, { 0x8500, "Memory could not be configured in the selected RAS mode" }, { 0x8510, "Memory above 16GB maximum" }, /*S5000V only*/ { 0x8520, "DIMM_A1 failed Self Test (BIST)" }, { 0x8521, "DIMM_A2 failed Self Test (BIST)" }, { 0x8522, "DIMM_A3 failed Self Test (BIST)" }, { 0x8523, "DIMM_A4 failed Self Test (BIST)" }, { 0x8524, "DIMM_B1 failed Self Test (BIST)" }, { 0x8525, "DIMM_B2 failed Self Test (BIST)" }, { 0x8526, "DIMM_B3 failed Self Test (BIST)" }, { 0x8527, "DIMM_B4 failed Self Test (BIST)" }, { 0x8528, "DIMM_C1 failed Self Test (BIST)" }, { 0x8529, "DIMM_C2 failed Self Test (BIST)" }, { 0x852A, "DIMM_C3 failed Self Test (BIST)" }, { 0x852B, "DIMM_C4 failed Self Test (BIST)" }, { 0x852C, "DIMM_D1 failed Self Test (BIST)" }, { 0x852D, "DIMM_D2 failed Self Test (BIST)" }, { 0x852E, "DIMM_D3 failed Self Test (BIST)" }, { 0x852F, "DIMM_D4 failed Self Test (BIST)" }, { 0x8540, "Memory lost redundancy during last boot" }, { 0x8580, "DIMM_A1 Correctable ECC error" }, { 0x8581, "DIMM_A2 Correctable ECC error" }, { 0x8582, "DIMM_A3 Correctable ECC error" }, { 0x8583, "DIMM_A4 Correctable ECC error" }, { 0x8584, "DIMM_B1 Correctable ECC error" }, { 0x8585, "DIMM_B2 Correctable ECC error" }, { 0x8586, "DIMM_B3 Correctable ECC error" }, { 0x8587, "DIMM_B4 Correctable ECC error" }, { 0x8588, "DIMM_C1 Correctable ECC error" }, { 0x8589, "DIMM_C2 Correctable ECC error" }, { 0x858A, "DIMM_C3 Correctable ECC error" }, { 0x858B, "DIMM_C4 Correctable ECC error" }, { 0x858C, "DIMM_D1 Correctable ECC error" }, { 0x858D, "DIMM_D2 Correctable ECC error" }, { 0x858E, "DIMM_D3 Correctable ECC error" }, { 0x858F, "DIMM_D4 Correctable ECC error" }, { 0x8600, "Primary and secondary BIOS IDs do not match" }, { 0x8601, "BIOS Bank Override jumper set to lower bank" }, { 0x8602, "WatchDog timer expired (check secondary BIOS bank)" }, { 0x8603, "Secondary BIOS checksum fail" }, { 0xffff , NULL } /*end of list*/ }; const struct valstr intel_s5500_post[] = { /*from S5520UR TPS*/ { 0x0012, "CMOS date/time not set" }, { 0x0048, "Password check failed" }, { 0x0108, "Keyboard locked error" }, { 0x0109, "Keyboard stuck key error" }, { 0x0113, "The SAS RAID firmware cannot run properly" }, { 0x0140, "PCI PERR detected" }, { 0x0141, "PCI resource conflict" }, { 0x0146, "PCI out of resources error" }, { 0x0192, "Processor cache size mismatch" }, { 0x0194, "Processor family mismatch" }, { 0x0195, "Processor QPI speed mismatch" }, { 0x0196, "Processor Model mismatch" }, { 0x0197, "Processor speeds mismatched" }, { 0x0198, "Processor family is unsupported" }, { 0x019F, "Processor/chipset stepping configuration is unsupported" }, { 0x5220, "CMOS/NVRAM Configuration Cleared" }, { 0x5221, "Passwords cleared by jumper" }, { 0x5224, "Password clear jumper is Set" }, { 0x8110, "Proc1 internal error (IERR) on last boot" }, /*not used*/ { 0x8111, "Proc2 internal error (IERR) on last boot" }, /*not used*/ { 0x8120, "Proc1 thermal trip error on last boot" }, /*not used*/ { 0x8121, "Proc2 thermal trip error on last boot" }, /*not used*/ { 0x8130, "Proc1 disabled" }, /*not used*/ { 0x8131, "Proc2 disabled" }, /*not used*/ { 0x8140, "Proc1 Failed FRB-3 Timer" }, /*not used*/ { 0x8141, "Proc2 Failed FRB-3 Timer" }, /*not used*/ { 0x8160, "Proc1 unable to apply microcode update" }, { 0x8161, "Proc2 unable to apply microcode update" }, { 0x8170, "Proc1 failed Self Test (BIST)" }, /*not used*/ { 0x8171, "Proc2 failed Self Test (BIST)" }, /*not used*/ { 0x8180, "Processor microcode update not found" }, { 0x8190, "Watchdog timer failed on last boot" }, { 0x8198, "OS boot watchdog timer expired on last boot" }, { 0x8300, "iBMC failed self-test" }, { 0x8305, "Hotswap controller failure" }, { 0x84F2, "iBMC failed to respond" }, { 0x84F3, "iBMC in update mode" }, { 0x84F4, "Sensor data record empty" }, { 0x84FF, "System event log full" }, { 0x8500, "Memory could not be configured in the selected RAS mode" }, { 0x8520, "DIMM_A1 failed Self Test (BIST)" }, { 0x8521, "DIMM_A2 failed Self Test (BIST)" }, { 0x8522, "DIMM_B1 failed Self Test (BIST)" }, { 0x8523, "DIMM_B2 failed Self Test (BIST)" }, { 0x8524, "DIMM_C1 failed Self Test (BIST)" }, { 0x8525, "DIMM_C2 failed Self Test (BIST)" }, { 0x8526, "DIMM_D1 failed Self Test (BIST)" }, { 0x8527, "DIMM_D2 failed Self Test (BIST)" }, { 0x8528, "DIMM_E1 failed Self Test (BIST)" }, { 0x8529, "DIMM_E2 failed Self Test (BIST)" }, { 0x852A, "DIMM_F1 failed Self Test (BIST)" }, { 0x852B, "DIMM_F2 failed Self Test (BIST)" }, { 0x8540, "DIMM_A1 Disabled" }, { 0x8541, "DIMM_A2 Disabled" }, { 0x8542, "DIMM_B1 Disabled" }, { 0x8543, "DIMM_B2 Disabled" }, { 0x8544, "DIMM_C1 Disabled" }, { 0x8545, "DIMM_C2 Disabled" }, { 0x8546, "DIMM_D1 Disabled" }, { 0x8547, "DIMM_D2 Disabled" }, { 0x8548, "DIMM_E1 Disabled" }, { 0x8549, "DIMM_E2 Disabled" }, { 0x854A, "DIMM_F1 Disabled" }, { 0x854B, "DIMM_F2 Disabled" }, { 0x8560, "DIMM_A1 SPD fail error." }, { 0x8561, "DIMM_A2 SPD fail error" }, { 0x8562, "DIMM_B1 SPD fail error" }, { 0x8563, "DIMM_B2 SPD fail error" }, { 0x8564, "DIMM_C1 SPD fail error" }, { 0x8565, "DIMM_C2 SPD fail error" }, { 0x8566, "DIMM_D1 SPD fail error" }, { 0x8567, "DIMM_D2 SPD fail error" }, { 0x8568, "DIMM_E1 SPD fail error" }, { 0x8569, "DIMM_E2 SPD fail error" }, { 0x856A, "DIMM_F1 SPD fail error" }, { 0x856B, "DIMM_F2 SPD fail error" }, { 0x8580, "DIMM_A1 Correctable ECC error" }, { 0x8581, "DIMM_A2 Correctable ECC error" }, { 0x8582, "DIMM_B1 Correctable ECC error" }, { 0x8583, "DIMM_B2 Correctable ECC error" }, { 0x8584, "DIMM_C1 Correctable ECC error" }, { 0x8585, "DIMM_C2 Correctable ECC error" }, { 0x8586, "DIMM_D1 Correctable ECC error" }, { 0x8587, "DIMM_D2 Correctable ECC error" }, { 0x8588, "DIMM_E1 Correctable ECC error" }, { 0x8589, "DIMM_E2 Correctable ECC error" }, { 0x858A, "DIMM_F1 Correctable ECC error" }, { 0x858B, "DIMM_F2 Correctable ECC error" }, { 0x85A0, "DIMM_A1 Uncorrectable ECC error" }, { 0x85A1, "DIMM_A2 Uncorrectable ECC error" }, { 0x85A2, "DIMM_B1 Uncorrectable ECC error" }, { 0x85A3, "DIMM_B2 Uncorrectable ECC error" }, { 0x85A4, "DIMM_C1 Uncorrectable ECC error" }, { 0x85A5, "DIMM_C2 Uncorrectable ECC error" }, { 0x85A6, "DIMM_D1 Uncorrectable ECC error" }, { 0x85A7, "DIMM_D2 Uncorrectable ECC error" }, { 0x85A8, "DIMM_E1 Uncorrectable ECC error" }, { 0x85A9, "DIMM_E2 Uncorrectable ECC error" }, { 0x85AA, "DIMM_F1 Uncorrectable ECC error" }, { 0x85AB, "DIMM_F2 Uncorrectable ECC error" }, { 0x8601, "BIOS Bank Override jumper set to lower bank" }, /*not used*/ { 0x8602, "WatchDog timer expired (check secondary BIOS bank)" }, /*not used*/ { 0x8603, "Secondary BIOS checksum fail" }, /*not used*/ { 0x8604, "Chipset Reclaim of non critical variables complete" }, { 0x9000, "Unspecified processor component error" }, { 0x9223, "Keyboard was not detected" }, /*not used*/ { 0x9226, "Keyboard controller error" }, { 0x9243, "Mouse was not detected" }, { 0x9246, "Mouse controller error" }, { 0x9266, "Local Console controller error" }, { 0x9268, "Local Console output error" }, { 0x9269, "Local Console resource conflict error" }, { 0x9286, "Remote Console controller error" }, { 0x9287, "Remote Console input error" }, { 0x9288, "Remote Console output error" }, { 0x92A3, "Serial port was not detected" }, { 0x92A9, "Serial port resource conflict error" }, { 0x92C6, "Serial Port controller error" }, { 0x92C7, "Serial Port input error" }, { 0x92C8, "Serial Port output error" }, { 0x94C6, "LPC controller error" }, { 0x94C9, "LPC resource conflict error" }, { 0x9506, "ATA/ATPI controller error" }, { 0x95A6, "PCI controller error" }, { 0x95A7, "PCI read error" }, { 0x95A8, "PCI write error" }, { 0x9609, "Unspecified software start error" }, { 0x9641, "PEI Core load error" }, { 0x9667, "PEI module Illegal software state error" }, { 0x9687, "DXE core Illegal software state error" }, { 0x96A7, "DXE driver Illegal software state error" }, { 0x96AB, "DXE driver Invalid configuration" }, { 0x96E7, "SMM driver Illegal software state error" }, { 0xA000, "TPM device not detected" }, { 0xA001, "TPM device missing" }, { 0xA002, "TPM device failure" }, { 0xA003, "TPM device failed self-test" }, { 0xA022, "Processor mismatch error" }, { 0xA027, "Processor low voltage error" }, { 0xA028, "Processor high voltage error" }, { 0xA421, "PCI SERR detected" }, { 0xA500, "ATA/ATPI ATA bus SMART not supported" }, { 0xA501, "ATA/ATPI ATA SMART is disabled" }, { 0xA5A0, "PCI Express PERR" }, { 0xA5A1, "PCI Express SERR" }, { 0xA5A4, "PCI Express IBIST error" }, { 0xA6A0, "DXE driver Not enough memory to shadow legacy OpROM" }, { 0xB6A3, "DXE driver unrecognized" }, { 0xffff , NULL } /*end of list*/ }; const struct valstr intel_s2600_post[] = { /*from S2600CP TPS*/ { 0x0012, "CMOS date/time not set" }, { 0x0048, "Password check failed" }, { 0x0108, "Keyboard locked error" }, { 0x0109, "Keyboard stuck key error" }, { 0x0113, "The SAS RAID firmware cannot run properly" }, { 0x0140, "PCI PERR detected" }, { 0x0141, "PCI resource conflict" }, { 0x0146, "PCI out of resources error" }, { 0x0191, "Processor core/thread count mismatch" }, { 0x0192, "Processor cache size mismatch" }, { 0x0194, "Processor family mismatch" }, { 0x0195, "Processor QPI speed mismatch" }, { 0x0196, "Processor Model mismatch" }, { 0x0197, "Processor speeds mismatched" }, { 0x0198, "Processor family is unsupported" }, { 0x019F, "Processor/chipset stepping configuration is unsupported" }, { 0x5220, "CMOS/NVRAM Configuration Cleared" }, { 0x5221, "Passwords cleared by jumper" }, { 0x5224, "Password clear jumper is Set" }, { 0x8110, "Proc1 internal error (IERR) on last boot" }, /*not used*/ { 0x8111, "Proc2 internal error (IERR) on last boot" }, /*not used*/ { 0x8120, "Proc1 thermal trip error on last boot" }, /*not used*/ { 0x8121, "Proc2 thermal trip error on last boot" }, /*not used*/ { 0x8130, "Proc1 disabled" }, /*not used*/ { 0x8131, "Proc2 disabled" }, /*not used*/ { 0x8140, "Proc1 Failed FRB-3 Timer" }, /*not used*/ { 0x8141, "Proc2 Failed FRB-3 Timer" }, /*not used*/ { 0x8160, "Proc1 unable to apply microcode update" }, { 0x8161, "Proc2 unable to apply microcode update" }, { 0x8170, "Proc1 failed Self Test (BIST)" }, /*not used*/ { 0x8171, "Proc2 failed Self Test (BIST)" }, /*not used*/ { 0x8180, "Processor microcode update not found" }, { 0x8181, "Proc2 microcode update not found" }, { 0x8190, "Watchdog timer failed on last boot" }, { 0x8198, "OS boot watchdog timer expired on last boot" }, { 0x8300, "iBMC failed self-test" }, { 0x8305, "Hotswap controller failure" }, { 0x84F2, "iBMC failed to respond" }, { 0x84F3, "iBMC in update mode" }, { 0x84F4, "Sensor data record empty" }, { 0x84FF, "System event log full" }, { 0x8500, "Memory could not be configured in the selected RAS mode" }, { 0x8501, "DIMM Population Error" }, { 0x8520, "DIMM_A1 failed test/initialization" }, { 0x8521, "DIMM_A2 failed test/initialization" }, { 0x8522, "DIMM_A3 failed test/initialization" }, { 0x8523, "DIMM_B1 failed test/initialization" }, { 0x8524, "DIMM_B2 failed test/initialization" }, { 0x8525, "DIMM_B3 failed test/initialization" }, { 0x8526, "DIMM_C1 failed test/initialization" }, { 0x8527, "DIMM_C2 failed test/initialization" }, { 0x8528, "DIMM_C3 failed test/initialization" }, { 0x8529, "DIMM_D1 failed test/initialization" }, { 0x852A, "DIMM_D2 failed test/initialization" }, { 0x852B, "DIMM_D3 failed test/initialization" }, { 0x852C, "DIMM_E1 failed test/initialization" }, { 0x852D, "DIMM_E2 failed test/initialization" }, { 0x852E, "DIMM_E3 failed test/initialization" }, { 0x852F, "DIMM_F1 failed test/initialization" }, { 0x8530, "DIMM_F2 failed test/initialization" }, { 0x8531, "DIMM_F3 failed test/initialization" }, { 0x8532, "DIMM_G1 failed test/initialization" }, { 0x8533, "DIMM_G2 failed test/initialization" }, { 0x8534, "DIMM_G3 failed test/initialization" }, { 0x8535, "DIMM_H1 failed test/initialization" }, { 0x8536, "DIMM_H2 failed test/initialization" }, { 0x8537, "DIMM_H3 failed test/initialization" }, { 0x8538, "DIMM_I1 failed test/initialization" }, { 0x8539, "DIMM_I2 failed test/initialization" }, { 0x853A, "DIMM_I3 failed test/initialization" }, { 0x853B, "DIMM_J1 failed test/initialization" }, { 0x853C, "DIMM_J2 failed test/initialization" }, { 0x853D, "DIMM_J3 failed test/initialization" }, { 0x853E, "DIMM_K1 failed test/initialization" }, { 0x853F, "DIMM_K2 failed test/initialization" }, { 0x8540, "DIMM_A1 Disabled" }, { 0x8541, "DIMM_A2 Disabled" }, { 0x8542, "DIMM_A3 Disabled" }, { 0x8543, "DIMM_B1 Disabled" }, { 0x8544, "DIMM_B2 Disabled" }, { 0x8545, "DIMM_B3 Disabled" }, { 0x8546, "DIMM_C1 Disabled" }, { 0x8547, "DIMM_C2 Disabled" }, { 0x8548, "DIMM_C3 Disabled" }, { 0x8549, "DIMM_D1 Disabled" }, { 0x854A, "DIMM_D2 Disabled" }, { 0x854B, "DIMM_D3 Disabled" }, { 0x854C, "DIMM_E1 Disabled" }, { 0x854D, "DIMM_E2 Disabled" }, { 0x854E, "DIMM_E3 Disabled" }, { 0x854F, "DIMM_F1 Disabled" }, { 0x8550, "DIMM_F2 Disabled" }, { 0x8551, "DIMM_F3 Disabled" }, { 0x8552, "DIMM_G1 Disabled" }, { 0x8553, "DIMM_G2 Disabled" }, { 0x8554, "DIMM_G3 Disabled" }, { 0x8555, "DIMM_H1 Disabled" }, { 0x8556, "DIMM_H1 Disabled" }, { 0x8557, "DIMM_H1 Disabled" }, { 0x8558, "DIMM_I1 Disabled" }, { 0x8559, "DIMM_I2 Disabled" }, { 0x855A, "DIMM_I3 Disabled" }, { 0x855B, "DIMM_J1 Disabled" }, { 0x855C, "DIMM_J2 Disabled" }, { 0x855D, "DIMM_J3 Disabled" }, { 0x855E, "DIMM_K1 Disabled" }, { 0x855F, "DIMM_K2 Disabled" }, { 0x8560, "DIMM_A1 SPD fail error" }, { 0x8561, "DIMM_A2 SPD fail error" }, { 0x8562, "DIMM_A3 SPD fail error" }, { 0x8563, "DIMM_B1 SPD fail error" }, { 0x8564, "DIMM_B2 SPD fail error" }, { 0x8565, "DIMM_B3 SPD fail error" }, { 0x8566, "DIMM_C1 SPD fail error" }, { 0x8567, "DIMM_C2 SPD fail error" }, { 0x8568, "DIMM_C3 SPD fail error" }, { 0x8569, "DIMM_D1 SPD fail error" }, { 0x856A, "DIMM_D2 SPD fail error" }, { 0x856B, "DIMM_D3 SPD fail error" }, { 0x856C, "DIMM_E1 SPD fail error" }, { 0x856D, "DIMM_E2 SPD fail error" }, { 0x856E, "DIMM_E3 SPD fail error" }, { 0x856F, "DIMM_F1 SPD fail error" }, { 0x8570, "DIMM_F2 SPD fail error" }, { 0x8571, "DIMM_F3 SPD fail error" }, { 0x8572, "DIMM_G1 SPD fail error" }, { 0x8573, "DIMM_G2 SPD fail error" }, { 0x8574, "DIMM_G3 SPD fail error" }, { 0x8575, "DIMM_H1 SPD fail error" }, { 0x8576, "DIMM_H1 SPD fail error" }, { 0x8577, "DIMM_H1 SPD fail error" }, { 0x8578, "DIMM_I1 SPD fail error" }, { 0x8579, "DIMM_I2 SPD fail error" }, { 0x857A, "DIMM_I3 SPD fail error" }, { 0x857B, "DIMM_J1 SPD fail error" }, { 0x857C, "DIMM_J2 SPD fail error" }, { 0x857D, "DIMM_J3 SPD fail error" }, { 0x857E, "DIMM_K1 SPD fail error" }, { 0x857F, "DIMM_K2 SPD fail error" }, /* some missing here for DIMM_K3 thru DIMM_P3 */ { 0x8604, "Chipset Reclaim of non critical variables complete" }, { 0x8605, "BIOS settings are corrupt" }, { 0x92A3, "Serial port was not detected" }, { 0x92A9, "Serial port resource conflict error" }, { 0xA000, "TPM device not detected" }, { 0xA001, "TPM device missing" }, { 0xA002, "TPM device failure" }, { 0xA003, "TPM device failed self-test" }, { 0xA100, "BIOS ACM errord" }, { 0xA421, "PCI SERR detected" }, { 0xA5A0, "PCI Express PERR" }, { 0xA5A1, "PCI Express SERR" }, { 0xffff , NULL } /*end of list*/ }; /* decode Intel POST codes for some platforms*/ int decode_post_intel(int prod, ushort code, char *outbuf,int szbuf) { int rv = -1; const char *poststr = NULL; if (is_thurley(VENDOR_INTEL,prod)) /* S5520UR/T5520UR (CG2100 or NSN2U)*/ poststr = val2str(code,intel_s5500_post); else if (is_romley(VENDOR_INTEL,prod)) /* S2600CO, CG2200 */ poststr = val2str(code,intel_s2600_post); else switch(prod) { case 0x0028: /*S5000PAL*/ case 0x0029: /*S5000PSL*/ case 0x0811: /*S5000PHB*/ poststr = val2str(code,intel_s5000_post); break; default: break; } if (poststr != NULL) { strncpy(outbuf, poststr, szbuf); rv = 0; } return(rv); } #define ENC_LED_SLEEP 50000 #define ENC_RCMD_SLEEP 500000 int get_hsbp_version_intel(uchar *maj, uchar *min) { uchar idata[8]; uchar rdata[4]; int rv, rlen, i; uchar cc; *maj = 0; *min = 0; /* For Romley/CG2200 get HSBP FW Version */ for (i = 0; i < 3; i++) { idata[0] = 0x0A; // 0x0A idata[1] = 0xD0; idata[2] = 0x01; // return one byte of LED data idata[3] = 0x0A; // HSBP Major version rlen = sizeof(rdata); rv = ipmi_cmd(MASTER_WRITE_READ, idata, 4, rdata, &rlen, &cc, fdebug); if (rv == 0 && cc != 0) rv = cc; os_usleep(0,ENC_LED_SLEEP); /* wait before re-reading values */ if (rv == 0) { *maj = rdata[0]; break; } /*else retry reading it*/ } for (i = 0; i < 3; i++) { idata[0] = 0x0A; // 0x0A idata[1] = 0xD0; idata[2] = 0x01; // return one byte of LED data idata[3] = 0x0B; // HSBP Minor version rlen = sizeof(rdata); rv = ipmi_cmd(MASTER_WRITE_READ, idata, 4, rdata, &rlen, &cc, fdebug); if (rv == 0 && cc != 0) rv = cc; os_usleep(0,ENC_LED_SLEEP); /* wait before re-reading values */ if (rv == 0) { *min = rdata[0]; break; } /*else retry reading it*/ } return (rv); } static uchar rdisk_led_method = 0; /* 0=initial, 1=rcmd, 2=i2c */ static uchar rdisk_led_override = 0x00; /*override is off by default*/ static int get_enc_leds_i2c(uchar *val) { uchar idata[8]; uchar rdata[4]; int rv, rv2, rlen, i; uchar cc; *val = 0; /*make sure to initialize the reading*/ for (i = 0; i < 3; i++) { /* For Romley/Patsburg get disk fault LED status */ idata[0] = 0x0A; // 0x0A idata[1] = 0xD0; idata[2] = 0x01; // return one byte of LED data idata[3] = 0x0E; // LED_Status rlen = sizeof(rdata); rv = ipmi_cmd(MASTER_WRITE_READ, idata, 4, rdata, &rlen, &cc, fdebug); if (rv == 0 && cc != 0) rv = cc; os_usleep(0,ENC_LED_SLEEP); /* wait before re-reading values */ if (rv == 0) { *val = rdata[0]; break; } /*else retry reading the LED Status*/ } /* get & save the override status for use in show() */ idata[0] = 0x0A; // 0x0A idata[1] = 0xD0; idata[2] = 0x01; // return one byte of LED data idata[3] = 0x0D; // LED_Override rlen = sizeof(rdata); rv2 = ipmi_cmd(MASTER_WRITE_READ, idata, 4, rdata, &rlen, &cc, fdebug); if (rv2 == 0 && cc != 0) rv2 = cc; if (rv2 == 0) rdisk_led_override = rdata[0]; return (rv); } static int set_enc_override_i2c(uchar val) { uchar idata[8]; uchar rdata[4]; int rv, rlen, i; uchar cc; if (val != 0) val = 1; for (i = 0; i < 3; i++) { /* Set LED Override to 0=off or 1=on */ idata[0] = 0x0A; // 0x0A bus idata[1] = 0xD0; idata[2] = 0x00; // return no data idata[3] = 0x0D; // LED_Override idata[4] = val; /* turn on override */ rlen = sizeof(rdata); rv = ipmi_cmd(MASTER_WRITE_READ, idata, 5, rdata, &rlen, &cc, fdebug); if (rv == 0 && cc != 0) rv = cc; os_usleep(0,ENC_LED_SLEEP); /* wait before next LED cmd */ if (rv == 0) break; } return(rv); } static int set_enc_leds_i2c(uchar val) { uchar idata[8]; uchar rdata[4]; int rv, rv2, rlen, i; uchar cc; if ((val != 0) && (rdisk_led_override == 0)) { /* setting some LED, so set disk led override*/ rv2 = set_enc_override_i2c(1); } for (i = 0; i < 3; i++) { /* For Romley/Patsburg set disk fault LED status */ idata[0] = 0x0A; // 0x0A bus idata[1] = 0xD0; idata[2] = 0x00; // return one byte of LED data idata[3] = 0x0E; // LED_Status idata[4] = val; rlen = sizeof(rdata); rv = ipmi_cmd(MASTER_WRITE_READ, idata, 5, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; os_usleep(0,ENC_LED_SLEEP); /* wait before next LED cmd */ if (rv == 0) break; } if (val == 0x00) { /* clear the disk led override */ rv2 = set_enc_override_i2c(0); } return (rv); } void show_enc_leds_i2c(uchar val, int numd) { char *enc_pattn = "disk slot %d LED: %s %s\n"; char *pstat; char *pover; uchar mask; int i; if (fdebug) printf("leds = %02x override = %02x\n",val,rdisk_led_override); /* Some backplanes support 6 slots, but max is 8. */ if (numd > 8) numd = 8; mask = 0x01; for (i = 0; i < numd; i++) { if (val & mask) pstat = "ON"; else pstat = "off"; if (rdisk_led_override) pover = "(override)"; else pover = ""; printf(enc_pattn,i,pstat,pover); mask = (mask << 1); } } static int set_enc_override_rcmd(uchar val) { rdisk_led_override = val; return(0); } static int get_enc_leds_rcmd(uchar *val) { uchar rdata[8]; uchar slot[12]; int rv, rlen, i; uchar cc; uchar v = 0; /* This command is only supported on Intel Romley w BMC >= 1.10 */ for (i = 0; i < 12; i++) slot[i] = 0; rlen = sizeof(rdata); rv = ipmi_cmdraw(0x65, 0x30, g_sa,g_bus,g_lun, NULL, 0, rdata, &rlen, &cc, fdebug); if (fdebug) printf("get_enc_leds_rcmd: rv = %d, cc=%02x\n", rv,cc); if ((rv == 0) && (cc != 0)) rv = cc; if (rv == 0) { rdisk_led_override = (rdata[0] & 0x07); /* rdata[1]: Slot 1 to 4 status [7:6]Slot4 status 00-Off 01-Locate (Amber 4HZ) 10-Fail (Amber solid on) 11-Rebuild (Amber 1HZ) [5:4] Slot3 status 00-Off 01-Locate (Amber 4HZ) 10-Fail (Amber solid on) 11-Rebuild (Amber 1HZ) [3:2] Slot2 status 00-Off 01-Locate (Amber 4HZ) 10-Fail (Amber solid on) 11-Rebuild (Amber 1HZ) [1:0] Slot1 status 00-Off 01-Locate (Amber 4HZ) 10-Fail (Amber solid on) 11-Rebuild (Amber 1HZ) */ if (rdata[1] & 0x02) slot[0] = 1; if (rdata[1] & 0x08) slot[1] = 1; if (rdata[1] & 0x20) slot[2] = 1; if (rdata[1] & 0x80) slot[3] = 1; if (rdata[2] & 0x02) slot[4] = 1; if (rdata[2] & 0x08) slot[5] = 1; if (rdata[2] & 0x20) slot[6] = 1; if (rdata[2] & 0x80) slot[7] = 1; if (rdata[3] & 0x02) slot[8] = 1; if (rdata[3] & 0x08) slot[9] = 1; if (rdata[3] & 0x20) slot[10] = 1; if (rdata[3] & 0x80) slot[11] = 1; } for (i = 0; i < 8; i++) { if (slot[i] == 1) v |= (1 << i); } *val = v; return(rv); } static int set_enc_leds_rcmd(uchar val) { uchar idata[8]; uchar rdata[4]; int rlen, rv; uchar cc; if ((val != 0) && (rdisk_led_override == 0)) set_enc_override_rcmd(1); /* This command is only supported on Intel Romley w BMC >= 1.10 */ idata[0] = rdisk_led_override; idata[1] = val; /*first 8 slots*/ idata[2] = 0; idata[3] = 0; rlen = sizeof(rdata); rv = ipmi_cmdraw(0x64, 0x30, g_sa,g_bus,g_lun, idata, 4, rdata, &rlen, &cc, fdebug); if (fdebug) printf("set_enc_leds_rcmd: rv = %d, cc=%02x\n", rv,cc); if ((rv == 0) && (cc != 0)) rv = cc; if (rv == 0) os_usleep(0,ENC_RCMD_SLEEP); if ((rv == 0) && (val == 0)) { /*repeat with override off*/ os_usleep(1,0); /* wait before next LED cmd */ idata[0] = 0; idata[1] = val; idata[2] = 0; idata[3] = 0; rlen = sizeof(rdata); rv = ipmi_cmdraw(0x64, 0x30, g_sa,g_bus,g_lun, idata, 4, rdata, &rlen, &cc, fdebug); if (fdebug) printf("set_enc_leds_rcmd0: rv = %d, cc=%02x\n", rv,cc); if ((rv == 0) && (cc != 0)) rv = cc; if (rv == 0) os_usleep(0,ENC_RCMD_SLEEP); set_enc_override_rcmd(0); } os_usleep(1,0); /* wait before next LED cmd */ return(rv); } static void show_enc_leds_rcmd(uchar val, int numd) { char *enc_pattn = "disk slot %d LED: %s %s\n"; char *pstat; char *pover; uchar mask; int i; if (fdebug) printf("leds = %02x override = %02x\n",val,rdisk_led_override); /* Some backplanes support 6 slots, but max is 8. */ if (numd > 8) numd = 8; mask = 0x01; for (i = 0; i < numd; i++) { if (val & mask) pstat = "ON"; else pstat = "off"; if (rdisk_led_override) pover = "(override)"; else pover = ""; printf(enc_pattn,i,pstat,pover); mask = (mask << 1); } } int set_enc_override_intel(uchar val) { int rv; if (rdisk_led_method == 1) rv = set_enc_override_rcmd(val); else rv = set_enc_override_i2c(val); return(rv); } int get_enc_leds_intel(uchar *val) { int rv = -1; if (rdisk_led_method < 2) rv = get_enc_leds_rcmd(val); if ((rv != 0) && (rdisk_led_method == 0)) rdisk_led_method = 2; if (rdisk_led_method == 2) rv = get_enc_leds_i2c(val); return(rv); } int set_enc_leds_intel(uchar val) { int rv = -1; if (rdisk_led_method < 2) rv = set_enc_leds_rcmd(val); if ((rv != 0) && (rdisk_led_method == 0)) rdisk_led_method = 2; if (rdisk_led_method == 2) rv = set_enc_leds_i2c(val); return(rv); } void show_enc_leds_intel(uchar val, int numd) { if (rdisk_led_method == 1) show_enc_leds_rcmd(val, numd); else show_enc_leds_i2c(val, numd); } #ifdef METACOMMAND int i_inteloem(int argc, char **argv) { printf("%s ver %s\n", progname,progver); return(0); } #endif /* end oem_intel.c */ ipmiutil-3.1.5/util/ipmicmd.c0000644000076400007640000014130113566765324016221 0ustar mgportalloggers/*M* // PVCS: // $Workfile: ipmicmd.c $ // $Revision: 1.12 $ // $Modtime: 23 Feb 2005 11:24:14 $ // $Author: arcress at users.sourceforge.net $ // // Define the ipmi_cmd routine and supporting logic to execute IPMI // commands via one of the supported IPMI drivers: // /dev/ipmi0 /dev/ipmi/0 = MontaVista OpenIPMI driver // /dev/imb = Intel IMB ipmidrvr (comes with ISM) // /dev/ipmikcs /dev/ipmi/kcs = valinux driver by San Mehat // libfreeipmi.so = GNU FreeIPMI user-space library // ldipmidaemon = LanDesk IPMI daemon (user-space process) // // 08/05/02 ARC - created // 08/15/02 ARC - added decode_cc // 10/24/02 ARC - made cmd param ushort to be more unique // 01/29/03 ARC - added MontaVista OpenIPMI driver support // 07/25/03 ARC - added serial-over-lan commands // 07/30/03 ARC - added GetThresholds, fix for ipmi_cmd_raw, // changed some error messages // 09/04/03 ARC - added debug messages for fDriverTyp first time // 05/05/04 ARC - leave _mv device open, rely on each app calling ipmi_close, // helps performance. // 08/10/04 ARC - fix typo in ipmi_cmd_raw/mv: cmd->icmd (thanks Kevin Gao) // 08/26/04 ARC - fix out-of-bounds error in decode_cc // 10/27/04 ARC - added gnu FreeIPMI library support // 11/11/04 ARC - added fdebug to ipmi_getdeviceid & ipmi_open_gnu // 02/23/05 ARC - added routines for LanDesk, fDriverTyp=5 // 07/15/05 ARC - test for ldipmi first, since it hangs KCS if another // driver tries to coexist. // 07/06/06 ARC - better separate driver implementations, cleaner now *M*/ /*----------------------------------------------------------------------* The BSD License 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 Corporation 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. *----------------------------------------------------------------------*/ #ifdef WIN32 #include #include #include #include #include #include #elif defined(EFI) // defined (EFI32) || defined (EFI64) || defined(EFIX64) #include #include #else /* Linux, Solaris, BSD */ #include #include #include #include #include #include #ifndef DOS #include #include #endif #include #include #endif #include "ipmicmd.h" /* has NCMDS, ipmi_cmd_t */ #include "ipmilan2.h" /*includes ipmilan.h also*/ ipmi_cmd_t ipmi_cmds[NCMDS] = { /*if add here, also change NCMDS in ipmicmd.h*/ {/*empty,temp*/ 0, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 0, 20}, {GET_SEL_INFO, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 0, 14}, {GET_SEL_ALLOCATION_INFO,BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 0, 9}, {GET_SEL_ENTRY, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 6, 18}, {RESERVE_SEL, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 0, 2}, {CLEAR_SEL, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 6, 1}, {GET_SEL_TIME, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 6, 4}, {GET_LAN_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 4, 19}, {SET_LAN_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 21, 0}, {GET_LAN_STATS, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 2, 18}, {GET_SER_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 4, 19}, {SET_SER_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 21, 0}, {SET_SER_MUX, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 2, 0}, {GET_PEF_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 3, 22}, {SET_PEF_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 22, 0}, // {SET_PEF_ENABLE, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 4, 0}, /*old*/ {GET_DEVSDR_INFO, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 0, 6}, {GET_DEVICE_SDR, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 6, 18}, {RESERVE_DEVSDR_REP,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 0, 2}, {GET_SENSOR_READING,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 1, 4}, {GET_SENSOR_READING_FACTORS,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 2, 7}, {GET_SENSOR_TYPE, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 1, 2}, {GET_SENSOR_THRESHOLD,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 1, 7}, {SET_SENSOR_THRESHOLD,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 8, 0}, {GET_SENSOR_HYSTERESIS,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 2, 2}, {SET_SENSOR_HYSTERESIS,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 4, 0}, {GET_SDR, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 6, 18},/*full=63*/ {GET_SDR_REPINFO, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 0, 14}, {RESERVE_SDR_REP, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 0, 2}, {GET_FRU_INV_AREA, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 1, 3}, {READ_FRU_DATA, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 4, 18}, {WRITE_FRU_DATA, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN,20 /*3+N(17)*/, 1}, {GET_DEVICE_ID, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 0, 15}, {SET_USER_ACCESS, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 4, 0}, {GET_USER_ACCESS, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 2, 4}, {GET_USER_NAME, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 1, 16}, {SET_USER_NAME, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 17, 0}, {SET_USER_PASSWORD,BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 18, 0}, {MASTER_WRITE_READ,BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 4 /*or 3*/, 1}, {GET_SYSTEM_GUID, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 0, 16}, {WATCHDOG_GET, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 0, 8}, {WATCHDOG_SET, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 6, 0}, {WATCHDOG_RESET, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 0, 0}, {CHASSIS_STATUS, BMC_SA, PUBLIC_BUS, NETFN_CHAS, BMC_LUN, 0, 2}, {CHASSIS_CTL, BMC_SA, PUBLIC_BUS, NETFN_CHAS, BMC_LUN, 1, 0}, {CHASSIS_IDENTIFY, BMC_SA, PUBLIC_BUS, NETFN_CHAS, BMC_LUN, 1, 0}, {GET_POWERON_HOURS,BMC_SA, PUBLIC_BUS, NETFN_CHAS, BMC_LUN, 0, 0}, {SET_BOOT_OPTIONS, BMC_SA, PUBLIC_BUS, NETFN_CHAS, BMC_LUN, 19, 0}, {GET_BOOT_OPTIONS, BMC_SA, PUBLIC_BUS, NETFN_CHAS, BMC_LUN, 3, 18}, {ACTIVATE_SOL1, BMC_SA, PUBLIC_BUS, NETFN_SOL, BMC_LUN, 0, 0}, {SET_SOL_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_SOL, BMC_LUN, 3, 0}, {GET_SOL_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_SOL, BMC_LUN, 4, 2}, {ACTIVATE_SOL2, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 0, 0}, {SET_SOL_CONFIG2, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 3, 0}, {GET_SOL_CONFIG2, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 4, 2}, {GET_SEVT_ENABLE, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 1, 5}, {SET_SEVT_ENABLE, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 6, 0}, {REARM_SENSOR, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 6, 0}, {READ_EVENT_MSGBUF,BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 0, 16}, {GET_EVENT_RECEIVER,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 0, 2}, {GET_CHANNEL_INFO, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 1, 9}, {SET_CHANNEL_ACC, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 3, 0}, {GET_CHANNEL_ACC, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 2, 1} }; /* Subroutine definitions for each driver */ #ifdef EFI int ipmi_open_efi(char fdebug); int ipmi_cmdraw_efi( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); #else #ifdef WIN32 extern int ipmi_cmdraw_ia( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_ia(char fdebug); extern int ipmi_close_ia(void); extern int ipmi_cmdraw_ms(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_ms(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_ms(char fdebug); extern int ipmi_close_ms(void); #elif defined(SOLARIS) extern int ipmi_cmdraw_bmc(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_bmc(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_bmc(char fdebug); extern int ipmi_close_bmc(void); extern int ipmi_cmdraw_lipmi(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_lipmi(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_lipmi(char fdebug); extern int ipmi_close_lipmi(void); #elif defined(LINUX) extern int ipmi_cmdraw_ia( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_ia(char fdebug); extern int ipmi_close_ia(void); extern int ipmi_cmdraw_mv(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_mv(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_mv(char fdebug); extern int ipmi_close_mv(void); extern int ipmi_open_ld(char fdebug); extern int ipmi_close_ld(void); extern int ipmi_cmdraw_ld(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_ld(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_direct(char fdebug); extern int ipmi_close_direct(void); extern int ipmi_cmdraw_direct( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_direct(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_set_max_kcs_loops(int ms); #elif defined(DOS) extern int ipmi_open_direct(char fdebug); extern int ipmi_close_direct(void); extern int ipmi_cmdraw_direct( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_direct(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_set_max_kcs_loops(int ms); #else /* BSD */ extern int ipmi_open_direct(char fdebug); extern int ipmi_close_direct(void); extern int ipmi_cmdraw_direct( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_direct(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_set_max_kcs_loops(int ms); extern int ipmi_cmdraw_mv(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_mv(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_mv(char fdebug); extern int ipmi_close_mv(void); #endif extern int fd_wait(int fd, int nsec, int usec); #endif /* Global Data */ int fDriverTyp = DRV_UNKNOWN; /* 1=IMB driver, 2=VA driver, 3=MV open driver */ /* 4= GNU FreeIPMI, 5= LanDesk, 6= builtin IPMI LAN */ /* 7= direct KCS, 8= direct SMB, 9= IPMI LAN v2.0 */ int fipmi_lan = 0; int fjustpass = 0; FILE *fperr = NULL; FILE *fpdbg = NULL; FILE *fplog = NULL; int fauth_type_set = 0; char fdebug = 0; char log_name[60] = {'\0'}; /*log_name global*/ uchar my_devid[20] = {0,0,0,0,0,0,0,0}; /*saved devid, only needs 16 bytes*/ int gshutdown = 0; /* see ipmilan.c ipmilanplus.c */ LAN_OPT lanp = { "localhost","","", IPMI_SESSION_AUTHTYPE_MD5, IPMI_PRIV_LEVEL_USER, 3, "", 0, RMCP_PRI_RMCP_PORT }; static char *gnode = lanp.node; //char *guser = lanp.user; //char *gpswd = lanp.pswd; //uchar *gaddr = lanp.addr; //int gaddr_len = 0; //int gcipher_suite = 3; /*used in ipmilanplus.c*/ //int gauth_type = IPMI_SESSION_AUTHTYPE_MD5; /*if 0, use any: MD5, MD2, etc.*/ //int gpriv_level = IPMI_PRIV_LEVEL_USER; typedef struct { uchar adrtype; uchar sa; uchar bus; uchar lun; uchar capab; } mc_info; mc_info bmc = { ADDR_SMI, BMC_SA, PUBLIC_BUS, BMC_LUN, 0x8F }; /*BMC via SMI*/ mc_info mc2 = { ADDR_IPMB, BMC_SA, PUBLIC_BUS, BMC_LUN, 0x4F }; /*IPMB target*/ mc_info mymc = { ADDR_IPMB, BMC_SA, PUBLIC_BUS, BMC_LUN, 0x4F }; /*IPMB */ static char bcomma = ','; static mc_info *mc = &bmc; #ifdef WIN32 static char msg_no_drv[] = { /*no Windows driver*/ "Cannot open an IPMI driver: imbdrv.sys or ipmidrv.sys\n"}; #elif defined(SOLARIS) static char msg_no_drv[] = { /*no Solaris driver*/ "Cannot open an IPMI driver: /dev/bmc or /dev/lipmi\n"}; #elif defined(LINUX) static char msg_no_drv[] = { /*no Linux driver*/ "Cannot open an IPMI driver: /dev/imb, /dev/ipmi0, " "/dev/ipmi/0, \n\t " /* "/dev/ipmikcs, /dev/ipmi/kcs, " *no longer support valinux */ #ifdef LINK_LANDESK "ldipmi, " #endif "or direct driverless.\n" }; #elif defined(DOS) static char msg_no_drv[] = { /*no DOS IPMI driver*/ "Cannot open an IPMI direct KCS interface.\n"}; #else static char msg_no_drv[] = { /*no BSD IPMI driver*/ "Cannot open an IPMI driver: /dev/ipmi0 or direct.\n"}; #endif /* From IPMI v1.5/v2.0 spec, Table 5-2 Completion Codes */ #define NUMCC 32 struct { uchar code; char *mesg; } cc_mesg[NUMCC] = { /* Note: completion codes 0x80-0x9f may vary depending on the command. * 0x80 = Invalid Session Handle or Empty Buffer or Unsupported Feature */ {0x00, "Command completed successfully"}, {0x80, "Invalid Session Handle or Empty Buffer"}, {0x81, "Lost Arbitration"}, {0x82, "Bus Error"}, {0x83, "NAK on Write - busy"}, {0x84, "Truncated Read"}, {0x85, "Invalid session ID in request"}, /*for ActivateSession*/ {0x86, "Requested privilege level exceeds limit"}, /*for ActivateSession*/ {0xC0, "Node Busy"}, {0xC1, "Invalid Command"}, {0xC2, "Command invalid for given LUN"}, {0xC3, "Timeout while processing command"}, {0xC4, "Out of space"}, {0xC5, "Reservation ID cancelled or invalid"}, {0xC6, "Request data truncated"}, {0xC7, "Request data length invalid"}, {0xC8, "Request data field length limit exceeded"}, {0xC9, "Parameter out of range"}, {0xCA, "Cannot return requested number of data bytes"}, {0xCB, "Requested sensor, data, or record not present"}, {0xCC, "Invalid data field in request"}, {0xCD, "Command illegal for this sensor/record type"}, {0xCE, "Command response could not be provided"}, {0xCF, "Cannot execute duplicated request"}, {0xD0, "SDR Repository in update mode, no response"}, {0xD1, "Device in firmware update mode, no response"}, {0xD2, "BMC initialization in progress, no response"}, {0xD3, "Destination unavailable"}, {0xD4, "Cannot execute command. Insufficient privilege level"}, {0xD5, "Cannot execute command. Request parameters not supported"}, {0xD6, "Cannot execute command. Subfunction unavailable"}, {0xFF, "Unspecified error"} }; char * decode_cc(ushort icmd, int cc) { static char other_msg[25]; char *pmsg; int i; for (i = 0; i < NUMCC; i++) { if (cc == cc_mesg[i].code) break; } if (i == NUMCC) { /* if not found, show other_msg */ sprintf(other_msg,"Other error 0x%02x",cc); pmsg = other_msg; } else { if ((icmd == READ_EVENT_MSGBUF) && (cc == 0x80)) pmsg = "no data available (queue/buffer empty)"; else pmsg = cc_mesg[i].mesg; } return(pmsg); } char *decode_rv(int rv) { char *msg; static char msgbuf[80]; if (rv == 0x6F) msg = "License not supported"; /*for Dell*/ else if (rv > 0) msg = decode_cc((ushort)0,rv); else switch(rv) { case 0: msg = "completed successfully"; break; case -1: msg = "error -1"; break; case LAN_ERR_SEND_FAIL: msg = "send to BMC failed"; break; case LAN_ERR_RECV_FAIL: msg = "receive from BMC failed"; break; case LAN_ERR_CONNECT: msg = "cannot connect to BMC"; break; case LAN_ERR_ABORT: msg = "abort signal caught"; break; case LAN_ERR_TIMEOUT: msg = "timeout occurred"; break; case LAN_ERR_BADLENGTH: msg = "length greater than max"; break; case LAN_ERR_INVPARAM: msg = "invalid lan parameter"; break; case LAN_ERR_NOTSUPPORT: msg = "request not supported"; break; case LAN_ERR_TOO_SHORT: msg = "receive too short"; break; case LAN_ERR_HOSTNAME: msg = "error resolving hostname"; break; case LAN_ERR_PING: msg = "error during ping"; break; case LAN_ERR_V1: msg = "BMC only supports lan v1"; break; case LAN_ERR_V2: msg = "BMC only supports lan v2"; break; case LAN_ERR_OTHER: msg = "other error"; break; case ERR_NO_DRV: msg = "cannot open IPMI driver"; break; case ERR_BAD_PARAM: msg = "invalid parameter"; break; case ERR_NOT_ALLOWED: msg = "access not allowed"; break; case ERR_USAGE: msg = "usage or help requested"; break; case LAN_ERR_DROPPED: msg = "session dropped by BMC"; break; case ERR_FILE_OPEN: msg = "cannot open file"; break; case ERR_NOT_FOUND: msg = "item not found"; break; case ERR_BMC_MSG: msg = "error getting msg from BMC"; break; /* ipmidir.h: ERGETTINGIPMIMESSAGE -504 */ case ERR_BAD_FORMAT: msg = "bad format"; break; case ERR_BAD_LENGTH: msg = "length less than min"; break; case ERR_SDR_MALFORMED: msg = "an SDR is malformed"; break; default: sprintf(msgbuf,"error %d",rv); msg = msgbuf; break; } return(msg); } int get_cmd_rslen(uchar cmd, uchar netfn) { /* used by ipmicmd_gnu */ int rslen = 0; int i; ushort cmdkey; cmdkey = cmd | (netfn << 8); for (i = 0; i < NCMDS; i++) { if (ipmi_cmds[i].cmdtyp == cmdkey) { rslen = ipmi_cmds[i].rslen; break; } } return(rslen); } /*end get_cmd_rslen()*/ static int ndrivers = NDRIVERS; static struct { int idx; char *tag; } drv_types[NDRIVERS] = { { DRV_IMB, "imb" }, { DRV_MV, "open" }, { DRV_LD, "landesk" }, { DRV_LAN2, "lan2" }, { DRV_LAN2I,"lan2i" }, { DRV_LAN, "lan" }, { DRV_KCS, "kcs" }, { DRV_SMB, "smb" }, { DRV_MS, "ms" }, { DRV_BMC, "sun_bmc" }, { DRV_LIPMI,"sun_lipmi" }, { DRV_SMC, "supermicro" }, { DRV_IBM, "ibm" }, { DRV_HP, "hp" }, /*++++*/ #ifdef EFI { DRV_EFI, "efi" } #else { 0, "" } /*DRV_UNKNOWN*/ #endif }; // { DRV_VA, "va" }, // { DRV_GNU, "free" }, void set_iana(int iana) { my_devid[6] = (iana & 0x0000ff); my_devid[7] = ((iana & 0x00ff00) >> 8); my_devid[8] = ((iana & 0xff0000) >> 16); } void set_mfgid(uchar *devid, int len) { if (devid == NULL) return; if (len > sizeof(my_devid)) len = sizeof(my_devid); memcpy(my_devid,devid,len); } void get_mfgid(int *pvend, int *pprod) { if (pvend != NULL) *pvend = my_devid[6] + (my_devid[7] << 8) + (my_devid[8] << 16); if (pprod != NULL) *pprod = my_devid[9] + (my_devid[10] << 8); } char *show_driver_type(int idx) { int i; char *tag; for (i = 0; i < ndrivers; i++) { if (drv_types[i].idx == idx) { tag = drv_types[i].tag; break; } } if (i >= ndrivers) { /*not found*/ tag = "unknown"; } return(tag); } int get_driver_type(void) { return(fDriverTyp); } int set_driver_type(char *tag) { int rv = 0; int i; /* else if (str_icmp(tag,"lan2") == 0) * leave vendor id as is. */ for (i = 0; i < ndrivers; i++) { if (str_icmp(drv_types[i].tag, tag) == 0) { fDriverTyp = drv_types[i].idx; if (fDriverTyp == DRV_LAN2I) { /*LAN2 Intel*/ set_iana(VENDOR_INTEL); /*VENDOR_INTEL = 0x000157*/ } else if (fDriverTyp == DRV_SMC) { /*supermicro*/ set_iana(VENDOR_SUPERMICRO); /*VENDOR_SUPERMICRO = 0x002A7C*/ fDriverTyp = DRV_LAN; } if (fDriverTyp == DRV_IBM) { /*LAN IBM*/ set_iana(VENDOR_IBM); fDriverTyp = DRV_LAN; } if (fDriverTyp == DRV_HP) { /*LAN2 HP ++++*/ set_iana(VENDOR_HP); fDriverTyp = DRV_LAN2; lanp.auth_type = IPMI_SESSION_AUTHTYPE_NONE; /*HP default*/ } break; } } if (i >= ndrivers) { /*not found*/ fDriverTyp = DRV_UNKNOWN; /*not set yet, so detect*/ rv = 1; // if (fdebugcmd) { printf("Invalid -F argument (%s), valid driver types are:\n",tag); for (i = 0; i < ndrivers; i++) printf("\t%s\n",drv_types[i].tag); } } return(rv); } /* * use_devsdrs * detect whether to use SDR repository or Device SDRs from * the saved GetDeviceID response. * ipmi_getdeviceid saves it into my_devid. */ int use_devsdrs(int picmg) { int fdev, vend, prod; /* set Device SDRs flag as specified in the GetDeviceID */ if ((my_devid[1] & 0x80) == 0x80) fdev = 1; else fdev = 0; if (picmg) return(fdev); /* check for vendor/products that can report the flag wrong */ vend = my_devid[6] + (my_devid[7] << 8) + (my_devid[8] << 16); prod = my_devid[9] + (my_devid[10] << 8); switch(vend) { case VENDOR_INTEL: if ((prod != 0x800) && (prod != 0x808) && (prod != 0x841)) fdev = 0; break; case VENDOR_NSC: fdev = 0; break; case VENDOR_NEC: fdev = 0; break; case VENDOR_DELL: fdev = 0; break; case VENDOR_HP: fdev = 0; break; case VENDOR_SUN: fdev = 0; break; default: break; } return(fdev); } /* get_lan_channel returns the next lan channel starting with chfirst. */ int get_lan_channel(uchar chfirst, uchar *chan) { int ret, j; uchar iData[4]; uchar rData[9]; int rlen; uchar cc; int found = 0; for (j = chfirst; j < 12; j++) { rlen = sizeof(rData); iData[0] = (uchar)j; /*channel #*/ memset(rData,0,9); /*initialize recv data*/ ret = ipmi_cmd(GET_CHANNEL_INFO, iData, 1, rData, &rlen, &cc, fdebug); if (ret == 0xcc || cc == 0xcc) /* special case for ipmi_lan */ continue; if (ret != 0) { if (fdebug) printf("get_chan_info rc = %x\n",ret); break; } /* rData[1] == channel medium type */ if (rData[1] == 4) { /* medium type 4 = 802.3 LAN type*/ if (fdebug) printf("chan[%d] = lan\n",j); found = 1; *chan = (uchar)j; break; } } if (found == 0) ret = -1; return(ret); } int nodeislocal(char *nodename) { if (nodename == NULL) return 1; if (nodename[0] == 0) return 1; if (strcmp(nodename,"localhost") == 0) return 1; return 0; } int set_max_kcs_loops(int ms) { int rv = 0; #if defined(LINUX) rv = ipmi_set_max_kcs_loops(ms); #elif defined(BSD) rv = ipmi_set_max_kcs_loops(ms); #elif defined(DOS) rv = ipmi_set_max_kcs_loops(ms); #endif return(rv); } /* * ipmi_open * This is called by ipmi_cmd and ipmicmd_raw if a session has not * yet been opened (fDriverTyp == DRV_UNKNOWN). * The order to try these drivers could be customized for specific * environments by modifying this routine. * * ipmi_cmd[raw] would call a specific open routine if set_driver_type(). */ int ipmi_open(char fdebugcmd) { int rc = 0; fperr = stderr; fpdbg = stdout; fdebug = fdebugcmd; #ifdef EFI rc = ipmi_open_efi(fdebugcmd); #else if (!nodeislocal(gnode)) { fipmi_lan = 1; } if (fdebugcmd) printf("ipmi_open: driver type = %s\n", show_driver_type(fDriverTyp)); /* first time, so try each */ if (fipmi_lan) { /* Try IPMI LAN 1.5 first */ rc = ipmi_open_lan(gnode,lanp.port,lanp.user,lanp.pswd,fdebugcmd); fDriverTyp = DRV_LAN; if (rc == LAN_ERR_V2) { /* Use IPMI LAN 2.0 if BMC said it only supports LAN2 */ /* This is a violation of IPMI 2.0 Spec section 13.4, * but some HP firmware behaves this way, so handle it. */ fDriverTyp = DRV_LAN2; rc = ipmi_open_lan2(gnode,lanp.user,lanp.pswd,fdebugcmd); if (rc != 0) fDriverTyp = DRV_UNKNOWN; } } else { /* local, not lan */ #ifdef WIN32 rc = ipmi_open_ia(fdebugcmd); if (rc == ACCESS_OK) fDriverTyp = DRV_IMB; else if ((rc = ipmi_open_ms(fdebugcmd)) == ACCESS_OK) fDriverTyp = DRV_MS; else rc = ERR_NO_DRV; #elif defined(SOLARIS) rc = ipmi_open_bmc(fdebugcmd); if (rc == ACCESS_OK) fDriverTyp = DRV_BMC; else if ((rc = ipmi_open_lipmi(fdebugcmd)) == ACCESS_OK) fDriverTyp = DRV_LIPMI; else rc = ERR_NO_DRV; #elif defined(LINUX) if ((rc = ipmi_open_ld(fdebugcmd)) == ACCESS_OK) { fDriverTyp = DRV_LD; ipmi_close_ld(); } else if ((rc = ipmi_open_mv(fdebugcmd)) == ACCESS_OK) { fDriverTyp = DRV_MV; /* ipmi_close_mv(); * leave it open until explicit close */ } else if ((rc = ipmi_open_ia(fdebugcmd)) == ACCESS_OK) { fDriverTyp = DRV_IMB; } else if ((rc = ipmi_open_direct(fdebugcmd)) == ACCESS_OK) { /* set to either DRV_KCS or DRV_SMB */ } else rc = ERR_NO_DRV; #elif defined(DOS) rc = ipmi_open_direct(fdebugcmd); /* sets fDriverTyp to either DRV_KCS or DRV_SMB */ if (rc != ACCESS_OK) rc = ERR_NO_DRV; #else /* BSD or MACOS */ if ((rc = ipmi_open_mv(fdebugcmd)) == ACCESS_OK) { /* FreeBSD "kldload ipmi" has /dev/ipmi0 */ fDriverTyp = DRV_MV; /* ipmi_close_mv(); * leave it open until explicit close */ } else if ((rc = ipmi_open_direct(fdebugcmd)) == ACCESS_OK) { /* sets fDriverTyp to either DRV_KCS or DRV_SMB */ } else rc = ERR_NO_DRV; #endif } /*endelse local, not lan*/ #endif if (fdebugcmd) printf("ipmi_open rc = %d type = %s\n",rc, show_driver_type(fDriverTyp)); return (rc); } int ipmi_close_(void) { int rc = 0; #ifndef EFI switch (fDriverTyp) { #ifdef WIN32 case DRV_IMB: rc = ipmi_close_ia(); break; case DRV_MS: rc = ipmi_close_ms(); break; #elif defined(SOLARIS) case DRV_BMC: rc = ipmi_close_bmc(); break; case DRV_LIPMI: rc = ipmi_close_lipmi(); break; #elif defined(LINUX) case DRV_IMB: rc = ipmi_close_ia(); break; case DRV_MV: rc = ipmi_close_mv(); break; case DRV_LD: rc = ipmi_close_ld(); break; case DRV_SMB: case DRV_KCS: rc = ipmi_close_direct(); break; #elif defined(DOS) case DRV_SMB: case DRV_KCS: rc = ipmi_close_direct(); break; #else /* BSD or MACOS */ case DRV_MV: rc = ipmi_close_mv(); break; case DRV_SMB: case DRV_KCS: rc = ipmi_close_direct(); break; #endif case DRV_LAN: rc = ipmi_close_lan(gnode); break; case DRV_LAN2I: case DRV_LAN2: rc = ipmi_close_lan2(gnode); break; default: break; } /*end switch*/ #endif fDriverTyp = DRV_UNKNOWN; return (rc); } /* don't worry about conflict with other ipmi libs any longer */ int ipmi_close(void) { return(ipmi_close_()); } #if defined(EFI) int ipmi_open_efi(int fdebugcmd) { int rc = 0; static bool BmcLibInitialized = false; if (BmcLibInitialized == false ) { rc = BmcLibInitialize(); if (rc == 0) { BmcLibInitialized = true; fDriverTyp = DRV_EFI; } } return rc; } #define TIMEOUT_EFI (1000*1000) /*see ipmi_timeout_ia*/ int ipmi_cmdraw_efi(uchar cmd, uchar netfn, uchar sa, uchar bus, uchar lun, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { BMC_MESSAGE ReqMsg; BMC_MESSAGE RespMsg; int status = 0; uchar * pc; int sz, i; ReqMsg.DevAdd = sa; ReqMsg.NetFn = netfn; ReqMsg.LUN = lun; ReqMsg.Cmd = cmd; ReqMsg.Len = sdata; for( sz=0; (sz 255) return(LAN_ERR_BADLENGTH); if (fDriverTyp == DRV_UNKNOWN) { /*first time, so find which one */ rc = ipmi_open(fdebugcmd); if (fdebugcmd) fprintf(fpdbg,"Driver type %s, open rc = %d\n", show_driver_type(fDriverTyp),rc); if (rc == ERR_NO_DRV && !fipmi_lan) fprintf(fperr, "%s", msg_no_drv); else if (rc != 0) fprintf(fperr,"ipmi_open error = %d %s\n", rc,decode_rv(rc)); if (rc != 0) return(rc); } /*endif first time*/ icmd = (cmd & 0x00ff) | (netfn << 8); *pcc = 0; /* Check for the size of the response buffer being zero. */ /* This may be valid for some commands, but print a debug warning. */ if (fdebugcmd && (*sresp == 0)) printf("ipmi_cmdraw: warning, sresp==0\n"); #ifdef EFI rc = ipmi_cmdraw_efi(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); #else switch (fDriverTyp) { #ifdef WIN32 case DRV_IMB: rc = ipmi_cmdraw_ia(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; case DRV_MS: rc = ipmi_cmdraw_ms(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; #elif defined(SOLARIS) case DRV_BMC: rc = ipmi_cmdraw_bmc(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; case DRV_LIPMI: rc = ipmi_cmdraw_lipmi(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; #elif defined(LINUX) case DRV_IMB: rc = ipmi_cmdraw_ia(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; case DRV_MV: rc = ipmi_cmdraw_mv(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; case DRV_LD: rc = ipmi_cmdraw_ld( cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; case DRV_SMB: case DRV_KCS: rc = ipmi_cmdraw_direct(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; #elif defined(DOS) case DRV_SMB: case DRV_KCS: rc = ipmi_cmdraw_direct(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; #else /* BSD or MACOS */ case DRV_MV: rc = ipmi_cmdraw_mv(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; case DRV_SMB: case DRV_KCS: rc = ipmi_cmdraw_direct(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; #endif case DRV_LAN: rc = ipmi_cmdraw_lan(gnode, cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; case DRV_LAN2I: case DRV_LAN2: rc = ipmi_cmdraw_lan2(gnode, cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; default: /* no ipmi driver */ rc = ERR_NO_DRV; break; } /*end switch*/ #endif if ((rc >= 0) && (*pcc != 0) && fdebugcmd) { fprintf(fpdbg,"ccode %x: %s\n",*pcc,decode_cc(icmd,(int)*pcc)); } /* clear the temp cmd (OLD) */ // ipmi_cmds[0].cmdtyp = 0; // ipmi_cmds[0].sa = BMC_SA; return(rc); } /* * ipmi_cmd_mc() * This uses the mc pointer to route commands via either the SMI or * IPMB method to the designated mc. * See also ipmi_set_mc and ipmi_restore_mc. */ int ipmi_cmd_mc(ushort icmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { uchar cmd, netfn; int rv; cmd = icmd & CMDMASK; netfn = (icmd & 0xFF00) >> 8; if (sdata > 255) return(LAN_ERR_BADLENGTH); if ((fDriverTyp != DRV_MV) && (mc->adrtype == ADDR_IPMB) && !fipmi_lan) { rv = ipmi_cmd_ipmb(cmd, netfn, mc->sa, mc->bus, mc->lun, pdata, sdata, presp, sresp, pcc, fdebugcmd); } else { /* use ADDR_SMI */ rv = ipmi_cmdraw(cmd, netfn, mc->sa, mc->bus, mc->lun, pdata, sdata, presp, sresp, pcc, fdebugcmd); } return(rv); } int ipmi_cmdraw_mc(uchar cmd, uchar netfn, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rv; if (sdata > 255) return(LAN_ERR_BADLENGTH); if ((fDriverTyp != DRV_MV) && (mc->adrtype == ADDR_IPMB) && !fipmi_lan) { rv = ipmi_cmd_ipmb(cmd, netfn, mc->sa, mc->bus, mc->lun, pdata, sdata, presp, sresp, pcc, fdebugcmd); } else { /* use ADDR_SMI */ rv = ipmi_cmdraw(cmd, netfn, mc->sa, mc->bus, mc->lun, pdata, sdata, presp, sresp, pcc, fdebugcmd); } return(rv); } /* * ipmi_cmd() * * This is the externally exposed subroutine for commands that * are defined in the ipmi_cmds array above. * It calls the ipmi_cmdraw routine for further processing. */ int ipmi_cmd(ushort icmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rc, i; uchar bcmd; uchar netfn, sa, bus, lun; fperr = stderr; fpdbg = stdout; if (sdata > 255) return(LAN_ERR_BADLENGTH); if (fDriverTyp == DRV_UNKNOWN) { /*first time, so find which one */ rc = ipmi_open(fdebugcmd); if (fdebugcmd) fprintf(fpdbg,"Driver type %s, open rc = %d\n", show_driver_type(fDriverTyp),rc); if (rc != 0) { if (rc == ERR_NO_DRV && !fipmi_lan) fprintf(fperr, "%s", msg_no_drv); else fprintf(fperr,"ipmi_open error = %d %s\n", rc,decode_rv(rc)); return(rc); } } /*endif first time*/ for (i = 0; i < NCMDS; i++) { if (ipmi_cmds[i].cmdtyp == icmd) break; } if (i >= NCMDS) { fprintf(fperr, "ipmi_cmd: Unknown command %x\n",icmd); return(-1); } bcmd = icmd & CMDMASK; /* unmask it */ netfn = ipmi_cmds[i].netfn; lun = ipmi_cmds[i].lun; sa = ipmi_cmds[i].sa; bus = ipmi_cmds[i].bus; rc = ipmi_cmdraw(bcmd, netfn, sa, bus, lun, pdata,sdata, presp,sresp, pcc, fdebugcmd); return(rc); } /* MOVED ipmi_cmd_ipmb() to ipmilan.c */ int ipmi_getpicmg(uchar *presp, int sresp, char fdebug) { uchar idata[2]; int rc; uchar cc; /* check that sresp is big enough */ if (sresp < 4) return(-3); idata[0] = PICMG_ID; rc = ipmi_cmdraw(PICMG_GET_PROPERTIES, NETFN_PICMG, BMC_SA, PUBLIC_BUS, BMC_LUN, idata, 1, presp,&sresp, &cc, fdebug); if (rc != ACCESS_OK) return(rc); if (cc != 0) return(cc); return(ACCESS_OK); /* success */ } int ipmi_getdeviceid(uchar *presp, int sresp, char fdebug) { int rc, i; uchar cc; /* check that sresp is big enough (default is 15 bytes for Langley)*/ if (sresp < 15) return(ERR_BAD_LENGTH); rc = ipmi_cmd_mc(GET_DEVICE_ID, NULL, 0, presp,&sresp, &cc, fdebug); if (rc != ACCESS_OK) return(rc); if (cc != 0) return(cc); i = sresp; if (i > sizeof(my_devid)) i = sizeof(my_devid); memcpy(my_devid,presp,i); /* save device id for later use */ if (fdebug) { uchar maj,min,iver; int vend, prod; get_devid_ver(&maj,&min,&iver); get_mfgid(&vend, &prod); printf("devid: firmware ver %x.%02x, IPMI v%02x, vendor=%d prod=%d\n", maj,min,iver,vend,prod); } return(ACCESS_OK); /* success */ } void get_devid_ver(uchar *bmaj, uchar *bmin, uchar *iver) { if (bmaj != NULL) *bmaj = my_devid[2]; if (bmin != NULL) *bmin = my_devid[3]; if (iver != NULL) *iver = my_devid[4]; } void show_devid(uchar b1, uchar b2, uchar i1, uchar i2) { /* b1 = devid[2]; b2 = devid[3]; i2|i1 = devid[4]; */ printf("-- BMC version %x.%02x%c IPMI version %d.%d \n",b1,b2,bcomma,i1,i2); } void ipmi_set_mc(uchar bus, uchar sa, uchar lun, uchar atype) { mc = &mc2; mc->bus = bus; mc->sa = sa; mc->lun = lun; mc->adrtype = atype; /* ADDR_SMI or ADDR_IPMB */ if (fdebug) printf("ipmi_set_mc(%02x,%02x,%02x,%02x)\n",bus,sa,lun,atype); return; } void ipmi_restore_mc(void) { mc = &bmc; return; } void ipmi_get_mc(uchar *bus, uchar *sa, uchar *lun, uchar *type) { /* mc = &bmc or &mc2; */ if (bus != NULL) *bus = mc->bus; if (sa != NULL) *sa = mc->sa; if (lun != NULL) *lun = mc->lun; if (type != NULL) *type = mc->adrtype; /* ADDR_SMI or ADDR_IPMB */ return; } void ipmi_set_mymc(uchar bus, uchar sa, uchar lun, uchar type) { mymc.bus = bus; mymc.sa = sa; mymc.lun = lun; mymc.adrtype = type; /* ADDR_SMI or ADDR_IPMB */ return; } void ipmi_get_mymc(uchar *bus, uchar *sa, uchar *lun, uchar *type) { if (bus != NULL) *bus = mymc.bus; if (sa != NULL) *sa = mymc.sa; if (lun != NULL) *lun = mymc.lun; if (type != NULL) *type = mymc.adrtype; /* ADDR_SMI or ADDR_IPMB */ return; } int ipmi_sendrecv(struct ipmi_rq * req, uchar *rsp, int *rsp_len) { /* compatible with intf->sendrecv() */ int rv; uchar ccode; int rlen; rlen = IPMI_RSPBUF_SIZE; *rsp_len = 0; if ((fDriverTyp != DRV_MV) && (mc->adrtype == ADDR_IPMB) && !fipmi_lan) { rv = ipmi_cmd_ipmb( req->msg.cmd, req->msg.netfn, mc->sa,mc->bus, req->msg.lun, req->msg.data, (uchar)req->msg.data_len, rsp, &rlen, &ccode, fdebug); } else { /* use ADDR_SMI */ rv = ipmi_cmdraw(req->msg.cmd, req->msg.netfn, mc->sa,mc->bus, req->msg.lun, req->msg.data, (uchar)req->msg.data_len, rsp, &rlen, &ccode, fdebug); } if (rv == 0 && ccode != 0) rv = ccode; if (rv == 0) { /*success*/ *rsp_len = rlen; } return (rv); } #ifdef WIN32 static HANDLE con_in = INVALID_HANDLE_VALUE; static DWORD cmodein; static DWORD cmodeold; void tty_setraw(int mode) { // system("@echo off"); con_in = GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(con_in, &cmodein); cmodeold = cmodein; if (mode == 2) { cmodein &= ~(ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT); } else { /* (mode==1) just suppress ECHO */ cmodein &= ~ENABLE_ECHO_INPUT; } SetConsoleMode(con_in, cmodein); } void tty_setnormal(int mode) { // system("echo on"); if (mode == 1) cmodein |= ENABLE_ECHO_INPUT; else cmodein = cmodeold; SetConsoleMode(con_in, cmodein); } int tty_getattr(int *lflag, int *oflag, int *iflag) { *lflag = (int)cmodein; *oflag = 0; *iflag = 0; return(0); } #elif defined(DOS) void tty_setraw(int mode) { return; } void tty_setnormal(int mode) { return; } int tty_getattr(int *lflag, int *oflag, int *iflag) { return(-1); } #else /*LINUX, SOLARIS, BSD*/ // #include static struct termios mytty; static struct termios ttyold; static ulong tty_oldflags; int tty_getattr(int *lflag, int *oflag, int *iflag) { int rv; static struct termios outtty; rv = tcgetattr(STDOUT_FILENO, &outtty); if (rv == 0) { *lflag = outtty.c_lflag; *oflag = outtty.c_oflag; *iflag = outtty.c_iflag; } return(rv); } void tty_setraw(int mode) { int i; // system("stty -echo"); i = tcgetattr(STDIN_FILENO, &mytty); if (i == 0) { tty_oldflags = mytty.c_lflag; ttyold = mytty; #ifdef SOLARIS mytty.c_iflag |= IGNPAR; mytty.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); mytty.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL); mytty.c_lflag &= ~IEXTEN; /* mytty.c_oflag &= ~OPOST; // this causes NL but no CR on output */ mytty.c_cc[VMIN] = 1; mytty.c_cc[VTIME] = 0; i = tcsetattr(STDIN_FILENO, TCSADRAIN, &mytty); #else if (mode == 2) { /*raw mode*/ mytty.c_lflag &= ~(ICANON | ISIG | ECHO); // mytty.c_oflag &= ~ONLCR; /* do not map NL to CR-NL on output */ } else /* (mode==1) just suppress ECHO */ mytty.c_lflag &= ~ECHO; i = tcsetattr(STDIN_FILENO, TCSANOW, &mytty); #endif } } void tty_setnormal(int mode) { // system("stty echo"); if (mode == 1) mytty.c_lflag |= ECHO; else { /*(mode==2)*/ mytty.c_lflag = tty_oldflags; mytty = ttyold; } tcsetattr(STDIN_FILENO, TCSANOW, &mytty); #ifdef SOLARIS tcsetattr(fileno(stdin), TCSADRAIN, &mytty); #endif } #endif static char *my_getline(char *prompt, char fwipe) { /* getline is the same format as readline, but much simpler, and portable. */ static char linebuf[128]; int c, i; if (prompt != NULL) printf("%s\n",prompt); if (fwipe) tty_setraw(1); for (i = 0; i < (sizeof(linebuf)-1); i++) { c = getc(stdin); if (c == EOF) break; if (c == '\n') break; if ((c < 0x20) || (c > 0x7F)) break; /*out of bounds for ASCII */ linebuf[i] = c & 0xff; } linebuf[i] = 0; if (fwipe) { for (c = 0; c < i; c++) putc('*',stdout); putc('\n',stdout); tty_setnormal(1); } if (i == 0) return NULL; return(linebuf); } static char *getline_wipe(char *prompt) { return(my_getline(prompt,1)); } void set_debug(void) { fdebug = 1; } char is_remote(void) { return((char)fipmi_lan); } int get_lan_options(char *node, char *user, char *pswd, int *auth, int *priv, int *cipher, void *addr, int *addr_len) { if (fipmi_lan == 0) return(-1); if (node != NULL) strcpy(node,lanp.node); if (user != NULL) strcpy(user,lanp.user); if (pswd != NULL) strcpy(pswd,lanp.pswd); if (auth != NULL) *auth = lanp.auth_type; if (priv != NULL) *priv = lanp.priv; if (cipher != NULL) *cipher = lanp.cipher; if (addr != NULL && lanp.addr_len != 0) memcpy(addr,lanp.addr,lanp.addr_len); if (addr_len != NULL) *addr_len = lanp.addr_len; return(0); } int set_lan_options(char *node, char *user, char *pswd, int auth, int priv, int cipher, void *addr, int addr_len) { int rv = 0; if (node != NULL) { strncpy(lanp.node,node,SZGNODE); lanp.node[SZGNODE] = '\0'; gnode = lanp.node; fipmi_lan = 1; } if (user != NULL) { strncpy(lanp.user,user,SZGNODE); lanp.user[SZGNODE] = '\0'; } if (pswd != NULL) { strncpy(lanp.pswd,pswd,PSW_MAX); lanp.pswd[PSW_MAX] = '\0'; } if (auth > 0 && auth <= 5) { lanp.auth_type = auth; } else rv = ERR_BAD_PARAM; if (priv > 0 && priv <= 5) { lanp.priv = priv; } else rv = ERR_BAD_PARAM; if (cipher >= 0 && cipher <= 17) { lanp.cipher = cipher; } else rv = ERR_BAD_PARAM; if ((addr != NULL) && (addr_len > 15) && (addr_len <= sizeof(lanp.addr))) { memcpy(lanp.addr,addr,addr_len); lanp.addr_len = addr_len; } ipmi_flush_lan(gnode); return(rv); } void parse_lan_options(int c, char *popt, char fdebugcmd) { #if defined(EFI) | defined(DOS) return; #else int i; static int fset_dtype = 0; uchar sa; char *p = NULL; switch(c) { case 'p': i = atoi(popt); if (i > 0) lanp.port = i; else printf("-p port %d < 0, defaults to %d\n", i,RMCP_PRI_RMCP_PORT); break; case 'F': /* force driver type */ i = set_driver_type(popt); if (i == 0) fset_dtype = 1; break; case 'T': /* auth type */ i = atoi(popt); if (i >= 0 && i <= 5) lanp.auth_type = i; fauth_type_set = 1; break; case 'V': /* priv level */ i = atoi(popt); if (i > 0 && i <= 5) lanp.priv = i; break; case 'J': i = atoi(popt); if (i >= 0 && i <= 17) lanp.cipher = i; else printf("-J cipher suite %d > 17, defaults to %d\n", i,lanp.cipher); if (fset_dtype == 0) i = set_driver_type("lan2"); break; case 'N': strncpy(lanp.node,popt,SZGNODE); /*remote nodename */ lanp.node[SZGNODE] = '\0'; fipmi_lan = 1; break; case 'U': strncpy(lanp.user,popt,SZGNODE); /*remote username */ lanp.user[SZGNODE] = '\0'; /* Hide username from 'ps' */ memset(popt, ' ', strlen(popt)); break; case 'R': case 'P': strncpy(lanp.pswd,popt,PSW_MAX); /*remote password */ lanp.pswd[PSW_MAX] = '\0'; /* Hide password from 'ps' */ memset(popt, ' ', strlen(popt)); break; case 'E': /* get password from IPMI_PASSWORD environment var */ p = getenv("IPMI_PASSWORD"); if (p == NULL) perror("getenv(IPMI_PASSWORD)"); else { strncpy(lanp.pswd,p,PSW_MAX); /*remote password */ if (strlen(p) > PSW_MAX) lanp.pswd[PSW_MAX] = '\0'; if (fdebugcmd) printf("using IPMI_PASSWORD\n"); } break; case 'Y': /* prompt for remote password */ p = getline_wipe("Enter IPMI LAN Password: "); if (p != NULL) { strncpy(lanp.pswd,p,PSW_MAX); /*remote password */ if (strlen(p) > PSW_MAX) lanp.pswd[PSW_MAX] = '\0'; } break; case 'Z': /* set local MC address */ sa = htoi(&popt[0]); /*device slave address*/ ipmi_set_mymc(mc->bus, sa, mc->lun, ADDR_IPMB); break; default: if (fdebugcmd) printf("unrecognized option %c\n",c); break; } ipmi_flush_lan(gnode); #endif } /*end parse_lan_options*/ void print_lan_opt_usage(int opt) { #if defined(EFI) | defined(DOS) return; #else if (opt == 1) /*port ok*/ printf(" -p port UDP Port of target system\n"); printf(" -N node Nodename or IP address of target system\n"); printf(" -U user Username for remote node\n"); printf(" -P/-R pswd Remote Password\n"); printf(" -E use password from Environment IPMI_PASSWORD\n"); printf(" -F force driver type (e.g. imb, lan2)\n"); printf(" -J 0 use lanplus cipher suite 0: 0 thru 14, 3=default\n"); printf(" -T 1 use auth Type: 1=MD2, 2=MD5(default), 4=Pswd\n"); printf(" -V 2 use priVilege level: 2=user(default), 4=admin\n"); printf(" -Y prompt for remote password\n"); printf(" -Z set slave address of local MC\n"); #endif } /*end parse_lan_options*/ char *get_nodename(void) { return(gnode); } void show_outcome(char *prog, int ret) { int err = 0; if (prog == NULL) prog = ""; err = get_LastError(); if (ret == -1 && err != 0) show_LastError(prog,err); printf("%s%c %s\n",prog,bcomma,decode_rv(ret)); } /* end ipmicmd.c */ ipmiutil-3.1.5/util/oem_quanta.c0000644000076400007640000001212113566765324016725 0ustar mgportalloggers/* * oem_quanta.c * Handle Quanta OEM command functions * * Change history: * 01/11/2012 ARCress - included in source tree * *--------------------------------------------------------------------- */ /*M* Copyright (c) 2010 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 Kontron 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*/ #ifdef WIN32 #include #endif #include #include #include #include "ipmicmd.h" #include "ievents.h" extern int decode_sensor_intel_nm(uchar *sdr,uchar *reading, char *pstring,int slen); /*oem_intel.c*/ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil quantaoem"; #else static char * progver = "3.08"; static char * progname = "iquantaoem"; #endif static char fdbg = 0; /* * decode_sensor_quanta * inputs: * sdr = the SDR buffer * reading = the 3 or 4 bytes of data from GetSensorReading * pstring = points to the output string buffer * slen = size of the output buffer * outputs: * rv = 0 if this sensor was successfully interpreted here, * non-zero otherwise, to use default interpretations. * pstring = contains the sensor reading interpretation string (if rv==0) */ int decode_sensor_quanta(uchar *sdr,uchar *reading,char *pstring, int slen) { int rv = -1; int vend, prod; if (sdr == NULL || reading == NULL) return(rv); if (pstring == NULL || slen == 0) return(rv); get_mfgid(&vend,&prod); /*saved from ipmi_getdeviceid */ if (vend != VENDOR_QUANTA) return(rv); if (prod != PRODUCT_QUANTA_S99Q) return(rv); /*only handle S99Q product*/ if (sdr[3] != 0x02) return(rv); /*skip if not compact sensor*/ /* OEM SDR for Intel Node Manager */ rv = decode_sensor_intel_nm(sdr,reading,pstring,slen); return(rv); } /* * decode_sel_quanta * inputs: * evt = the 16-byte IPMI SEL event * outbuf = points to the output string buffer * outsz = size of the output buffer * outputs: * rv = 0 if this event was successfully interpreted here, * non-zero otherwise, to use default interpretations. * outbuf = will contain the interpreted event text string (if rv==0) * * Also case 7 was added to mem_str() in ievents.c for Quanta QSSC-S4R. */ int decode_sel_quanta(uchar *evt, char *outbuf, int outsz, char fdesc, char fdebug) { int rv = -1; ushort id; uchar rectype; ulong timestamp; char mybuf[64]; char *type_str = ""; char *gstr = NULL; char *pstr = NULL; int sevid; ushort genid; uchar snum; int vend, prod; fdbg = fdebug; get_mfgid(&vend,&prod); /*saved from ipmi_getdeviceid */ if (vend != VENDOR_QUANTA) return(rv); if (prod != PRODUCT_QUANTA_S99Q) return(rv); /*only handle S99Q product*/ sevid = SEV_INFO; id = evt[0] + (evt[1] << 8); rectype = evt[2]; snum = evt[11]; timestamp = evt[3] + (evt[4] << 8) + (evt[5] << 16) + (evt[6] << 24); genid = evt[7] | (evt[8] << 8); if (genid == 0x0033) gstr = "Bios"; else gstr = "BMC "; if (rectype == 0x02) { sprintf(mybuf,"%02x [%02x %02x %02x]", evt[12],evt[13],evt[14],evt[15]); switch(evt[10]) { /*sensor type*/ case 0xC0: /* CPU Temp Sensor, EvTyp=0x70 */ switch(evt[13]) { /*offset/data1*/ case 0x02: pstr = "Overheat"; sevid = SEV_MAJ; rv = 0; break; default: break; } break; default: break; } } if (rv == 0) { format_event(id,timestamp, sevid, genid, type_str, snum,NULL,pstr,mybuf,outbuf,outsz); } return(rv); } #ifdef METACOMMAND int i_quantaoem(int argc, char **argv) { printf("%s ver %s\n", progname,progver); return(0); } #endif /* end oem_quanta.c */ ipmiutil-3.1.5/util/Makefile.in0000644000000000000000000010015413566765327015121 0ustar rootroot# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = ipmiutil$(EXEEXT) ievents$(EXEEXT) idiscover$(EXEEXT) sbin_PROGRAMS = ipmi_port$(EXEEXT) iseltime$(EXEEXT) EXTRA_PROGRAMS = ipmi_sample$(EXEEXT) ipmi_sample_evt$(EXEEXT) subdir = util DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS) am_idiscover_OBJECTS = idiscover.$(OBJEXT) idiscover_OBJECTS = $(am_idiscover_OBJECTS) idiscover_LDADD = $(LDADD) am__DEPENDENCIES_1 = idiscover_DEPENDENCIES = $(am__DEPENDENCIES_1) am_ievents_OBJECTS = ievents.$(OBJEXT) ievents_OBJECTS = $(am_ievents_OBJECTS) ievents_LDADD = $(LDADD) ievents_DEPENDENCIES = $(am__DEPENDENCIES_1) am_ipmi_port_OBJECTS = ipmi_port.$(OBJEXT) ipmi_port_OBJECTS = $(am_ipmi_port_OBJECTS) ipmi_port_LDADD = $(LDADD) ipmi_port_DEPENDENCIES = $(am__DEPENDENCIES_1) ipmi_sample_SOURCES = ipmi_sample.c ipmi_sample_OBJECTS = ipmi_sample.$(OBJEXT) ipmi_sample_LDADD = $(LDADD) ipmi_sample_DEPENDENCIES = $(am__DEPENDENCIES_1) ipmi_sample_evt_SOURCES = ipmi_sample_evt.c ipmi_sample_evt_OBJECTS = ipmi_sample_evt.$(OBJEXT) ipmi_sample_evt_LDADD = $(LDADD) ipmi_sample_evt_DEPENDENCIES = $(am__DEPENDENCIES_1) am__objects_1 = oem_kontron.$(OBJEXT) oem_fujitsu.$(OBJEXT) \ oem_intel.$(OBJEXT) oem_sun.$(OBJEXT) oem_supermicro.$(OBJEXT) \ oem_dell.$(OBJEXT) oem_quanta.$(OBJEXT) oem_hp.$(OBJEXT) \ oem_newisys.$(OBJEXT) oem_lenovo.$(OBJEXT) oem_asus.$(OBJEXT) \ iekanalyzer.$(OBJEXT) am__objects_2 = ipmicmd.$(OBJEXT) mem_if.$(OBJEXT) ipmidir.$(OBJEXT) \ imbapi.$(OBJEXT) ipmimv.$(OBJEXT) ipmild.$(OBJEXT) \ ipmibmc.$(OBJEXT) ipmilipmi.$(OBJEXT) subs.$(OBJEXT) \ md5.$(OBJEXT) md2.$(OBJEXT) ipmilan.$(OBJEXT) \ ipmilanplus.$(OBJEXT) am__objects_3 = ipmiutil.$(OBJEXT) ialarms.$(OBJEXT) ihealth.$(OBJEXT) \ ievents.$(OBJEXT) ifru.$(OBJEXT) ifru_picmg.$(OBJEXT) \ igetevent.$(OBJEXT) ireset.$(OBJEXT) icmd.$(OBJEXT) \ ilan.$(OBJEXT) isensor.$(OBJEXT) isel.$(OBJEXT) \ iserial.$(OBJEXT) iwdt.$(OBJEXT) isol.$(OBJEXT) \ idiscover.$(OBJEXT) iconfig.$(OBJEXT) ipicmg.$(OBJEXT) \ ifirewall.$(OBJEXT) ifwum.$(OBJEXT) ihpm.$(OBJEXT) \ itsol.$(OBJEXT) idcmi.$(OBJEXT) iuser.$(OBJEXT) \ $(am__objects_1) $(am__objects_2) am_ipmiutil_OBJECTS = $(am__objects_3) ipmiutil_OBJECTS = $(am_ipmiutil_OBJECTS) ipmiutil_LDADD = $(LDADD) ipmiutil_DEPENDENCIES = $(am__DEPENDENCIES_1) iseltime_SOURCES = iseltime.c iseltime_OBJECTS = iseltime.$(OBJEXT) iseltime_LDADD = $(LDADD) iseltime_DEPENDENCIES = $(am__DEPENDENCIES_1) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(idiscover_SOURCES) $(ievents_SOURCES) $(ipmi_port_SOURCES) \ ipmi_sample.c ipmi_sample_evt.c $(ipmiutil_SOURCES) iseltime.c DIST_SOURCES = $(idiscover_SOURCES) $(ievents_SOURCES) \ $(ipmi_port_SOURCES) ipmi_sample.c ipmi_sample_evt.c \ $(ipmiutil_SOURCES) iseltime.c ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CROSS_CFLAGS = @CROSS_CFLAGS@ CROSS_LFLAGS = @CROSS_LFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GPL_CFLAGS = @GPL_CFLAGS@ GREP = @GREP@ IA64_CFLAGS = @IA64_CFLAGS@ INIT_DIR = @INIT_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INS_LIB = @INS_LIB@ LANDESK_CFLAGS = @LANDESK_CFLAGS@ LANDESK_LDADD = @LANDESK_LDADD@ LANPLUS_CFLAGS = @LANPLUS_CFLAGS@ LANPLUS_CRYPTO = @LANPLUS_CRYPTO@ LANPLUS_LDADD = @LANPLUS_LDADD@ LANPLUS_LIB = @LANPLUS_LIB@ LANPLUS_SAM = @LANPLUS_SAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LD_SAMX = @LD_SAMX@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSENSORS = @LIBSENSORS@ LIBTOOL = @LIBTOOL@ LIB_DIR = @LIB_DIR@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OS_CFLAGS = @OS_CFLAGS@ OS_DRIVERS = @OS_DRIVERS@ OS_LFLAGS = @OS_LFLAGS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_DIR = @PKG_DIR@ RANLIB = @RANLIB@ SAM2OBJ = @SAM2OBJ@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SHR_LINK = @SHR_LINK@ STRIP = @STRIP@ SUBDIR_S = @SUBDIR_S@ SYSTEMD_DIR = @SYSTEMD_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = $(datadir)/locale localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgconfigdir = @pkgconfigdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ OS_CF = @OS_CFLAGS@ @CROSS_CFLAGS@ OS_LF = @OS_LFLAGS@ @CROSS_LFLAGS@ # To build ipmiutil, need to use METACFLAGS for each .c/.o # The LanDesk library is proprietary, so it is incompatible with ALLOW_GPL. # To build with LanDesk support: # First copy the library to ../lib/libipmiapi.a # Then ./configure --enable-landesk # Result: # AM_CPPFLAGS += -DLINK_LANDESK # LDADD += -lipmiapi -L../lib # For lanplus plugin support (IPMI LAN 2.0 RMCP+) used by SOL: # If ./configure --disable-lanplus # AM_CPPFLAGS += # LDADD += # Otherwise default result is lanplus enabled: # AM_CPPFLAGS += -DHAVE_LANPLUS # LDADD += -L../lib -lipmi_lanplus -L/usr/local/lib -lcrypto # LDADD += -L../lib -lintf_lanplus -L/usr/local/lib -lcrypto (older) # Could also use CMDMOD += ipmilan2.c instead, if completed. AM_CPPFLAGS = $(OS_CF) -DLOCALEDIR=\"$(localedir)\" -I.. @IA64_CFLAGS@ \ @GPL_CFLAGS@ -I. -I.. -DMETACOMMAND @LANDESK_CFLAGS@ \ @LANPLUS_CFLAGS@ $(am__empty) LDADD = $(OS_LF) -lpthread @LANDESK_LDADD@ @LANPLUS_LIB@ \ @LANPLUS_CRYPTO@ $(am__empty) # usu LD_SAMX = ../lib/libipmi_lanplus.a -lcrypto LDSAM = $(OS_LF) @LD_SAMX@ CFLAGS_SAMX = -O2 -g -I. -I.. $(OS_CF) @LANPLUS_CFLAGS@ CFLAGS_SAM = -O2 -g -I. -I.. $(OS_CF) # May be /usr/bin/install or /bin/install INSTALLBIN = install -c extradir = $(datadir)/ipmiutil inc_dir = $(includedir) tmpobj = obj tmpwin = tmp LIBDIR = @LIB_DIR@ CMDMOD = ipmicmd.c mem_if.c ipmidir.c imbapi.c ipmimv.c ipmild.c \ ipmibmc.c ipmilipmi.c subs.c md5.c md2.c ipmilan.c \ ipmilanplus.c # CMDMOD = ipmicmd.c mem_if.c @OS_DRIVERS@ # am: configure substitutions are not allowed in _SOURCES variables TMPOBJL = $(tmpobj)/ipmilanL.o $(tmpobj)/ipmilanplusL.o TMPOBJA = $(tmpobj)/ipmilanA.o $(tmpobj)/ipmilanplusA.o LIBOBJ = ipmicmd.o mem_if.o ipmidir.o imbapi.o ipmimv.o ipmild.o ipmibmc.o ipmilipmi.o subs.o md5.o md2.o @LIBSENSORS@ OEMMOD = oem_kontron.c oem_fujitsu.c oem_intel.c oem_sun.c oem_supermicro.c oem_dell.c oem_quanta.c oem_hp.c oem_newisys.c oem_lenovo.c oem_asus.c iekanalyzer.c # usu SAM2OBJ = isensor2.o ievents2.o L2OBJ = @SAM2OBJ@ METASOURCE = ipmiutil.c ialarms.c ihealth.c ievents.c ifru.c ifru_picmg.c igetevent.c ireset.c icmd.c ilan.c isensor.c isel.c iserial.c iwdt.c isol.c idiscover.c iconfig.c ipicmg.c ifirewall.c ifwum.c ihpm.c itsol.c idcmi.c iuser.c $(OEMMOD) $(CMDMOD) LANPLUS_OBJ = $(shell ar t @LANPLUS_LIB@ 2>/dev/null) DEV_LIB = libipmiutil.a # SHRLINK is libipmiutil.so.1 if OS supports it SHRLINK = @SHR_LINK@ SHR_LIB = $(SHRLINK) SHR_BLIB = libipmiutil.so LDNAME = -Wl,-soname,$(SHR_LIB) TESTPROGS = libimbapi.a iconfig ipmimv ifruset ipmi_sample2 ialarms_enc # OLDPROGS are old/previous binaries that may exist and need to be deleted. OLDPROGS = alarms bmchealth fruconfig getevent hwreset icmd isolconsole pefconfig sensor showsel tmconfig wdt ipmiutil_SOURCES = $(METASOURCE) ievents_SOURCES = ievents.c idiscover_SOURCES = idiscover.c ipmi_port_SOURCES = ipmi_port.c EXTRA_DIST = imb_api.h ipmicmd.h ipmidir.h ipmilan.h ipmilanplus.h AnsiTerm.h ifirewall.h ifwum.h ihpm.h ipicmg.h ipmiutil.h md2.h oem_dell.h oem_fujitsu.h oem_intel.h oem_kontron.h oem_sun.h idcmi.h isensor.h iekanalyzer.h all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign util/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign util/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)" @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ialarms.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icmd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iconfig.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idcmi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idiscover.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iekanalyzer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ievents.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifirewall.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifru.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifru_picmg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifwum.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/igetevent.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ihealth.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ihpm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ilan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imbapi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipicmg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_port.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sample.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sample_evt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmibmc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmicmd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmidir.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmilan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmilanplus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmild.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmilipmi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmimv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmiutil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ireset.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isel.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iseltime.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isensor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iserial.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isol.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/itsol.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iuser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iwdt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem_if.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_asus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_dell.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_fujitsu.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_hp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_intel.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_kontron.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_lenovo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_newisys.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_quanta.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_sun.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_supermicro.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subs.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool \ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool clean-sbinPROGRAMS ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-sbinPROGRAMS install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-sbinPROGRAMS # To build an imb api library (libimbapi.a): libimbapi.a: imbapi.c mkdir -p $(tmpobj) $(CC) -I. -I.. $(OS_CF) -fPIC $(CFLAGS) -o $(tmpobj)/imbapi.o -c imbapi.c $(AR) cru libimbapi.a $(tmpobj)/imbapi.o $(RANLIB) libimbapi.a rm -f $(tmpobj)/imbapi.o $(tmpobj)/ipmilanplusL.o: ipmilanplus.c mkdir -p $(tmpobj) $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilanplusL.o -c ipmilanplus.c; $(tmpobj)/ipmilanL.o: ipmilan.c mkdir -p $(tmpobj) $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilanL.o -c ipmilan.c; $(tmpobj)/ipmilanplusA.o: ipmilanplus.c mkdir -p $(tmpobj) $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilanplusA.o -c ipmilanplus.c; $(tmpobj)/ipmilanA.o: ipmilan.c mkdir -p $(tmpobj) $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilanA.o -c ipmilan.c; # Build a lib to support all of the IPMI drivers (libipmiutil.a) # If LANPLUS_SAM = yes, include LANPLUS_OBJ, else do not. # See configure --enable-liblanplus to change this $(DEV_LIB): $(CMDMOD:.c=.o) @LANPLUS_LIB@ @LIBSENSORS@ $(TMPOBJL) $(TMPOBJA) if [ "x@LANPLUS_SAM@" = "xyes" ]; then \ ar x @LANPLUS_LIB@ ; \ $(AR) cru $(DEV_LIB) $(LIBOBJ) $(TMPOBJL) $(LANPLUS_OBJ); \ $(RANLIB) $(DEV_LIB); \ else \ $(AR) cru $(DEV_LIB) $(LIBOBJ) $(TMPOBJA) ; \ $(RANLIB) $(DEV_LIB) ; \ fi $(SHR_LIB): $(CMDMOD:.c=.o) @LANPLUS_LIB@ @LIBSENSORS@ $(TMPOBJL) $(TMPOBJA) if [ "x@LANPLUS_SAM@" = "xyes" ]; then \ ar x @LANPLUS_LIB@ ; \ $(CC) $(LDFLAGS) -shared $(LDNAME) -o $(SHR_LIB) $(LIBOBJ) $(TMPOBJL) $(LANPLUS_OBJ); \ else \ $(CC) $(LDFLAGS) -shared $(LDNAME) -o $(SHR_LIB) $(LIBOBJ) $(TMPOBJA) ; \ fi $(SHR_BLIB): $(SHR_LIB) ln -s $(SHR_LIB) $(SHR_BLIB) idiscover$(EXEEXT): idiscover.c $(CC) $(CFLAGS_SAM) $(LDFLAGS) $(OS_LF) -o idiscover idiscover.c ipmimv$(EXEEXT): ipmimv.c $(CC) $(CFLAGS_SAM) $(LDFLAGS) -DTEST_BIN -o ipmimv ipmimv.c ievents$(EXEEXT): ievents.c $(CC) $(CFLAGS_SAM) $(LDFLAGS) -DALONE -o ievents ievents.c isensor2.o: isensor.c $(CC) $(CFLAGS_SAM) -o isensor2.o -c isensor.c ievents2.o: ievents.c $(CC) $(CFLAGS_SAM) -DSENSORS_OK -o ievents2.o -c ievents.c ifru_picmg2.o: ifru_picmg.c $(CC) $(CFLAGS_SAM) -o ifru_picmg2.o -c ifru_picmg.c ifru2.o: ifru.c $(CC) $(CFLAGS_SAM) -o ifru2.o -c ifru.c isel2.o: isel.c $(CC) $(CFLAGS_SAM) -o isel2.o -c isel.c ipmi_sample.o: ipmi_sample.c $(CC) $(CFLAGS_SAM) -c ipmi_sample.c ipmi_sample2.o: ipmi_sample.c $(CC) $(CFLAGS_SAM) -D GET_SENSORS -D GET_FRU -o ipmi_sample2.o -c ipmi_sample.c ipmi_sample_evt.o: ipmi_sample_evt.c $(CC) $(CFLAGS_SAM) -o ipmi_sample_evt.o -c ipmi_sample_evt.c ipmi_sample$(EXEEXT): $(DEV_LIB) ipmi_sample.o isensor.o ievents.o $(CC) -g -O2 -o ipmi_sample ipmi_sample.o $(DEV_LIB) $(LDFLAGS) $(LDSAM) # To build ipmi_sample with GET_SENSORS enabled, need isensors.o, ievents.o # Note that this does not include oem_intel, etc. for OEM SEL decoding. ipmi_sample2$(EXEEXT): $(DEV_LIB) ipmi_sample2.o ifru2.o isel2.o ifru_picmg2.o $(L2OBJ) $(CC) -g -O2 -o ipmi_sample2 ipmi_sample2.o $(L2OBJ) ifru2.o ifru_picmg2.o isel2.o $(DEV_LIB) $(LDFLAGS) $(LDSAM) ipmi_sample_evt$(EXEEXT): $(DEV_LIB) ipmi_sample_evt.o $(L2OBJ) $(CC) -g -O2 -o ipmi_sample_evt ipmi_sample_evt.o $(L2OBJ) $(DEV_LIB) $(LDFLAGS) $(LDSAM) ialarms2.o: ialarms.c $(CC) $(CFLAGS_SAM) -DTEST_ENC -o ialarms2.o -c ialarms.c oem_intel2.o: oem_intel.c $(CC) $(CFLAGS_SAM) -DNO_EVENTS -o oem_intel2.o -c oem_intel.c ialarms_enc$(EXEEXT): $(DEV_LIB) ialarms2.o oem_intel2.o $(CC) -g -O2 -o ialarms_enc ialarms2.o oem_intel2.o $(DEV_LIB) $(LDFLAGS) $(LDSAM) ifruset.o: ifruset.c $(CC) $(CFLAGS_SAM) -c ifruset.c ifruset$(EXEEXT): $(DEV_LIB) ifruset.o ifru_picmg2.o $(CC) -g -O2 -o ifruset ifruset.o ifru_picmg2.o $(DEV_LIB) $(LDFLAGS) $(LDADD) iseltime.o: iseltime.c $(CC) $(CFLAGS_SAM) -c iseltime.c iseltime$(EXEEXT): $(DEV_LIB) iseltime.o $(CC) -g -O2 -o iseltime iseltime.o $(DEV_LIB) $(LDFLAGS) $(LDADD) iconfig$(EXEEXT): iconfig.c $(DEV_LIB) $(CC) $(CFLAGS_SAM) $(LDFLAGS) -o iconfig iconfig.c $(DEV_LIB) @LANPLUS_CRYPTO@ ipmi_port$(EXEEXT): ipmi_port.c $(CC) $(CFLAGS_SAM) $(LDFLAGS) -o ipmi_port ipmi_port.c # @LANPLUS_LIB@ is ../lib/libipmi_lanplus.a ../lib/libipmi_lanplus.a: cd ../lib; make ipmiutil$(EXEEXT): $(METASOURCE:.c=.o) @LANPLUS_LIB@ $(CC) $(CFLAGS) $(LDFLAGS) -o ipmiutil $(METASOURCE:.c=.o) $(LDADD) all-am: Makefile $(bin_PROGRAMS) $(sbin_PROGRAMS) $(EXTRA_PROGRAMS) $(DEV_LIB) $(SHRLINK) install-data-am: $(EXTRA_PROGRAMS) $(DEV_LIB) $(SHRLINK) @INS_LIB@ mkdir -p $(DESTDIR)$(extradir) @INS_LIB@ mkdir -p $(DESTDIR)$(LIBDIR) @INS_LIB@ mkdir -p $(DESTDIR)$(inc_dir) @INS_LIB@ cp -f ipmi_sample.c $(DESTDIR)$(extradir) @INS_LIB@ cp -f ipmi_sample_evt.c $(DESTDIR)$(extradir) @INS_LIB@ cp -f ipmicmd.h $(DESTDIR)$(inc_dir) @INS_LIB@ cp -f isensor.c ievents.c $(DESTDIR)$(extradir) @INS_LIB@ cp -f isensor.h ievents.h $(DESTDIR)$(extradir) @INS_LIB@ cp -f Makefile.sample $(DESTDIR)$(extradir)/Makefile @INS_LIB@ cp -f $(DEV_LIB) $(DESTDIR)$(LIBDIR) @INS_LIB@ if [ "x$(SHRLINK)" != "x" ]; then \ @INS_LIB@ cp -f $(SHRLINK) $(DESTDIR)$(LIBDIR) ; \ @INS_LIB@ cd $(DESTDIR); ln -sf $(LIBDIR)/$(SHRLINK) $(DESTDIR)$(LIBDIR)/$(SHR_BLIB); \ @INS_LIB@ fi clean-generic: rm -f $(DEV_LIB) $(EXTRA_PROGRAMS) $(OLDPROGS) $(TESTPROGS) $(SHRLINK) if [ -d $(tmpobj) ]; then rm -rf $(tmpobj) ; fi if [ -d $(tmpwin) ]; then rm -rf $(tmpwin) ; fi rm -f *.log *.tmp debug*.list *.o *.pdb *.lo *.la *.so # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ipmiutil-3.1.5/util/oem_dell.h0000644000076400007640000004621513566765324016374 0ustar mgportalloggers/**************************************************************************** Copyright (c) 2008, Dell 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: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 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. - Neither the name of Dell Inc 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. *****************************************************************************/ #ifndef IPMI_DELLOEM_H #define IPMI_DELLOEM_H #if HAVE_CONFIG_H # include #endif #ifdef HAVE_ATTRIBUTE_PACKING /* this attribute is not very portable */ #define ATTRIBUTE_PACKING __attribute__ ((packed)) #else /* use #pragma pack(1) instead */ #define ATTRIBUTE_PACKING #endif #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define IPMI_SET_SYS_INFO 0x58 #define IPMI_GET_SYS_INFO 0x59 /* Dell selector for LCD control - get and set unless specified */ #define IPMI_DELL_LCD_STRING_SELECTOR 0xC1 /* RW get/set the user string */ #define IPMI_DELL_LCD_CONFIG_SELECTOR 0xC2 /* RW set to user/default/none */ #define IPMI_DELL_LCD_GET_CAPS_SELECTOR 0xCF /* RO use when available*/ #define IPMI_DELL_LCD_STRINGEX_SELECTOR 0xD0 /* RW get/set the user string use first when available*/ #define IPMI_DELL_LCD_STATUS_SELECTOR 0xE7 /* LCD string when config set to default.*/ #define IPMI_DELL_PLATFORM_MODEL_NAME_SELECTOR 0xD1 /* LCD string when config set to default.*/ /* Dell defines for picking which string to use */ #define IPMI_DELL_LCD_CONFIG_USER_DEFINED 0x00 /* use string set by user*/ #define IPMI_DELL_LCD_CONFIG_DEFAULT 0x01 /* use platform model name*/ #define IPMI_DELL_LCD_CONFIG_NONE 0x02 /* blank*/ #define IPMI_DELL_LCD_iDRAC_IPV4ADRESS 0x04 /* use string set by user*/ #define IPMI_DELL_LCD_IDRAC_MAC_ADDRESS 0x08 /* use platform model name*/ #define IPMI_DELL_LCD_OS_SYSTEM_NAME 0x10 /* blank*/ #define IPMI_DELL_LCD_SERVICE_TAG 0x20 /* use string set by user*/ #define IPMI_DELL_LCD_iDRAC_IPV6ADRESS 0x40 /* use string set by user*/ #define IPMI_DELL_LCD_AMBEINT_TEMP 0x80 /* use platform model name*/ #define IPMI_DELL_LCD_SYSTEM_WATTS 0x100 /* blank*/ #define IPMI_DELL_LCD_ASSET_TAG 0x200 #define IPMI_DELL_LCD_ERROR_DISP_SEL 0x01 /* use platform model name*/ #define IPMI_DELL_LCD_ERROR_DISP_VERBOSE 0x02 /* blank*/ #define IPMI_DELL_IDRAC_VALIDATOR 0xDD #define IPMI_DELL_POWER_CAP_STATUS 0xBA #define IPMI_DELL_AVG_POWER_CONSMP_HST 0xEB #define IPMI_DELL_PEAK_POWER_CONSMP_HST 0xEC #define SYSTEM_BOARD_SYSTEM_LEVEL_SENSOR_NUM 0x98 #define IDRAC_11G 1 #define IDRAC_12G 2 // Return Error code for license #define LICENSE_NOT_SUPPORTED 0x6F #define VFL_NOT_LICENSED 0x33 #define btuphr 0x01 #define watt 0x00 #define IPMI_DELL_POWER_CAP 0xEA #define percent 0x03 /* Not on all Dell servers. If there, use it.*/ #pragma pack(1) typedef struct _tag_ipmi_dell_lcd_caps { uint8_t parm_rev; /* 0x11 for IPMI 2.0 */ uint8_t char_set; /* always 1 for printable ASCII 0x20-0x7E */ uint8_t number_lines; /* 0-4, 1 for 9G. 10G tbd */ uint8_t max_chars[4]; /* 62 for triathlon, 0 if not present (glacier) */ /* [0] is max chars for line 1 */ }IPMI_DELL_LCD_CAPS; #define IPMI_DELL_LCD_STRING_LENGTH_MAX 62 /* Valid for 9G. Glacier ??. */ #define IPMI_DELL_LCD_STRING1_SIZE 14 #define IPMI_DELL_LCD_STRINGN_SIZE 16 /* vFlash subcommands */ #define IPMI_GET_EXT_SD_CARD_INFO 0xA4 typedef struct _tag_ipmi_dell_lcd_string { uint8_t parm_rev; /* 0x11 for IPMI 2.0 */ uint8_t data_block_selector; /* 16-byte data block number to access, 0 based.*/ union { struct { uint8_t encoding : 4; /* 0 is printable ASCII 7-bit */ uint8_t length; /* 0 to max chars from lcd caps */ uint8_t data[IPMI_DELL_LCD_STRING1_SIZE]; /* not zero terminated. */ }selector_0_string; uint8_t selector_n_data[IPMI_DELL_LCD_STRINGN_SIZE]; }lcd_string; } ATTRIBUTE_PACKING IPMI_DELL_LCD_STRING; /* Only found on servers with more than 1 line. Use if available. */ typedef struct _tag_ipmi_dell_lcd_stringex { uint8_t parm_rev; /* 0x11 for IPMI 2.0 */ uint8_t line_number; /* LCD line number 1 to 4 */ uint8_t data_block_selector; /* 16-byte data block number to access, 0 based.*/ union { struct { uint8_t encoding : 4; /* 0 is printable ASCII 7-bit */ uint8_t length; /* 0 to max chars from lcd caps */ uint8_t data[IPMI_DELL_LCD_STRING1_SIZE]; /* not zero terminated. */ } selector_0_string; uint8_t selector_n_data[IPMI_DELL_LCD_STRINGN_SIZE]; } lcd_string; } ATTRIBUTE_PACKING IPMI_DELL_LCD_STRINGEX; typedef struct _lcd_status { char vKVM_status; char lock_status; char Resv1; char Resv; } ATTRIBUTE_PACKING LCD_STATUS; typedef struct _lcd_mode { uint8_t parametersel; uint32_t lcdmode; uint16_t lcdqualifier; uint32_t capabilites; uint8_t error_display; uint8_t Resv; } ATTRIBUTE_PACKING LCD_MODE; #pragma pack() #define PARAM_REV_OFFSET (uint8_t)(0x1) #define LOM_MACTYPE_ETHERNET 0 #define LOM_MACTYPE_ISCSI 1 #define LOM_MACTYPE_RESERVED 3 #define LOM_ETHERNET_ENABLED 0 #define LOM_ETHERNET_DISABLED 1 #define LOM_ETHERNET_PLAYINGDEAD 2 #define LOM_ETHERNET_RESERVED 3 #define LOM_ACTIVE 1 #define LOM_INACTIVE 0 #define MACADDRESSLENGH 6 #define MAX_LOM 8 #define IPMI_NETFN_SE (uint8_t)(0x04) #define IPMI_NETFN_APP (uint8_t)(0x06) //NETFN_APP #define IPMI_NETFN_STORAGE (uint8_t)(0x0a) //NETFN_STOR #define IPMI_CMD_GET_SEL_TIME 0x48 #define GET_FRU_INFO 0x10 #define GET_FRU_DATA 0x11 #define BSWAP_16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8)) #define APP_NETFN (uint8_t)(0x6) #define GET_SYSTEM_INFO_CMD (uint8_t)(0x59) #define EMB_NIC_MAC_ADDRESS_11G (uint8_t)(0xDA) #define EMB_NIC_MAC_ADDRESS_9G_10G (uint8_t)(0xCB) #define IMC_IDRAC_10G (uint8_t) (0x08) #define IMC_CMC (uint8_t) (0x09) #define IMC_IDRAC_11G_MONOLITHIC (uint8_t) (0x0A) #define IMC_IDRAC_11G_MODULAR (uint8_t) (0x0B) #define IMC_UNUSED (uint8_t) (0x0C) #define IMC_MASER_LITE_BMC (uint8_t) (0x0D) #define IMC_IDRAC_12G_MONOLITHIC (uint8_t) (0x10) #define IMC_IDRAC_12G_MODULAR (uint8_t) (0x11) #pragma pack(1) #ifdef LOM_OLD typedef struct { unsigned int BladSlotNumber : 4; unsigned int MacType : 2; unsigned int EthernetStatus : 2; unsigned int NICNumber : 5; unsigned int Reserved : 3; uint8_t MacAddressByte[MACADDRESSLENGH]; } LOMMacAddressType; #else typedef struct { uint8_t b0; uint8_t b1; uint8_t MacAddressByte[MACADDRESSLENGH]; } LOMMacAddressType; #endif #pragma pack() #pragma pack(1) typedef struct { LOMMacAddressType LOMMacAddress [MAX_LOM]; } EmbeddedNICMacAddressType; typedef struct { uint8_t MacAddressByte[MACADDRESSLENGH]; } MacAddressType; typedef struct { MacAddressType MacAddress [MAX_LOM]; } EmbeddedNICMacAddressType_10G; struct fru_info { uint16_t size; uint8_t access:1; }; struct fru_header { uint8_t version; struct { uint8_t internal; uint8_t chassis; uint8_t board; uint8_t product; uint8_t multi; } offset; uint8_t pad; uint8_t checksum; } ATTRIBUTE_PACKING; struct entity_id { uint8_t id; /* physical entity id */ #if WORDS_BIGENDIAN uint8_t logical : 1; /* physical/logical */ uint8_t instance : 7; /* instance number */ #else uint8_t instance : 7; /* instance number */ uint8_t logical : 1; /* physical/logical */ #endif } ATTRIBUTE_PACKING; struct sdr_record_mask { union { struct { uint16_t assert_event; /* assertion event mask */ uint16_t deassert_event; /* de-assertion event ma sk */ uint16_t read; /* discrete reading mask */ } ATTRIBUTE_PACKING discrete; /*...*/ } ATTRIBUTE_PACKING type; } ATTRIBUTE_PACKING ; struct sdr_record_full_sensor { struct { uint8_t owner_id; #if WORDS_BIGENDIAN uint8_t channel:4; /* channel number */ uint8_t __reserved1:2; uint8_t lun:2; /* sensor owner lun */ #else uint8_t lun:2; /* sensor owner lun */ uint8_t __reserved2:2; uint8_t channel:4; /* channel number */ #endif uint8_t sensor_num; /* unique sensor number */ } ATTRIBUTE_PACKING keys; struct entity_id entity; struct { struct { #if WORDS_BIGENDIAN uint8_t __reserved3:1; uint8_t scanning:1; uint8_t events:1; uint8_t thresholds:1; uint8_t hysteresis:1; uint8_t type:1; uint8_t event_gen:1; uint8_t sensor_scan:1; #else uint8_t sensor_scan:1; uint8_t event_gen:1; uint8_t type:1; uint8_t hysteresis:1; uint8_t thresholds:1; uint8_t events:1; uint8_t scanning:1; uint8_t __reserved4:1; #endif } ATTRIBUTE_PACKING init; struct { #if WORDS_BIGENDIAN uint8_t ignore:1; uint8_t rearm:1; uint8_t hysteresis:2; uint8_t threshold:2; uint8_t event_msg:2; #else uint8_t event_msg:2; uint8_t threshold:2; uint8_t hysteresis:2; uint8_t rearm:1; uint8_t ignore:1; #endif } ATTRIBUTE_PACKING capabilities; uint8_t type; } ATTRIBUTE_PACKING sensor; uint8_t event_type; /* event/reading type code */ struct sdr_record_mask mask; struct { #if WORDS_BIGENDIAN uint8_t analog:2; uint8_t rate:3; uint8_t modifier:2; uint8_t pct:1; #else uint8_t pct:1; uint8_t modifier:2; uint8_t rate:3; uint8_t analog:2; #endif struct { uint8_t base; uint8_t modifier; } ATTRIBUTE_PACKING type; } ATTRIBUTE_PACKING unit; #define SDR_SENSOR_L_LINEAR 0x00 #define SDR_SENSOR_L_LN 0x01 #define SDR_SENSOR_L_LOG10 0x02 #define SDR_SENSOR_L_LOG2 0x03 #define SDR_SENSOR_L_E 0x04 #define SDR_SENSOR_L_EXP10 0x05 #define SDR_SENSOR_L_EXP2 0x06 #define SDR_SENSOR_L_1_X 0x07 #define SDR_SENSOR_L_SQR 0x08 #define SDR_SENSOR_L_CUBE 0x09 #define SDR_SENSOR_L_SQRT 0x0a #define SDR_SENSOR_L_CUBERT 0x0b #define SDR_SENSOR_L_NONLINEAR 0x70 uint8_t linearization; /* 70h=non linear, 71h-7Fh=non linear, OEM */ uint16_t mtol; /* M, tolerance */ uint32_t bacc; /* accuracy, B, Bexp, Rexp */ struct { #if WORDS_BIGENDIAN uint8_t __reserved5:5; uint8_t normal_min:1; /* normal min field specified */ uint8_t normal_max:1; /* normal max field specified */ uint8_t nominal_read:1; /* nominal reading field specified */ #else uint8_t nominal_read:1; /* nominal reading field specified */ uint8_t normal_max:1; /* normal max field specified */ uint8_t normal_min:1; /* normal min field specified */ uint8_t __reserved5:5; #endif } ATTRIBUTE_PACKING analog_flag; uint8_t nominal_read; /* nominal reading, raw value */ uint8_t normal_max; /* normal maximum, raw value */ uint8_t normal_min; /* normal minimum, raw value */ uint8_t sensor_max; /* sensor maximum, raw value */ uint8_t sensor_min; /* sensor minimum, raw value */ struct { struct { uint8_t non_recover; uint8_t critical; uint8_t non_critical; } ATTRIBUTE_PACKING upper; struct { uint8_t non_recover; uint8_t critical; uint8_t non_critical; } ATTRIBUTE_PACKING lower; struct { uint8_t positive; uint8_t negative; } ATTRIBUTE_PACKING hysteresis; } ATTRIBUTE_PACKING threshold; uint8_t __reserved6[2]; uint8_t oem; /* reserved for OEM use */ uint8_t id_code; /* sensor ID string type/length code */ uint8_t id_string[16]; /* sensor ID string bytes, only if id_code != 0 */ } ATTRIBUTE_PACKING; struct sdr_record_list { uint16_t id; uint8_t version; uint8_t type; uint8_t length; union { struct sdr_record_full_sensor *full; } ATTRIBUTE_PACKING record; uint8_t *raw; struct sdr_record_list *next; } ATTRIBUTE_PACKING; #pragma pack() #define TRANSPORT_NETFN (uint8_t)(0xc) #define GET_LAN_PARAM_CMD (uint8_t)(0x02) #define MAC_ADDR_PARAM (uint8_t)(0x05) #define LAN_CHANNEL_NUMBER (uint8_t)(0x01) #define IDRAC_NIC_NUMBER (uint8_t)(0x8) #define TOTAL_N0_NICS_INDEX (uint8_t)(0x1) // 12g supported #define SET_NIC_SELECTION_12G_CMD (uint8_t)(0x28) #define GET_NIC_SELECTION_12G_CMD (uint8_t)(0x29) // 11g supported #define SET_NIC_SELECTION_CMD (uint8_t)(0x24) #define GET_NIC_SELECTION_CMD (uint8_t)(0x25) #define GET_ACTIVE_NIC_CMD (uint8_t)(0xc1) #define POWER_EFFICENCY_CMD (uint8_t)(0xc0) #define SERVER_POWER_CONSUMPTION_CMD (uint8_t)(0x8F) #define POWER_SUPPLY_INFO (uint8_t)(0xb0) #define IPMI_ENTITY_ID_POWER_SUPPLY (uint8_t)(0x0a) #define SENSOR_STATE_STR_SIZE (uint8_t)(64) #define SENSOR_NAME_STR_SIZE (uint8_t)(64) #define GET_PWRMGMT_INFO_CMD (uint8_t)(0x9C) #define CLEAR_PWRMGMT_INFO_CMD (uint8_t)(0x9D) #define GET_PWR_HEADROOM_CMD (uint8_t)(0xBB) #define GET_PWR_CONSUMPTION_CMD (uint8_t)(0xB3) #define GET_FRONT_PANEL_INFO_CMD (uint8_t)0xb5 #pragma pack(1) typedef struct _ipmi_power_monitor { uint32_t cumStartTime; uint32_t cumReading; uint32_t maxPeakStartTime; uint32_t ampPeakTime; uint16_t ampReading; uint32_t wattPeakTime; uint16_t wattReading; } ATTRIBUTE_PACKING IPMI_POWER_MONITOR; #define MAX_POWER_FW_VERSION 8 typedef struct _ipmi_power_supply_infoo { /*No param_rev it is not a System Information Command */ uint16_t ratedWatts; uint16_t ratedAmps; uint16_t ratedVolts; uint32_t vendorid; uint8_t FrimwareVersion[MAX_POWER_FW_VERSION]; uint8_t Powersupplytype; uint16_t ratedDCWatts; uint16_t Resv; } ATTRIBUTE_PACKING IPMI_POWER_SUPPLY_INFO; typedef struct ipmi_power_consumption_data { uint16_t actualpowerconsumption; uint16_t powerthreshold; uint16_t warningthreshold; uint8_t throttlestate; uint16_t maxpowerconsumption; uint16_t throttlepowerconsumption; uint16_t Resv; } ATTRIBUTE_PACKING IPMI_POWER_CONSUMPTION_DATA; typedef struct ipmi_inst_power_consumption_data { uint16_t instanpowerconsumption; uint16_t instanApms; uint16_t resv1; uint8_t resv; } ATTRIBUTE_PACKING IPMI_INST_POWER_CONSUMPTION_DATA; typedef struct _ipmi_avgpower_consump_histroy { uint8_t parameterselector; uint16_t lastminutepower; uint16_t lasthourpower; uint16_t lastdaypower; uint16_t lastweakpower; } ATTRIBUTE_PACKING IPMI_AVGPOWER_CONSUMP_HISTORY; typedef struct _ipmi_power_consump_histroy { uint8_t parameterselector; uint16_t lastminutepower; uint16_t lasthourpower; uint16_t lastdaypower; uint16_t lastweakpower; uint32_t lastminutepowertime; uint32_t lasthourpowertime; uint32_t lastdaypowertime; uint32_t lastweekpowertime; } ATTRIBUTE_PACKING IPMI_POWER_CONSUMP_HISTORY; typedef struct _ipmi_delloem_power_cap { uint8_t parameterselector; uint16_t PowerCap; uint8_t unit; uint16_t MaximumPowerConsmp; uint16_t MinimumPowerConsmp; uint16_t totalnumpowersupp; uint16_t AvailablePower ; uint16_t SystemThrottling; uint16_t Resv; } ATTRIBUTE_PACKING IPMI_POWER_CAP; typedef struct _power_headroom { uint16_t instheadroom; uint16_t peakheadroom; } ATTRIBUTE_PACKING POWER_HEADROOM; struct vFlashstr { uint8_t val; const char * str; }; typedef struct ipmi_vFlash_extended_info { uint8_t vflashcompcode; uint8_t sdcardstatus; uint32_t sdcardsize; uint32_t sdcardavailsize; uint8_t bootpartion; uint8_t Resv; } IPMI_DELL_SDCARD_INFO; #pragma pack() typedef struct _SensorReadingType { uint8_t sensorReading; uint8_t sensorFlags; uint16_t sensorState; }SensorReadingType; struct standard_spec_sel_rec{ uint32_t timestamp; uint16_t gen_id; uint8_t evm_rev; uint8_t sensor_type; uint8_t sensor_num; #if WORDS_BIGENDIAN uint8_t event_dir : 1; uint8_t event_type : 7; #else uint8_t event_type : 7; uint8_t event_dir : 1; #endif #define DATA_BYTE2_SPECIFIED_MASK 0xc0 /* event_data[0] bit mask */ #define DATA_BYTE3_SPECIFIED_MASK 0x30 /* event_data[0] bit mask */ #define EVENT_OFFSET_MASK 0x0f /* event_data[0] bit mask */ uint8_t event_data[3]; }; #define SEL_OEM_TS_DATA_LEN 6 #define SEL_OEM_NOTS_DATA_LEN 13 struct oem_ts_spec_sel_rec{ uint32_t timestamp; uint8_t manf_id[3]; uint8_t oem_defined[SEL_OEM_TS_DATA_LEN]; }; struct oem_nots_spec_sel_rec{ uint8_t oem_defined[SEL_OEM_NOTS_DATA_LEN]; }; #pragma pack(1) struct sel_event_record { uint16_t record_id; uint8_t record_type; union{ struct standard_spec_sel_rec standard_type; struct oem_ts_spec_sel_rec oem_ts_type; struct oem_nots_spec_sel_rec oem_nots_type; } sel_type; } ATTRIBUTE_PACKING; // __attribute__ ((packed)); #pragma pack() uint16_t compareinputwattage(IPMI_POWER_SUPPLY_INFO* powersupplyinfo, uint16_t inputwattage); int ipmi_delloem_main(void * intf, int argc, char ** argv); int ipmi_delloem_getled_state (void * intf, uint8_t *state); #endif /*IPMI_DELLOEM_H*/ ipmiutil-3.1.5/util/ihpm.c0000644000076400007640000040205713566765324015544 0ustar mgportalloggers/* * ihpm.c * Hardware Platform Management, IPM Controller Firmware Upgrade Procedure * * Change history: * 08/25/2010 ARCress - ported from ipmitool/lib/ipmi_hpmfwupg.c * 08/24/2011 ARcress - updated to Kontron 1.08 (K17) version, * added hpm_decode_cc(), etc. * *--------------------------------------------------------------------- */ /* * Copyright (c) 2006 Kontron Canada, Inc. All Rights Reserved. * Copyright (c) 2003 Sun Microsystems, 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: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution 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. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #ifdef WIN32 #include #include #include #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int typedef uint32_t socklen_t; #include "getopt.h" #else #include #include #include #include #include /*for toupper*/ #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include #include #include #include #include "ipmicmd.h" #include "ihpm.h" /**************************************************************************** * * Copyright (c) 2006 Kontron Canada, Inc. All Rights Reserved. * * HPM.1 * Hardware Platform Management * IPM Controller Firmware Upgrade Procedure * * This module implements an Upgrade Agent for the IPM Controller * Firmware Upgrade Procedure (HPM.1) specification version 1.0. * * author: * Frederic.Lelievre@ca.kontron.com * Francois.Isabelle@ca.kontron.com * Jean-Michel.Audet@ca.kontron.com * MarieJosee.Blais@ca.kontron.com * ***************************************************************************** * * HISTORY * =========================================================================== * 2007-01-11 * * - Incremented to version 0.2 * - Added lan packet size reduction mechanism to workaround fact * that lan iface will not return C7 on excessive length * - Fixed some typos * - now uses lprintf() * * - Incremented to version 0.3 * - added patch for openipmi si driver V39 (send message in driver does not * retry on 82/83 completion code and return 82/83 as response from target * [conditionnaly built with ENABLE_OPENIPMI_V39_PATCH] * * see: ipmi-fix-send-msg-retry.pacth in openipmi-developer mailing list * * 2007-01-16 * * - Incremented to version 0.4 * - Fixed lan iface inaccesiblity timeout handling. Waiting for firmware * activation completion (fixed sleep) before re-opening a session and * get the final firmware upgrade status. * - Fixed some user interface stuff. * * 2007-05-09 * * - Incremented to version 1.0 * - Modifications for compliancy with HPM.1 specification version 1.0 * * 2007-06-05 * * - Modified the display of upgrade of Firmware version. * - Added new options like "check" and "component" and "all" to hpm commands. * - By default we skip the upgrade if we have the same firmware version * as compared to the Image file (*.hpm).This will ensure that user does * not update the target incase its already been updated * * 2008-01-25 * - Reduce buffer length more aggressively when no response from iol. * - Incremented version to 1.02 * * 2009-02-11 * - With multi-component HPM file, if one component need to be skipped because * the component is already up-to-date, ipmitool sends "Initiate upgrade * action / Upload for upgrade" anyway. * * If the component needs to be skipped, ipmitool will not send "Initiate * upgrade action / Upload for upgrade" * * - Incremented version to 1.03 * * 2009-02-11 * - Fixed side effect introduced by last version, "forced" update didn't * work anymore * - Incremented version to 1.04 * * 2009-03-25 * - Fix the case where ipmitool loses the iol connection during the upload * block process. Once IPMITool was successfully sent the first byte, * IPMITool will not resize the block size. * * 2009-03-26 * - Fix the problem when we try to upgrade specific component and the component * is already updated, IPMITool sends a "prepare action" but IPMITool skips * the upload firmware block process. * So, if we specify a specific component, we want to force to upload this * specific component. * - Incremented version to 1.05 * * 2009-04-20 * - Reworked previous update, when 'component' is specified, the other * components are now skipped. * - Incremented version to 1.06 * * =========================================================================== * TODO * =========================================================================== * 2007-01-11 * - Add interpretation of GetSelftestResults * - Add interpretation of component ID string * *****************************************************************************/ extern int verbose; /* * Agent version */ #define HPMFWUPG_VERSION_MAJOR 1 #define HPMFWUPG_VERSION_MINOR 0 #define HPMFWUPG_VERSION_SUBMINOR 9 static char * progname = "ihpm"; static char * progver = "1.09"; /* HPMFWUPG_VERSION */ extern char fdebug; /*from ipmicmd.c*/ static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static int g_channel_buf_size = 0; /* * HPM.1 FIRMWARE UPGRADE COMMANDS (part of PICMG) */ #define HPMFWUPG_GET_TARGET_UPG_CAPABILITIES 0x2E #define HPMFWUPG_GET_COMPONENT_PROPERTIES 0x2F #define HPMFWUPG_ABORT_UPGRADE 0x30 #define HPMFWUPG_INITIATE_UPGRADE_ACTION 0x31 #define HPMFWUPG_UPLOAD_FIRMWARE_BLOCK 0x32 #define HPMFWUPG_FINISH_FIRMWARE_UPLOAD 0x33 #define HPMFWUPG_GET_UPGRADE_STATUS 0x34 #define HPMFWUPG_ACTIVATE_FIRMWARE 0x35 #define HPMFWUPG_QUERY_SELFTEST_RESULT 0x36 #define HPMFWUPG_QUERY_ROLLBACK_STATUS 0x37 #define HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK 0x38 /* * HPM.1 SPECIFIC COMPLETION CODES */ #define HPMFWUPG_ROLLBACK_COMPLETED 0x00 #define HPMFWUPG_COMMAND_IN_PROGRESS 0x80 #define HPMFWUPG_NOT_SUPPORTED 0x81 #define HPMFWUPG_SIZE_MISMATCH 0x81 #define HPMFWUPG_ROLLBACK_FAILURE 0x81 #define HPMFWUPG_INV_COMP_MASK 0x81 #define HPMFWUPG__ABORT_FAILURE 0x81 #define HPMFWUPG_INV_COMP_ID 0x82 #define HPMFWUPG_INT_CHECKSUM_ERROR 0x82 #define HPMFWUPG_INV_UPLOAD_MODE 0x82 #define HPMFWUPG_ROLLBACK_OVERRIDE 0x82 #define HPMFWUPG_INV_COMP_PROP 0x83 #define HPMFWUPG_FW_MISMATCH 0x83 #define HPMFWUPG_ROLLBACK_DENIED 0x83 #define HPMFWUPG_NOT_SUPPORTED_NOW 0xd5 /* * This error code is used as a temporary PATCH to * the latest Open ipmi driver. This PATCH * will be removed once a new Open IPMI driver is released. * (Buggy version = 39) */ #define ENABLE_OPENIPMI_V39_PATCH #ifdef ENABLE_OPENIPMI_V39_PATCH #define RETRY_COUNT_MAX 3 static int errorCount; #define HPMFWUPG_IS_RETRYABLE(error) \ ((((error==0x83)||(error==0x82)||(error==0x80)) && (errorCount++descString,11); /* * If the cold reset is required then we can display * on it * so that user is aware that he needs to do payload power * cycle after upgrade */ printf("|%c%-2d|%-11s|",pVersion->coldResetRequired?'*':' ',pVersion->componentId,descString); if (mode & TARGET_VER) { if (pVersion->targetMajor == 0xFF && pVersion->targetMinor == 0xFF) printf(" ---.-- -------- |"); else printf(" %3d.%02x %02X%02X%02X%02X |", pVersion->targetMajor, pVersion->targetMinor, pVersion->targetAux[0], pVersion->targetAux[1], pVersion->targetAux[2], pVersion->targetAux[3] ); if (mode & ROLLBACK_VER) { if (pVersion->rollbackMajor == 0xFF && pVersion->rollbackMinor == 0xFF) printf(" ---.-- -------- |"); else printf(" %3d.%02x %02X%02X%02X%02X |", pVersion->rollbackMajor, pVersion->rollbackMinor, pVersion->rollbackAux[0], pVersion->rollbackAux[1], pVersion->rollbackAux[2], pVersion->rollbackAux[3]); } else { printf(" ---.-- -------- |"); } } if (mode & IMAGE_VER) { if (pVersion->imageMajor == 0xFF && pVersion->imageMinor == 0xFF) printf(" ---.-- |"); else printf(" %3d.%02x %02X%02X%02X%02X |", pVersion->imageMajor, pVersion->imageMinor, pVersion->imageAux[0], pVersion->imageAux[1], pVersion->imageAux[2], pVersion->imageAux[3]); } return 0; } /**************************************************************************** * * Function Name: HpmfwupgTargerCheck * * Description: This function gets the target information and displays it on the * screen * *****************************************************************************/ int HpmfwupgTargetCheck(void * intf, int option) { // struct HpmfwupgUpgradeCtx fwupgCtx; struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; int rc = HPMFWUPG_SUCCESS; int componentId = 0; int flagColdReset = FALSE; struct ipm_devid_rsp devIdrsp; struct HpmfwupgGetComponentPropertiesCtx getCompProp; int mode = 0; rc = HpmfwupgGetDeviceId(intf, &devIdrsp); if (rc != HPMFWUPG_SUCCESS) { lprintf(LOG_NOTICE,"Verify whether the Target board is present \n"); return rc; } rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd); if (rc != HPMFWUPG_SUCCESS) { /* * That indicates the target is not responding to the command * May be that there is no HPM support */ lprintf(LOG_NOTICE,"Board might not be supporting the HPM.1 Standards\n"); return rc; } if (option & VIEW_MODE) { lprintf(LOG_NOTICE,"-------Target Information-------"); lprintf(LOG_NOTICE,"Device Id : 0x%x", devIdrsp.device_id); lprintf(LOG_NOTICE,"Device Revision : 0x%x", devIdrsp.device_revision); lprintf(LOG_NOTICE,"Product Id : 0x%04x", buf2short(devIdrsp.product_id)); lprintf(LOG_NOTICE,"Manufacturer Id : 0x%04x (%s)\n\n", buf2short(devIdrsp.manufacturer_id), get_mfg_str(devIdrsp.manufacturer_id,NULL)); HpmDisplayVersionHeader(TARGET_VER|ROLLBACK_VER); } for ( componentId = HPMFWUPG_COMPONENT_ID_0; componentId < HPMFWUPG_COMPONENT_ID_MAX; componentId++ ) { /* If the component is supported */ if ( ((1 << componentId) & targetCapCmd.resp.componentsPresent.ComponentBits.byte) ) { memset((PVERSIONINFO)&gVersionInfo[componentId],0x00,sizeof(VERSIONINFO)); getCompProp.req.componentId = componentId; getCompProp.req.selector = HPMFWUPG_COMP_GEN_PROPERTIES; rc = HpmfwupgGetComponentProperties(intf, &getCompProp); if (rc != HPMFWUPG_SUCCESS) { lprintf(LOG_NOTICE,"Get CompGenProp Failed for component Id %d\n",componentId); return rc; } gVersionInfo[componentId].rollbackSupported = getCompProp.resp.Response. generalPropResp.GeneralCompProperties.bitfield.rollbackBackup; gVersionInfo[componentId].coldResetRequired = getCompProp.resp.Response. generalPropResp.GeneralCompProperties.bitfield.payloadColdReset; getCompProp.req.selector = HPMFWUPG_COMP_DESCRIPTION_STRING; rc = HpmfwupgGetComponentProperties(intf, &getCompProp); if (rc != HPMFWUPG_SUCCESS) { lprintf(LOG_NOTICE,"Get CompDescString Failed for component Id %d\n",componentId); return rc; } strcpy((char *)&gVersionInfo[componentId].descString, getCompProp.resp.Response.descStringResp.descString); getCompProp.req.selector = HPMFWUPG_COMP_CURRENT_VERSION; rc = HpmfwupgGetComponentProperties(intf, &getCompProp); if (rc != HPMFWUPG_SUCCESS) { lprintf(LOG_NOTICE,"Get CompCurrentVersion Failed for component Id %d\n",componentId); return rc; } gVersionInfo[componentId].componentId = componentId; gVersionInfo[componentId].targetMajor = getCompProp.resp.Response. currentVersionResp.currentVersion[0]; gVersionInfo[componentId].targetMinor = getCompProp.resp.Response. currentVersionResp.currentVersion[1]; gVersionInfo[componentId].targetAux[0] = getCompProp.resp.Response. currentVersionResp.currentVersion[2]; gVersionInfo[componentId].targetAux[1] = getCompProp.resp.Response. currentVersionResp.currentVersion[3]; gVersionInfo[componentId].targetAux[2] = getCompProp.resp.Response. currentVersionResp.currentVersion[4]; gVersionInfo[componentId].targetAux[3] = getCompProp.resp.Response. currentVersionResp.currentVersion[5]; mode = TARGET_VER; if (gVersionInfo[componentId].rollbackSupported) { getCompProp.req.selector = HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION; rc = HpmfwupgGetComponentProperties(intf, &getCompProp); if (rc != HPMFWUPG_SUCCESS) { lprintf(LOG_NOTICE,"Get CompRollbackVersion Failed for component Id %d\n",componentId); } else { gVersionInfo[componentId].rollbackMajor = getCompProp.resp .Response.rollbackFwVersionResp.rollbackFwVersion[0]; gVersionInfo[componentId].rollbackMinor = getCompProp.resp .Response.rollbackFwVersionResp.rollbackFwVersion[1]; gVersionInfo[componentId].rollbackAux[0] = getCompProp.resp.Response. rollbackFwVersionResp.rollbackFwVersion[2]; gVersionInfo[componentId].rollbackAux[1] = getCompProp.resp.Response. rollbackFwVersionResp.rollbackFwVersion[3]; gVersionInfo[componentId].rollbackAux[2] = getCompProp.resp.Response. rollbackFwVersionResp.rollbackFwVersion[4]; gVersionInfo[componentId].rollbackAux[3] = getCompProp.resp.Response. rollbackFwVersionResp.rollbackFwVersion[5]; } mode |= ROLLBACK_VER; } if (gVersionInfo[componentId].coldResetRequired) { /* * If any of the component indicates that the Payload Cold reset is required * then set the flag */ flagColdReset = TRUE; } if (option & VIEW_MODE) { HpmDisplayVersion(mode,&gVersionInfo[componentId]); printf("\n"); } } } if (option & VIEW_MODE) { HpmDisplayLine("-",53 ); if (flagColdReset) { fflush(stdout); lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset"); } printf("\n\n"); } return HPMFWUPG_SUCCESS; } /***************************************************************************** * Function Name: HpmfwupgUpgrade * * Description: This function performs the HPM.1 firmware upgrade procedure as * defined the IPM Controller Firmware Upgrade Specification * version 1.0 * *****************************************************************************/ int HpmfwupgUpgrade(void *intf, char* imageFilename, int activate,int componentToUpload, int option) { int rc = HPMFWUPG_SUCCESS; // struct HpmfwupgImageHeader imageHeader; struct HpmfwupgUpgradeCtx fwupgCtx; /* * GET IMAGE BUFFER FROM FILE */ rc = HpmfwupgGetBufferFromFile(imageFilename, &fwupgCtx); /* * VALIDATE IMAGE INTEGRITY */ if ( rc == HPMFWUPG_SUCCESS ) { printf("Validating firmware image integrity..."); fflush(stdout); rc = HpmfwupgValidateImageIntegrity(&fwupgCtx); if ( rc == HPMFWUPG_SUCCESS ) { printf("OK\n"); fflush(stdout); } else { free(fwupgCtx.pImageData); } } /* * PREPARATION STAGE */ if ( rc == HPMFWUPG_SUCCESS ) { printf("Performing preparation stage..."); fflush(stdout); rc = HpmfwupgPreparationStage(intf, &fwupgCtx, option); if ( rc == HPMFWUPG_SUCCESS ) { printf("OK\n"); fflush(stdout); } else { free(fwupgCtx.pImageData); } } /* * UPGRADE STAGE */ if ( rc == HPMFWUPG_SUCCESS ) { if (option & VIEW_MODE) { lprintf(LOG_NOTICE,"\nComparing Target & Image File version"); } else { lprintf(LOG_NOTICE,"\nPerforming upgrade stage:"); } if (option & VIEW_MODE) { rc = HpmfwupgPreUpgradeCheck(intf, &fwupgCtx,componentToUpload,VIEW_MODE); } else { rc = HpmfwupgPreUpgradeCheck(intf, &fwupgCtx,componentToUpload,option); if (rc == HPMFWUPG_SUCCESS ) { if( verbose ) { printf("Component update mask : 0x%02x\n", fwupgCtx.compUpdateMask.ComponentBits.byte); } rc = HpmfwupgUpgradeStage(intf, &fwupgCtx,componentToUpload,option); } } if ( rc != HPMFWUPG_SUCCESS ) { if (verbose) printf("HPM Upgrade error %d\n",rc); free(fwupgCtx.pImageData); } } /* * ACTIVATION STAGE */ if ( rc == HPMFWUPG_SUCCESS && activate ) { lprintf(LOG_NOTICE,"Performing activation stage: "); rc = HpmfwupgActivationStage(intf, &fwupgCtx); if ( rc != HPMFWUPG_SUCCESS ) { if (verbose) printf("HPM Activation error %d\n",rc); free(fwupgCtx.pImageData); } } if ( rc == HPMFWUPG_SUCCESS ) { if (option & VIEW_MODE) { // Dont display anything here in case we are just viewing it lprintf(LOG_NOTICE," "); } else { lprintf(LOG_NOTICE,"\nFirmware upgrade procedure successful\n"); } free(fwupgCtx.pImageData); } else { lprintf(LOG_NOTICE,"Firmware upgrade procedure failed\n"); } return rc; } /**************************************************************************** * * Function Name: HpmfwupgValidateImageIntegrity * * Description: This function validates a HPM.1 firmware image file as defined * in section 4 of the IPM Controller Firmware Upgrade * Specification version 1.0 * *****************************************************************************/ int HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData; md5_state_t ctx; static unsigned char md[HPMFWUPG_MD5_SIGNATURE_LENGTH]; unsigned char* pMd5Sig = pFwupgCtx->pImageData + (pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH); /* Validate MD5 checksum */ memset(md, 0, HPMFWUPG_MD5_SIGNATURE_LENGTH); memset(&ctx, 0, sizeof(md5_state_t)); md5_init(&ctx); md5_append(&ctx, pFwupgCtx->pImageData, pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH); md5_finish(&ctx, md); if ( memcmp(md, pMd5Sig,HPMFWUPG_MD5_SIGNATURE_LENGTH) != 0 ) { lprintf(LOG_NOTICE,"\n Invalid MD5 signature"); rc = HPMFWUPG_ERROR; } if ( rc == HPMFWUPG_SUCCESS ) { /* Validate Header signature */ if( strncmp(pImageHeader->signature, HPMFWUPG_IMAGE_SIGNATURE, HPMFWUPG_HEADER_SIGNATURE_LENGTH) == 0 ) { /* Validate Header image format version */ if ( pImageHeader->formatVersion == HPMFWUPG_IMAGE_HEADER_VERSION ) { /* Validate header checksum */ if ( HpmfwupgCalculateChecksum((unsigned char*)pImageHeader, sizeof(struct HpmfwupgImageHeader) + pImageHeader->oemDataLength + sizeof(unsigned char)/*checksum*/) != 0 ) { lprintf(LOG_NOTICE,"\n Invalid header checksum"); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"\n Unrecognized image version"); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"\n Invalid image signature"); rc = HPMFWUPG_ERROR; } } return rc; } /**************************************************************************** * * Function Name: HpmfwupgPreparationStage * * Description: This function the preperation stage of a firmware upgrade * procedure as defined in section 3.2 of the IPM Controller * Firmware Upgrade Specification version 1.0 * *****************************************************************************/ int HpmfwupgPreparationStage(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx, int option) { int rc = HPMFWUPG_SUCCESS; struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData; /* Get device ID */ rc = HpmfwupgGetDeviceId(intf, &pFwupgCtx->devId); /* Match current IPMC IDs with upgrade image */ if ( rc == HPMFWUPG_SUCCESS ) { /* Validate device ID */ if ( pImageHeader->deviceId == pFwupgCtx->devId.device_id ) { /* Validate product ID */ if ( memcmp(pImageHeader->prodId, pFwupgCtx->devId.product_id, HPMFWUPG_PRODUCT_ID_LENGTH ) == 0 ) { /* Validate man ID */ if ( memcmp(pImageHeader->manId, pFwupgCtx->devId.manufacturer_id, HPMFWUPG_MANUFATURER_ID_LENGTH ) != 0 ) { lprintf(LOG_NOTICE,"\n Invalid image file for manufacturer %u", buf2short(pFwupgCtx->devId.manufacturer_id)); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"\n Invalid image file for product %u", buf2short(pFwupgCtx->devId.product_id)); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"\n Invalid device ID %x", pFwupgCtx->devId.device_id); rc = HPMFWUPG_ERROR; } if (rc != HPMFWUPG_SUCCESS) { /* * Giving one more chance to user to check whether its OK to continue even if the * product ID does not match. This is helpful as sometimes we just want to update * and dont care whether we have a different product Id. If the user says NO then * we need to just bail out from here */ if ( (option & FORCE_MODE) || (option & VIEW_MODE) ) { printf("\n Image Information"); printf("\n Device Id : 0x%x",pImageHeader->deviceId); printf("\n Prod Id : 0x%02x%02x",pImageHeader->prodId[1], pImageHeader->prodId[0]); printf("\n Manuf Id : 0x%02x%02x%02x",pImageHeader->manId[2], pImageHeader->manId[1],pImageHeader->manId[0]); printf("\n Board Information"); printf("\n Device Id : 0x%x", pFwupgCtx->devId.device_id); printf("\n Prod Id : 0x%02x%02x",pFwupgCtx->devId.product_id[1], pFwupgCtx->devId.product_id[0]); printf("\n Manuf Id : 0x%02x%02x%02x",pFwupgCtx->devId.manufacturer_id[2], pFwupgCtx->devId.manufacturer_id[1],pFwupgCtx->devId.manufacturer_id[0]); if (HpmGetUserInput("\n Continue ignoring DeviceID/ProductID/ManufacturingID (Y/N) :")) rc = HPMFWUPG_SUCCESS; } else { /* * If you use all option its kind of FORCE command where we need to upgrade all the components */ printf("\n\n Use \"all\" option for uploading all the components\n"); } } } /* Validate earliest compatible revision */ if ( rc == HPMFWUPG_SUCCESS ) { /* Validate major & minor revision */ if ( pImageHeader->compRevision[0] < pFwupgCtx->devId.fw_rev1 ) { /* Do nothing, upgrade accepted */ } else if ( pImageHeader->compRevision[0] == pFwupgCtx->devId.fw_rev1 ) { /* Must validate minor revision */ if ( pImageHeader->compRevision[1] > pFwupgCtx->devId.fw_rev2 ) { /* Version not compatible for upgrade */ lprintf(LOG_NOTICE,"\n Version: Major: %d", pImageHeader->compRevision[0]); lprintf(LOG_NOTICE," Minor: %x", pImageHeader->compRevision[1]); lprintf(LOG_NOTICE," Not compatible with "); lprintf(LOG_NOTICE," Version: Major: %d", pFwupgCtx->devId.fw_rev1); lprintf(LOG_NOTICE," Minor: %x", pFwupgCtx->devId.fw_rev2); rc = HPMFWUPG_ERROR; } } else { /* Version not compatible for upgrade */ lprintf(LOG_NOTICE,"\n Version: Major: %d", pImageHeader->compRevision[0]); lprintf(LOG_NOTICE," Minor: %x", pImageHeader->compRevision[1]); lprintf(LOG_NOTICE," Not compatible with "); lprintf(LOG_NOTICE," Version: Major: %d", pFwupgCtx->devId.fw_rev1); lprintf(LOG_NOTICE," Minor: %x", pFwupgCtx->devId.fw_rev2); rc = HPMFWUPG_ERROR; } if (rc != HPMFWUPG_SUCCESS) { /* Confirming it once again */ if ( (option & FORCE_MODE) || (option & VIEW_MODE) ) { if( HpmGetUserInput("\n Continue IGNORING Earliest compatibility (Y/N) :")) rc = HPMFWUPG_SUCCESS; } } } /* Get target upgrade capabilities */ if ( rc == HPMFWUPG_SUCCESS ) { struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd); if ( rc == HPMFWUPG_SUCCESS ) { /* Copy response to context */ memcpy(&pFwupgCtx->targetCap, &targetCapCmd.resp, sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp)); if (option & VIEW_MODE) { return rc; } else { /* Make sure all component IDs defined in the upgrade image are supported by the IPMC */ if ( (pImageHeader->components.ComponentBits.byte & pFwupgCtx->targetCap.componentsPresent.ComponentBits.byte ) != pImageHeader->components.ComponentBits.byte ) { lprintf(LOG_NOTICE,"\n Some components present in the image file are not supported by the IPMC"); rc = HPMFWUPG_ERROR; } /* Make sure the upgrade is desirable rigth now */ if ( pFwupgCtx->targetCap.GlobalCapabilities.bitField.fwUpgUndesirable == 1 ) { lprintf(LOG_NOTICE,"\n Upgrade undesirable at this moment"); rc = HPMFWUPG_ERROR; } /* Get confimation from the user if he wants to continue when service affected during upgrade */ if ( pFwupgCtx->targetCap.GlobalCapabilities.bitField.servAffectDuringUpg == 1 || pImageHeader->imageCapabilities.bitField.servAffected == 1 ) { if (HpmGetUserInput("\nServices may be affected during upgrade. Do you wish to continue? y/n ")) { rc = HPMFWUPG_SUCCESS; } else { rc = HPMFWUPG_ERROR; } } } } } /* Get the general properties of each component present in image */ if ( rc == HPMFWUPG_SUCCESS ) { int componentId; for ( componentId = HPMFWUPG_COMPONENT_ID_0; componentId < HPMFWUPG_COMPONENT_ID_MAX; componentId++ ) { /* Reset component properties */ memset(&pFwupgCtx->genCompProp[componentId], 0, sizeof (struct HpmfwupgGetGeneralPropResp)); if ( (1 << componentId & pImageHeader->components.ComponentBits.byte) ) { struct HpmfwupgGetComponentPropertiesCtx getCompPropCmd; /* Get general component properties */ getCompPropCmd.req.componentId = componentId; getCompPropCmd.req.selector = HPMFWUPG_COMP_GEN_PROPERTIES; rc = HpmfwupgGetComponentProperties(intf, &getCompPropCmd); if ( rc == HPMFWUPG_SUCCESS ) { /* Copy response to context */ memcpy(&pFwupgCtx->genCompProp[componentId], &getCompPropCmd.resp, sizeof(struct HpmfwupgGetGeneralPropResp)); } } } } return rc; } /**************************************************************************** * * Function Name: HpmfwupgPreUpgradeCheck * * Description: This function the pre Upgrade check, this mainly helps in checking * which all version upgrade is skippable because the image version * is same as target version. * *****************************************************************************/ int HpmfwupgPreUpgradeCheck(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx, int componentToUpload,int option) { int rc = HPMFWUPG_SUCCESS; unsigned char* pImagePtr; struct HpmfwupgActionRecord* pActionRecord; unsigned int actionsSize; int flagColdReset = FALSE; struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData; /* Put pointer after image header */ pImagePtr = (unsigned char*) (pFwupgCtx->pImageData + sizeof(struct HpmfwupgImageHeader) + pImageHeader->oemDataLength + sizeof(unsigned char)/*checksum*/); /* Deternime actions size */ actionsSize = pFwupgCtx->imageSize - sizeof(struct HpmfwupgImageHeader); if (option & VIEW_MODE) { HpmDisplayVersionHeader(TARGET_VER|ROLLBACK_VER|IMAGE_VER); } /* Perform actions defined in the image */ while( ( pImagePtr < (pFwupgCtx->pImageData + pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH)) && ( rc == HPMFWUPG_SUCCESS) ) { /* Get action record */ pActionRecord = (struct HpmfwupgActionRecord*)pImagePtr; /* Validate action record checksum */ if ( HpmfwupgCalculateChecksum((unsigned char*)pActionRecord, sizeof(struct HpmfwupgActionRecord)) != 0 ) { lprintf(LOG_NOTICE," Invalid Action record."); rc = HPMFWUPG_ERROR; } if ( rc == HPMFWUPG_SUCCESS ) { switch( pActionRecord->actionType ) { case HPMFWUPG_ACTION_BACKUP_COMPONENTS: { pImagePtr += sizeof(struct HpmfwupgActionRecord); } break; case HPMFWUPG_ACTION_PREPARE_COMPONENTS: { if (componentToUpload != DEFAULT_COMPONENT_UPLOAD) { if (!(1<components.ComponentBits.byte)) { lprintf(LOG_NOTICE,"\nComponent Id given is not supported\n"); return HPMFWUPG_ERROR; } } pImagePtr += sizeof(struct HpmfwupgActionRecord); } break; case HPMFWUPG_ACTION_UPLOAD_FIRMWARE: /* Upload all firmware blocks */ { struct HpmfwupgFirmwareImage* pFwImage; unsigned char* pData; unsigned int firmwareLength = 0; unsigned char mode = 0; unsigned char componentId = 0x00; unsigned char componentIdByte = 0x00; VERSIONINFO *pVersionInfo; // struct HpmfwupgGetComponentPropertiesCtx getCompProp; /* Save component ID on which the upload is done */ componentIdByte = pActionRecord->components.ComponentBits.byte; while ((componentIdByte>>=1)!=0) { componentId++; } pFwupgCtx->componentId = componentId; pFwImage = (struct HpmfwupgFirmwareImage*)(pImagePtr + sizeof(struct HpmfwupgActionRecord)); pData = ((unsigned char*)pFwImage + sizeof(struct HpmfwupgFirmwareImage)); /* Get firmware length */ firmwareLength = pFwImage->length[0]; firmwareLength |= (pFwImage->length[1] << 8) & 0xff00; firmwareLength |= (pFwImage->length[2] << 16) & 0xff0000; firmwareLength |= (pFwImage->length[3] << 24) & 0xff000000; pVersionInfo = &gVersionInfo[componentId]; pVersionInfo->imageMajor = pFwImage->version[0]; pVersionInfo->imageMinor = pFwImage->version[1]; pVersionInfo->imageAux[0] = pFwImage->version[2]; pVersionInfo->imageAux[1] = pFwImage->version[3]; pVersionInfo->imageAux[2] = pFwImage->version[4]; pVersionInfo->imageAux[3] = pFwImage->version[5]; mode = TARGET_VER | IMAGE_VER; if (pVersionInfo->coldResetRequired) { flagColdReset = TRUE; } pVersionInfo->skipUpgrade = FALSE; if (option & FORCE_MODE_ALL) { /* user has given all to upload all the components on the command line */ if(verbose) { lprintf(LOG_NOTICE,"Forcing ALL components"); } } else if( option & FORCE_MODE_COMPONENT ) { if( componentToUpload != componentId ) { if(verbose) { lprintf(LOG_NOTICE,"Forcing component %d skip", componentId); } /* user has given the component Id to upload on the command line */ pVersionInfo->skipUpgrade = TRUE; } else if(verbose) { lprintf(LOG_NOTICE,"Forcing component %d update", componentId); /* user has given the component Id to upload on the command line */ } } else { if ( (pVersionInfo->imageMajor == pVersionInfo->targetMajor) && (pVersionInfo->imageMinor == pVersionInfo->targetMinor)) { if (pVersionInfo->rollbackSupported) { /*If the Image Versions are same as Target Versions then check for the * rollback version*/ if ( (pVersionInfo->imageMajor == pVersionInfo->rollbackMajor) && (pVersionInfo->imageMinor == pVersionInfo->rollbackMinor) ) { /* This indicates that the Rollback version is also same as * Image version -- So now we must skip it */ pVersionInfo->skipUpgrade = TRUE; } mode |= ROLLBACK_VER; } else { pVersionInfo->skipUpgrade = TRUE; } } if ( verbose ) { lprintf(LOG_NOTICE,"Component %d: %s", componentId , (pVersionInfo->skipUpgrade?"skipped":"to update")); } } if( pVersionInfo->skipUpgrade == FALSE ) { pFwupgCtx->compUpdateMask.ComponentBits.byte |= 1<pImageData; struct HpmfwupgActionRecord* pActionRecord; int rc = HPMFWUPG_SUCCESS; unsigned char* pImagePtr; unsigned int actionsSize; int flagColdReset = FALSE; // time_t start,end; /* Put pointer after image header */ pImagePtr = (unsigned char*) (pFwupgCtx->pImageData + sizeof(struct HpmfwupgImageHeader) + pImageHeader->oemDataLength + sizeof(unsigned char)/*checksum*/); /* Deternime actions size */ actionsSize = pFwupgCtx->imageSize - sizeof(struct HpmfwupgImageHeader); if (option & VERSIONCHECK_MODE || option & FORCE_MODE) { HpmDisplayUpgradeHeader(0); } /* Perform actions defined in the image */ while( ( pImagePtr < (pFwupgCtx->pImageData + pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH)) && ( rc == HPMFWUPG_SUCCESS) ) { /* Get action record */ pActionRecord = (struct HpmfwupgActionRecord*)pImagePtr; /* Validate action record checksum */ if ( HpmfwupgCalculateChecksum((unsigned char*)pActionRecord, sizeof(struct HpmfwupgActionRecord)) != 0 ) { lprintf(LOG_NOTICE," Invalid Action record."); rc = HPMFWUPG_ERROR; } if ( rc == HPMFWUPG_SUCCESS ) { switch( pActionRecord->actionType ) { case HPMFWUPG_ACTION_BACKUP_COMPONENTS: { /* Send prepare components command */ struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; initUpgActionCmd.req.componentsMask = pFwupgCtx->compUpdateMask; /* Action is prepare components */ initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_BACKUP; rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); pImagePtr += sizeof(struct HpmfwupgActionRecord); } break; case HPMFWUPG_ACTION_PREPARE_COMPONENTS: { int componentId; /* Make sure every components specified by this action supports the prepare components */ /* Component 'filtering' is done in PreUpdateCheck() and pFwupgCtx is set accordiongly */ for ( componentId = HPMFWUPG_COMPONENT_ID_0; componentId < HPMFWUPG_COMPONENT_ID_MAX; componentId++ ) { if ( (1 << componentId & pFwupgCtx->compUpdateMask.ComponentBits.byte) ) { if ( pFwupgCtx->genCompProp[componentId].GeneralCompProperties.bitfield.preparationSupport == 0 ) { lprintf(LOG_NOTICE," Prepare component not supported by component ID %d", componentId); rc = HPMFWUPG_ERROR; break; } } } if ( rc == HPMFWUPG_SUCCESS ) { if ( pFwupgCtx->compUpdateMask.ComponentBits.byte != 0x00 ) { /* Send prepare components command */ struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; initUpgActionCmd.req.componentsMask = pFwupgCtx->compUpdateMask; /* Action is prepare components */ initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_PREPARE; rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); } pImagePtr += sizeof(struct HpmfwupgActionRecord); } } break; case HPMFWUPG_ACTION_UPLOAD_FIRMWARE: /* Upload all firmware blocks */ rc = HpmFwupgActionUploadFirmware ( pActionRecord->components, pFwupgCtx, &pImagePtr, componentToUpload, intf, option, &flagColdReset ); break; default: lprintf(LOG_NOTICE," Invalid Action type. Cannot continue"); rc = HPMFWUPG_ERROR; break; } } } HpmDisplayLine("-",78); if (flagColdReset) { fflush(stdout); lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset"); } return rc; } static int HpmFwupgActionUploadFirmware ( struct HpmfwupgComponentBitMask components, struct HpmfwupgUpgradeCtx* pFwupgCtx, unsigned char** pImagePtr, int componentToUpload, void *intf, int option, int *pFlagColdReset ) { struct HpmfwupgFirmwareImage* pFwImage; struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; struct HpmfwupgUploadFirmwareBlockCtx uploadCmd; struct HpmfwupgFinishFirmwareUploadCtx finishCmd; // struct HpmfwupgGetComponentPropertiesCtx getCompProp; VERSIONINFO *pVersionInfo; time_t start,end; int rc = HPMFWUPG_SUCCESS; int skip = TRUE; unsigned char* pData, *pDataInitial; unsigned char count; unsigned int totalSent = 0; unsigned char bufLength = 0; unsigned int firmwareLength = 0; unsigned int displayFWLength = 0; unsigned char *pDataTemp; unsigned int imageOffset = 0x00; unsigned int blockLength = 0x00; unsigned int lengthOfBlock = 0x00; unsigned int numTxPkts = 0; unsigned int numRxPkts = 0; unsigned char mode = 0; unsigned char componentId = 0x00; unsigned char componentIdByte = 0x00; /* Save component ID on which the upload is done */ componentIdByte = components.ComponentBits.byte; while ((componentIdByte>>=1)!=0) { componentId++; } pFwupgCtx->componentId = componentId; pVersionInfo = (VERSIONINFO*) &gVersionInfo[componentId]; pFwImage = (struct HpmfwupgFirmwareImage*)((*pImagePtr) + sizeof(struct HpmfwupgActionRecord)); pDataInitial = ((unsigned char*)pFwImage + sizeof(struct HpmfwupgFirmwareImage)); pData = pDataInitial; /* Get firmware length */ firmwareLength = pFwImage->length[0]; firmwareLength |= (pFwImage->length[1] << 8) & 0xff00; firmwareLength |= (pFwImage->length[2] << 16) & 0xff0000; firmwareLength |= (pFwImage->length[3] << 24) & 0xff000000; mode = TARGET_VER | IMAGE_VER; if (pVersionInfo->rollbackSupported) { mode |= ROLLBACK_VER; } if ((option & DEBUG_MODE)) { printf("\n\n Comp ID : %d [%-20s]\n",pVersionInfo->componentId,pFwImage->desc); } else { HpmDisplayVersion(mode,pVersionInfo); } if( (1 << componentId) & pFwupgCtx->compUpdateMask.ComponentBits.byte) { if( verbose ) { lprintf(LOG_NOTICE,"Do not skip %d" , componentId); } skip = FALSE; } if(!skip) { /* Initialize parameters */ uploadCmd.req.blockNumber = 0; /* Check if we receive size in parameters */ if(g_channel_buf_size != 0) { if (g_sa == BMC_SA) { bufLength = g_channel_buf_size - 9; /* Plan for overhead */ } else { bufLength = g_channel_buf_size - 11; /* Plan for overhead */ } } else { /* Find max buffer length according the connection parameters */ if ( is_remote() ) /*IPMI LAN*/ { bufLength = HPMFWUPG_SEND_DATA_COUNT_LAN - 2; if (g_sa != BMC_SA) bufLength -= 8; } else { int i; i = get_driver_type(); if ((i == DRV_MV || i == DRV_KCS) && /*open driver*/ (g_sa == BMC_SA) ) { bufLength = HPMFWUPG_SEND_DATA_COUNT_KCS - 2; } else { if ( g_bus == 7 ) { bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMBL; } else { bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMB; } } } } if (verbose) printf("Upgrade buffer size = %d (%d)\n",bufLength,g_channel_buf_size); /* Send Initiate Upgrade Action */ initUpgActionCmd.req.componentsMask = components; /* Action is upgrade */ initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_UPGRADE; rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); if (rc != HPMFWUPG_SUCCESS) { skip = TRUE; } if ( (pVersionInfo->coldResetRequired) && (!skip)) { *pFlagColdReset = TRUE; } /* pDataInitial is the starting pointer of the image data */ /* pDataTemp is one which we will move across */ pData = pDataInitial; pDataTemp = pDataInitial; lengthOfBlock = firmwareLength; totalSent = 0x00; displayFWLength= firmwareLength; time(&start); while ( (pData < (pDataTemp+lengthOfBlock)) && (rc == HPMFWUPG_SUCCESS) ) { if ( (pData+bufLength) <= (pDataTemp+lengthOfBlock) ) { count = bufLength; } else { count = (unsigned char)((pDataTemp+lengthOfBlock) - pData); } memcpy(&uploadCmd.req.data, pData, bufLength); imageOffset = 0x00; blockLength = 0x00; numTxPkts++; rc = HpmfwupgUploadFirmwareBlock(intf, &uploadCmd, pFwupgCtx, count, &imageOffset,&blockLength); numRxPkts++; if ( rc != HPMFWUPG_SUCCESS) { if ( rc == HPMFWUPG_UPLOAD_BLOCK_LENGTH ) { /* Retry with a smaller buffer length */ if ( is_remote() ) // strstr(intf->name,"lan") != NULL { bufLength -= (unsigned char)8; lprintf(LOG_INFO,"Trying reduced buffer length: %d", bufLength); } else { bufLength -= (unsigned char)1; lprintf(LOG_INFO,"Trying reduced buffer length: %d", bufLength); } rc = HPMFWUPG_SUCCESS; } else if ( rc == HPMFWUPG_UPLOAD_RETRY ) { rc = HPMFWUPG_SUCCESS; } else { fflush(stdout); lprintf(LOG_NOTICE,"\n Error in Upload FIRMWARE command [rc=%d]\n",rc); lprintf(LOG_NOTICE,"\n TotalSent:0x%x ",totalSent); /* Exiting from the function */ rc = HPMFWUPG_ERROR; } } else { if (blockLength > firmwareLength) { /* * blockLength is the remaining length of the firmware to upload so * if its greater than the firmware length then its kind of error */ lprintf(LOG_NOTICE,"\n Error in Upload FIRMWARE command [rc=%d]\n",rc); lprintf(LOG_NOTICE,"\n TotalSent:0x%x Img offset:0x%x Blk length:0x%x Fwlen:0x%x\n", totalSent,imageOffset,blockLength,firmwareLength); rc = HPMFWUPG_ERROR; } totalSent += count; if (imageOffset != 0x00) { /* block Length is valid */ lengthOfBlock = blockLength; pDataTemp = pDataInitial + imageOffset; pData = pDataTemp; if ( displayFWLength == firmwareLength) { /* This is basically used only to make sure that we display uptil 100% */ displayFWLength = blockLength + totalSent; } } else { pData += count; } time(&end); /* * Just added debug mode in case we need to see exactly how many bytes have * gone through - Its a hidden option used mainly should be used for debugging */ if ( option & DEBUG_MODE) { fflush(stdout); printf(" Blk Num : %02x Bytes : %05x \r\n", uploadCmd.req.blockNumber,totalSent); if (imageOffset || blockLength) { printf("\r--> ImgOff : %x BlkLen : %x\n",imageOffset,blockLength); } if (displayFWLength == totalSent) { printf(" Time Taken %02d:%02d\n",(end-start)/60, (end-start)%60); printf("\n"); } } else { HpmDisplayUpgrade(0,totalSent,displayFWLength,(end-start)); } uploadCmd.req.blockNumber++; } } } if (skip) { HpmDisplayUpgrade(1,0,0,0); *pImagePtr = pDataInitial + firmwareLength; } if ( (rc == HPMFWUPG_SUCCESS) && (!skip) ) { /* Send finish component */ /* Set image length */ finishCmd.req.componentId = componentId; /* We need to send the actual data that is sent * not the comlete firmware image length */ finishCmd.req.imageLength[0] = totalSent & 0xFF; finishCmd.req.imageLength[1] = (totalSent >> 8) & 0xFF; finishCmd.req.imageLength[2] = (totalSent >> 16) & 0xFF; finishCmd.req.imageLength[3] = (totalSent >> 24) & 0xFF; rc = HpmfwupgFinishFirmwareUpload(intf, &finishCmd, pFwupgCtx); if ( option & DEBUG_MODE) printf("HpmfwupgFinishFirmwareUpload rc = %d sent = %d\n",rc,totalSent); *pImagePtr = pDataInitial + firmwareLength; } return rc; } /**************************************************************************** * * Function Name: HpmfwupgActivationStage * * Description: This function the validation stage of a firmware upgrade * procedure as defined in section 3.4 of the IPM Controller * Firmware Upgrade Specification version 1.0 * *****************************************************************************/ static int HpmfwupgActivationStage(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct HpmfwupgActivateFirmwareCtx activateCmd; struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData; /* Print out stuf...*/ printf(" "); fflush(stdout); /* Activate new firmware */ rc = HpmfwupgActivateFirmware(intf, &activateCmd, pFwupgCtx); if ( rc == HPMFWUPG_SUCCESS ) { /* Query self test result if supported by target and new image */ if ( (pFwupgCtx->targetCap.GlobalCapabilities.bitField.ipmcSelftestCap == 1) || (pImageHeader->imageCapabilities.bitField.imageSelfTest == 1) ) { struct HpmfwupgQuerySelftestResultCtx selfTestCmd; rc = HpmfwupgQuerySelftestResult(intf, &selfTestCmd, pFwupgCtx); if ( rc == HPMFWUPG_SUCCESS ) { /* Get the self test result */ if ( selfTestCmd.resp.result1 != 0x55 ) { /* Perform manual rollback if necessary */ /* BACKUP/ MANUAL ROLLBACK not supported by this UA */ lprintf(LOG_NOTICE," Self test failed:"); lprintf(LOG_NOTICE," Result1 = %x", selfTestCmd.resp.result1); lprintf(LOG_NOTICE," Result2 = %x", selfTestCmd.resp.result2); rc = HPMFWUPG_ERROR; } } else { /* Perform manual rollback if necessary */ /* BACKUP / MANUAL ROLLBACK not supported by this UA */ lprintf(LOG_NOTICE," Self test failed."); } } } /* If activation / self test failed, query rollback status if automatic rollback supported */ if ( rc == HPMFWUPG_ERROR ) { if ( (pFwupgCtx->targetCap.GlobalCapabilities.bitField.autRollback == 1) && (pFwupgCtx->genCompProp[pFwupgCtx->componentId].GeneralCompProperties.bitfield.rollbackBackup != 0x00) ) { struct HpmfwupgQueryRollbackStatusCtx rollCmd; lprintf(LOG_NOTICE," Getting rollback status..."); fflush(stdout); rc = HpmfwupgQueryRollbackStatus(intf, &rollCmd, pFwupgCtx); } } return rc; } int HpmfwupgGetBufferFromFile(char* imageFilename, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; FILE* pImageFile = fopen(imageFilename, "rb"); if ( pImageFile == NULL ) { lprintf(LOG_NOTICE,"Cannot open image file %s", imageFilename); rc = HPMFWUPG_ERROR; } if ( rc == HPMFWUPG_SUCCESS ) { /* Get the raw data in file */ fseek(pImageFile, 0, SEEK_END); pFwupgCtx->imageSize = ftell(pImageFile); pFwupgCtx->pImageData = malloc(sizeof(unsigned char)*pFwupgCtx->imageSize); pFwupgCtx->compUpdateMask.ComponentBits.byte = 0; rewind(pImageFile); if ( pFwupgCtx->pImageData != NULL ) { fread(pFwupgCtx->pImageData, sizeof(unsigned char), pFwupgCtx->imageSize, pImageFile); } else { rc = HPMFWUPG_ERROR; } fclose(pImageFile); } return rc; } int HpmfwupgGetDeviceId(void *intf, struct ipm_devid_rsp* pGetDevId) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_GET_DEVICE_ID; req.msg.data_len = 0; rsp = HpmfwupgSendCmd(intf, req, NULL); if ( rsp ) { if ( rsp->ccode == 0x00 ) { memcpy(pGetDevId, rsp->data, sizeof(struct ipm_devid_rsp)); } else { lprintf(LOG_NOTICE,"Error getting device ID, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error getting device ID\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgGetTargetUpgCapabilities(void *intf, struct HpmfwupgGetTargetUpgCapabilitiesCtx* pCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_GET_TARGET_UPG_CAPABILITIES; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgGetTargetUpgCapabilitiesReq); rsp = HpmfwupgSendCmd(intf, req, NULL); if ( rsp ) { if ( rsp->ccode == 0x00 ) { memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp)); if ( verbose ) { lprintf(LOG_NOTICE,"TARGET UPGRADE CAPABILITIES"); lprintf(LOG_NOTICE,"-------------------------------"); lprintf(LOG_NOTICE,"HPM.1 version............%d ", pCtx->resp.hpmVersion); lprintf(LOG_NOTICE,"Component 0 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component0 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 1 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component1 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 2 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component2 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 3 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component3 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 4 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component4 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 5 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component5 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 6 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component6 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 7 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component7 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Upgrade undesirable.....[%c] ", pCtx->resp.GlobalCapabilities. bitField.fwUpgUndesirable ? 'y' : 'n'); lprintf(LOG_NOTICE,"Aut rollback override...[%c] ", pCtx->resp.GlobalCapabilities. bitField.autRollbackOverride ? 'y' : 'n'); lprintf(LOG_NOTICE,"IPMC degraded...........[%c] ", pCtx->resp.GlobalCapabilities. bitField.ipmcDegradedDurinUpg ? 'y' : 'n'); lprintf(LOG_NOTICE,"Defered activation......[%c] ", pCtx->resp.GlobalCapabilities. bitField.deferActivation ? 'y' : 'n'); lprintf(LOG_NOTICE,"Service affected........[%c] ", pCtx->resp.GlobalCapabilities. bitField.servAffectDuringUpg ? 'y' : 'n'); lprintf(LOG_NOTICE,"Manual rollback.........[%c] ", pCtx->resp.GlobalCapabilities. bitField.manualRollback ? 'y' : 'n'); lprintf(LOG_NOTICE,"Automatic rollback......[%c] ", pCtx->resp.GlobalCapabilities. bitField.autRollback ? 'y' : 'n'); lprintf(LOG_NOTICE,"Self test...............[%c] ", pCtx->resp.GlobalCapabilities. bitField.ipmcSelftestCap ? 'y' : 'n'); lprintf(LOG_NOTICE,"Upgrade timeout.........[%d sec] ", pCtx->resp.upgradeTimeout*5); lprintf(LOG_NOTICE,"Self test timeout.......[%d sec] ", pCtx->resp.selftestTimeout*5); lprintf(LOG_NOTICE,"Rollback timeout........[%d sec] ", pCtx->resp.rollbackTimeout*5); lprintf(LOG_NOTICE,"Inaccessibility timeout.[%d sec] \n", pCtx->resp.inaccessTimeout*5); } } else { lprintf(LOG_NOTICE,"Error getting target upgrade capabilities\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error getting target upgrade capabilities\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgGetComponentProperties(void *intf, struct HpmfwupgGetComponentPropertiesCtx* pCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_GET_COMPONENT_PROPERTIES; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgGetComponentPropertiesReq); rsp = HpmfwupgSendCmd(intf, req, NULL); if ( rsp ) { if ( rsp->ccode == 0x00 ) { switch ( pCtx->req.selector ) { case HPMFWUPG_COMP_GEN_PROPERTIES: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetGeneralPropResp)); if ( verbose ) { lprintf(LOG_NOTICE,"GENERAL PROPERTIES"); lprintf(LOG_NOTICE,"-------------------------------"); lprintf(LOG_NOTICE,"Payload cold reset req....[%c] ", pCtx->resp.Response.generalPropResp. GeneralCompProperties.bitfield.payloadColdReset ? 'y' : 'n'); lprintf(LOG_NOTICE,"Def. activation supported.[%c] ", pCtx->resp.Response.generalPropResp. GeneralCompProperties.bitfield.deferredActivation ? 'y' : 'n'); lprintf(LOG_NOTICE,"Comparison supported......[%c] ", pCtx->resp.Response.generalPropResp. GeneralCompProperties.bitfield.comparisonSupport ? 'y' : 'n'); lprintf(LOG_NOTICE,"Preparation supported.....[%c] ", pCtx->resp.Response.generalPropResp. GeneralCompProperties.bitfield.preparationSupport ? 'y' : 'n'); lprintf(LOG_NOTICE,"Rollback supported........[%c] \n", pCtx->resp.Response.generalPropResp. GeneralCompProperties.bitfield.rollbackBackup ? 'y' : 'n'); } break; case HPMFWUPG_COMP_CURRENT_VERSION: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetCurrentVersionResp)); if ( verbose ) { lprintf(LOG_NOTICE,"Current Version: "); lprintf(LOG_NOTICE," Major: %d", pCtx->resp.Response.currentVersionResp.currentVersion[0]); lprintf(LOG_NOTICE," Minor: %x", pCtx->resp.Response.currentVersionResp.currentVersion[1]); lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d\n", pCtx->resp.Response.currentVersionResp.currentVersion[2], pCtx->resp.Response.currentVersionResp.currentVersion[3], pCtx->resp.Response.currentVersionResp.currentVersion[4], pCtx->resp.Response.currentVersionResp.currentVersion[5]); } break; case HPMFWUPG_COMP_DESCRIPTION_STRING: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetDescStringResp)); if ( verbose ) { lprintf(LOG_NOTICE,"Description string: %s\n", pCtx->resp.Response.descStringResp.descString); } break; case HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetRollbackFwVersionResp)); if ( verbose ) { lprintf(LOG_NOTICE,"Rollback FW Version: "); lprintf(LOG_NOTICE," Major: %d", pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[0]); lprintf(LOG_NOTICE," Minor: %x", pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[1]); lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d\n", pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[2], pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[3], pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[4], pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[5]); } break; case HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetDeferredFwVersionResp)); if ( verbose ) { lprintf(LOG_NOTICE,"Deferred FW Version: "); lprintf(LOG_NOTICE," Major: %d", pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[0]); lprintf(LOG_NOTICE," Minor: %x", pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[1]); lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d\n", pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[2], pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[3], pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[4], pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[5]); } break; // OEM Properties command case HPMFWUPG_COMP_OEM_PROPERTIES: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetOemProperties)); if ( verbose ) { unsigned char i = 0; lprintf(LOG_NOTICE,"OEM Properties: "); for (i=0; i < HPMFWUPG_OEM_LENGTH; i++) { lprintf(LOG_NOTICE," 0x%x ", pCtx->resp.Response.oemProperties.oemRspData[i]); } } break; default: lprintf(LOG_NOTICE,"Unsupported component selector"); rc = HPMFWUPG_ERROR; break; } } else { lprintf(LOG_NOTICE,"Error getting component properties, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error getting component properties\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgAbortUpgrade(void *intf, struct HpmfwupgAbortUpgradeCtx* pCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_ABORT_UPGRADE; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgAbortUpgradeReq); rsp = HpmfwupgSendCmd(intf, req, NULL); if ( rsp ) { if ( rsp->ccode != 0x00 ) { lprintf(LOG_NOTICE,"Error aborting upgrade, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error aborting upgrade\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgInitiateUpgradeAction(void *intf, struct HpmfwupgInitiateUpgradeActionCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_INITIATE_UPGRADE_ACTION; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgInitiateUpgradeActionReq); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { /* Long duration command handling */ if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS ) { rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); } else if ( rsp->ccode != 0x00 ) { lprintf(LOG_NOTICE,"Error initiating upgrade action, compcode = %x %s\n", rsp->ccode, hpm_decode_cc(req.msg.cmd,rsp->ccode)); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error initiating upgrade action\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgUploadFirmwareBlock(void *intf, struct HpmfwupgUploadFirmwareBlockCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx, int count ,unsigned int *imageOffset, unsigned int *blockLength ) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_UPLOAD_FIRMWARE_BLOCK; req.msg.data = (unsigned char*)&pCtx->req; /* 2 is the size of the upload struct - data */ req.msg.data_len = 2 + count; rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS || rsp->ccode == 0x00 ) { /* * We need to check if the response also contains the next upload firmware offset * and the firmware length in its response - These are optional but very vital */ if ( rsp->data_len > 1 ) { /* * If the response data length is greater than 1 it should contain both the * the Section offset and section length. Because we cannot just have * Section offset without section length so the length should be 9 */ if ( rsp->data_len == 9 ) { /* rsp->data[1] - LSB rsp->data[2] - rsp->data[3] = MSB */ *imageOffset = (rsp->data[4] << 24) + (rsp->data[3] << 16) + (rsp->data[2] << 8) + rsp->data[1]; *blockLength = (rsp->data[8] << 24) + (rsp->data[7] << 16) + (rsp->data[6] << 8) + rsp->data[5]; } else { /* * The Spec does not say much for this kind of errors where the * firmware returned only offset and length so currently returning it * as 0x82 - Internal CheckSum Error */ lprintf(LOG_NOTICE,"Error wrong rsp->datalen %d for Upload Firmware block command\n",rsp->data_len); rsp->ccode = HPMFWUPG_INT_CHECKSUM_ERROR; } } } /* Long duration command handling */ if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS ) { rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); } else if (rsp->ccode != 0x00) { /* * PATCH --> This validation is to handle retryables errors codes on IPMB bus. * This will be fixed in the next release of open ipmi and this * check will have to be removed. (Buggy version = 39) */ if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) ) { lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected"); rc = HPMFWUPG_UPLOAD_RETRY; } /* * If completion code = 0xc7, we will retry with a reduced buffer length. * Do not print error. */ else if ( rsp->ccode == IPMI_CC_REQ_DATA_INV_LENGTH ) { rc = HPMFWUPG_UPLOAD_BLOCK_LENGTH; } else { lprintf(LOG_NOTICE,"Error uploading firmware block, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } } else { lprintf(LOG_NOTICE,"Error uploading firmware block\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgFinishFirmwareUpload(void *intf, struct HpmfwupgFinishFirmwareUploadCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_FINISH_FIRMWARE_UPLOAD; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgFinishFirmwareUploadReq); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { /* Long duration command handling */ if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); } else if ( rsp->ccode != IPMI_CC_OK ) { lprintf(LOG_NOTICE,"Error finishing firmware upload, compcode = %x %s\n", rsp->ccode, hpm_decode_cc(req.msg.cmd,rsp->ccode)); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error finishing firmware upload\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgActivateFirmware(void *intf, struct HpmfwupgActivateFirmwareCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_ACTIVATE_FIRMWARE; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgActivateFirmwareReq) - (!pCtx->req.rollback_override ? 1 : 0); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { /* Long duration command handling */ if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { printf("Waiting firmware activation..."); fflush(stdout); rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); if ( rc == HPMFWUPG_SUCCESS ) { lprintf(LOG_NOTICE,"OK"); } else { lprintf(LOG_NOTICE,"Failed"); } } else if (rsp->ccode == HPMFWUPG_NOT_SUPPORTED_NOW) /*0xd5*/ { printf("Activation already completed.\n"); rc = HPMFWUPG_SUCCESS; } else if ( rsp->ccode != IPMI_CC_OK ) { lprintf(LOG_NOTICE,"Error activating firmware, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error activating firmware\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgGetUpgradeStatus(void *intf, struct HpmfwupgGetUpgradeStatusCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_GET_UPGRADE_STATUS; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgGetUpgradeStatusReq); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { if ( rsp->ccode == 0x00 ) { memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetUpgradeStatusResp)); if ( verbose > 1 ) { lprintf(LOG_NOTICE,"Upgrade status:"); lprintf(LOG_NOTICE," Command in progress: %x", pCtx->resp.cmdInProcess); lprintf(LOG_NOTICE," Last command completion code: %x", pCtx->resp.lastCmdCompCode); } } /* * PATCH --> This validation is to handle retryables errors codes on IPMB bus. * This will be fixed in the next release of open ipmi and this * check will have to be removed. (Buggy version = 39) */ else if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) ) { lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected"); pCtx->resp.lastCmdCompCode = HPMFWUPG_COMMAND_IN_PROGRESS; } else { if ( verbose ) { lprintf(LOG_NOTICE,"Error getting upgrade status, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } } else { if ( verbose ) { lprintf(LOG_NOTICE,"Error getting upgrade status"); rc = HPMFWUPG_ERROR; } } return rc; } int HpmfwupgManualFirmwareRollback(void *intf, struct HpmfwupgManualFirmwareRollbackCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgManualFirmwareRollbackReq); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { /* Long duration command handling */ if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS ) { struct HpmfwupgQueryRollbackStatusCtx resCmd; printf("Waiting firmware rollback..."); fflush(stdout); rc = HpmfwupgQueryRollbackStatus(intf, &resCmd, pFwupgCtx); } else if ( rsp->ccode != 0x00 ) { lprintf(LOG_NOTICE,"Error sending manual rollback, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error sending manual rollback\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgQueryRollbackStatus(void *intf, struct HpmfwupgQueryRollbackStatusCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; unsigned int rollbackTimeout = 0; unsigned int timeoutSec1, timeoutSec2; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_QUERY_ROLLBACK_STATUS; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgQueryRollbackStatusReq); /* * If we are not in upgrade context, we use default timeout values */ if ( pFwupgCtx != NULL ) { rollbackTimeout = pFwupgCtx->targetCap.rollbackTimeout*5; } else { struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; verbose--; rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd); verbose++; if ( rc == HPMFWUPG_SUCCESS ) { rollbackTimeout = targetCapCmd.resp.rollbackTimeout *5; } else { rollbackTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; } } /* Poll rollback status until completion or timeout */ timeoutSec1 = (uint32_t)time(NULL); timeoutSec2 = (uint32_t)time(NULL); do { /* Must wait at least 100 ms between status requests */ os_usleep(0,100000); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); /* * PATCH --> This validation is to handle retryables errors codes on IPMB bus. * This will be fixed in the next release of open ipmi and this * check will have to be removed. (Buggy version = 39) */ if ( rsp ) { if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) ) { lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected"); rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS; } } timeoutSec2 = (uint32_t)time(NULL); }while( rsp && (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) && (timeoutSec2 - timeoutSec1 < rollbackTimeout ) ); if ( rsp ) { if ( rsp->ccode == 0x00 ) { memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgQueryRollbackStatusResp)); if ( pCtx->resp.rollbackComp.ComponentBits.byte != 0 ) { /* Rollback occured */ lprintf(LOG_NOTICE,"Rollback occured on component mask: 0x%02x", pCtx->resp.rollbackComp.ComponentBits.byte); } else { lprintf(LOG_NOTICE,"No Firmware rollback occured"); } } else if ( rsp->ccode == 0x81 ) { lprintf(LOG_NOTICE,"Rollback failed on component mask: 0x%02x", pCtx->resp.rollbackComp.ComponentBits.byte); rc = HPMFWUPG_ERROR; } else { lprintf(LOG_NOTICE,"Error getting rollback status, compcode = %x", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error getting upgrade status\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgQuerySelftestResult(void *intf, struct HpmfwupgQuerySelftestResultCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; unsigned char selfTestTimeout = 0; unsigned int timeoutSec1, timeoutSec2; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; /* * If we are not in upgrade context, we use default timeout values */ if ( pFwupgCtx != NULL ) { /* Getting selftest timeout from new image */ struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData; selfTestTimeout = pImageHeader->selfTestTimeout; } else { selfTestTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; } memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_QUERY_SELFTEST_RESULT; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgQuerySelftestResultReq); /* Poll rollback status until completion or timeout */ timeoutSec1 = (uint32_t)time(NULL); timeoutSec2 = (uint32_t)time(NULL); do { /* Must wait at least 100 ms between status requests */ os_usleep(0,100000); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); /* * PATCH --> This validation is to handle retryables errors codes on IPMB bus. * This will be fixed in the next release of open ipmi and this * check will have to be removed. (Buggy version = 39) */ if ( rsp ) { if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) ) { lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected"); rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS; } } timeoutSec2 = (uint32_t)time(NULL); }while( rsp && (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) && (timeoutSec2 - timeoutSec1 < selfTestTimeout ) ); if ( rsp ) { if ( rsp->ccode == 0x00 ) { memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgQuerySelftestResultResp)); if ( verbose ) { lprintf(LOG_NOTICE,"Self test results:"); lprintf(LOG_NOTICE,"Result1 = %x", pCtx->resp.result1); lprintf(LOG_NOTICE,"Result2 = %x", pCtx->resp.result2); } } else { lprintf(LOG_NOTICE,"Error getting self test results, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error getting upgrade status\n"); rc = HPMFWUPG_ERROR; } return rc; } struct ipmi_rs * HpmfwupgSendCmd(void *intf, struct ipmi_rq req, struct HpmfwupgUpgradeCtx* pFwupgCtx ) { struct ipmi_rs * rsp; unsigned int inaccessTimeout = 0, inaccessTimeoutCounter = 0; unsigned int upgradeTimeout = 0, upgradeTimeoutCounter = 0; unsigned int timeoutSec1, timeoutSec2; unsigned char retry = 0; static struct ipmi_rs fakeRsp; int rv, rsp_len; /* * If we are not in upgrade context, we use default timeout values */ if ( pFwupgCtx != NULL ) { inaccessTimeout = pFwupgCtx->targetCap.inaccessTimeout*5; upgradeTimeout = pFwupgCtx->targetCap.upgradeTimeout*5; } else { /* keeping the inaccessTimeout to 60 seconds results in almost 2900 retries * So if the target is not available it will be retrying the command for 2900 * times which is not effecient -So reducing the Timout to 5 seconds which is * almost 200 retries if it continuously recieves 0xC3 as completion code. */ inaccessTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; } timeoutSec1 = (uint32_t)time(NULL); do { static unsigned char isValidSize = FALSE; rv = ipmi_sendrecv(&req, fakeRsp.data, &rsp_len); if( rv < 0) { #define HPM_LAN_PACKET_RESIZE_LIMIT 6 if(is_remote()) /* also covers lanplus */ { static int errorCount=0; lprintf(LOG_DEBUG,"HPM: no response available"); lprintf(LOG_DEBUG,"HPM: the command may be rejected for " \ "security reasons"); if ( req.msg.netfn == IPMI_NETFN_PICMG && req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK && errorCount < HPM_LAN_PACKET_RESIZE_LIMIT && (!isValidSize) ) { lprintf(LOG_DEBUG,"HPM: upload firmware block API called"); lprintf(LOG_DEBUG,"HPM: returning length error to force resize"); fakeRsp.ccode = IPMI_CC_REQ_DATA_INV_LENGTH; rv = fakeRsp.ccode; rsp = &fakeRsp; errorCount++; } else if ( req.msg.netfn == IPMI_NETFN_PICMG && ( req.msg.cmd == HPMFWUPG_ACTIVATE_FIRMWARE || req.msg.cmd == HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK ) ) { /* * rsp == NULL and command activate firmware or manual firmware * rollback most likely occurs when we have sent a firmware activation * request. Fake a command in progress response. */ lprintf(LOG_DEBUG,"HPM: activate/rollback firmware API called"); lprintf(LOG_DEBUG,"HPM: returning in progress to handle IOL session lost"); fakeRsp.ccode = HPMFWUPG_COMMAND_IN_PROGRESS; rv = fakeRsp.ccode; rsp = &fakeRsp; } else if ( req.msg.netfn == IPMI_NETFN_PICMG && ( req.msg.cmd == HPMFWUPG_QUERY_ROLLBACK_STATUS || req.msg.cmd == HPMFWUPG_GET_UPGRADE_STATUS ) ) { /* * rsp == NULL and command get upgrade status or query rollback * status most likely occurs when we are waiting for firmware * activation. Try to re-open the IOL session (re-open will work * once the IPMC recovers from firmware activation. */ lprintf(LOG_DEBUG,"HPM: upg/rollback status firmware API called"); lprintf(LOG_DEBUG,"HPM: try to re-open IOL session"); { /* force session re-open */ ipmi_close_(); os_usleep(inaccessTimeout,0); /* Fake timeout to retry command */ fakeRsp.ccode = 0xc3; rv = fakeRsp.ccode; rsp = &fakeRsp; } } } } /* Handle inaccessibility timeout (rsp = NULL if IOL) */ if ( rv < 0 || rv == 0xff || rv == 0xc3 || rv == 0xd3 ) { if ( inaccessTimeoutCounter < inaccessTimeout ) { timeoutSec2 = (uint32_t)time(NULL); if ( timeoutSec2 > timeoutSec1 ) { inaccessTimeoutCounter += timeoutSec2 - timeoutSec1; timeoutSec1 = (uint32_t)time(NULL); } os_usleep(0,100000); retry = 1; } else { retry = 0; } } /* Handle node busy timeout */ else if ( rv == 0xc0 ) { if ( upgradeTimeoutCounter < upgradeTimeout ) { timeoutSec2 = (uint32_t)time(NULL); if ( timeoutSec2 > timeoutSec1 ) { timeoutSec1 = (uint32_t)time(NULL); // upgradeTimeoutCounter += timeoutSec2 - timeoutSec1; upgradeTimeoutCounter += 1; } os_usleep(0,100000); retry = 1; } else { retry = 0; } } else { #ifdef ENABLE_OPENIPMI_V39_PATCH if( rv == IPMI_CC_OK ) { errorCount = 0 ; } #endif retry = 0; if ( req.msg.netfn == IPMI_NETFN_PICMG && req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK && (!isValidSize) ) { lprintf(LOG_INFO,"Buffer length is now considered valid" ); isValidSize = TRUE; } } }while( retry ); if (rv < 0) rsp = NULL; else { rsp = &fakeRsp; /*has data already*/ rsp->ccode = (uchar)rv; rsp->session.payloadtype = 0; /*IPMI_PAYLOAD_TYPE_IPMI*/ rsp->data_len = rsp_len; } return rsp; } int HpmfwupgWaitLongDurationCmd(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; unsigned int upgradeTimeout = 0; unsigned int timeoutSec1, timeoutSec2; struct HpmfwupgGetUpgradeStatusCtx upgStatusCmd; /* * If we are not in upgrade context, we use default timeout values */ if ( pFwupgCtx != NULL ) { upgradeTimeout = pFwupgCtx->targetCap.upgradeTimeout*5; if ( verbose ) printf("Use File Upgrade Capabilities: %i seconds\n", upgradeTimeout); } else { /* Try to retreive from Caps */ struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; if(HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd) != HPMFWUPG_SUCCESS) { upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; if ( verbose ) printf("Use default timeout: %i seconds\n", upgradeTimeout); } else { upgradeTimeout = (targetCapCmd.resp.upgradeTimeout * 5); if ( verbose ) printf("Use Command Upgrade Capabilities Timeout: %i seconds\n", upgradeTimeout); } } if(rc == HPMFWUPG_SUCCESS) { /* Poll upgrade status until completion or timeout*/ timeoutSec1 = (uint32_t)time(NULL); timeoutSec2 = (uint32_t)time(NULL); rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx); } while( (upgStatusCmd.resp.lastCmdCompCode == HPMFWUPG_COMMAND_IN_PROGRESS ) && (timeoutSec2 - timeoutSec1 < upgradeTimeout ) && (rc == HPMFWUPG_SUCCESS) ) { /* Must wait at least 1000 ms between status requests */ os_usleep(0,1000000); rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx); //printf("Get Status: %x - %x = %x _ %x [%x]\n", timeoutSec2, timeoutSec1,(timeoutSec2 - timeoutSec1),upgradeTimeout, rc); } if ( upgStatusCmd.resp.lastCmdCompCode != 0x00 ) { if ( verbose ) { lprintf(LOG_NOTICE,"Error waiting for command %x, compcode = %x", upgStatusCmd.resp.cmdInProcess, upgStatusCmd.resp.lastCmdCompCode, hpm_decode_cc(upgStatusCmd.resp.cmdInProcess, upgStatusCmd.resp.lastCmdCompCode)); } rc = HPMFWUPG_ERROR; } return rc; } unsigned char HpmfwupgCalculateChecksum(unsigned char* pData, unsigned int length) { unsigned char checksum = 0; int dataIdx = 0; for ( dataIdx = 0; dataIdx < (int)length; dataIdx++ ) { checksum += pData[dataIdx]; } return checksum; } static void HpmfwupgPrintUsage(void) { lprintf(LOG_NOTICE,"help - This help menu"); lprintf(LOG_NOTICE,"check - Check the target information"); lprintf(LOG_NOTICE,"check - If the user is unsure of what update is going to be "); lprintf(LOG_NOTICE," This will display the existing target version and image "); lprintf(LOG_NOTICE," version on the screen"); lprintf(LOG_NOTICE,"upgrade - Upgrade the firmware using a valid HPM.1 image "); lprintf(LOG_NOTICE," This checks the version from the file and image and "); lprintf(LOG_NOTICE," if it differs then only updates else skips"); lprintf(LOG_NOTICE,"upgrade all - Updates all the components present in the file on the target board"); lprintf(LOG_NOTICE," without skipping (use this only after using \"check\" command"); lprintf(LOG_NOTICE,"upgrade component x - Upgrade only component from the given "); lprintf(LOG_NOTICE," component 0 - BOOT"); lprintf(LOG_NOTICE," component 1 - RTK"); lprintf(LOG_NOTICE,"upgrade activate - Upgrade the firmware using a valid HPM.1 image "); lprintf(LOG_NOTICE," If activate is specified, activate new firmware rigth"); lprintf(LOG_NOTICE," away"); lprintf(LOG_NOTICE,"activate [norollback] - Activate the newly uploaded firmware"); lprintf(LOG_NOTICE,"targetcap - Get the target upgrade capabilities"); lprintf(LOG_NOTICE,"compprop can be one of the following: "); lprintf(LOG_NOTICE," 0- General properties"); lprintf(LOG_NOTICE," 1- Current firmware version"); lprintf(LOG_NOTICE," 2- Description string"); lprintf(LOG_NOTICE," 3- Rollback firmware version"); lprintf(LOG_NOTICE," 4- Deferred firmware version"); lprintf(LOG_NOTICE,"abort - Abort the on-going firmware upgrade"); lprintf(LOG_NOTICE,"upgstatus - Returns the status of the last long duration command"); lprintf(LOG_NOTICE,"rollback - Performs a manual rollback on the IPM Controller"); lprintf(LOG_NOTICE," firmware"); lprintf(LOG_NOTICE,"rollbackstatus - Query the rollback status"); lprintf(LOG_NOTICE,"selftestresult - Query the self test results\n"); } int ipmi_hpmfwupg_main(void * intf, int argc, char ** argv) { int rc = HPMFWUPG_SUCCESS; int activateFlag = 0x00; int componentId = DEFAULT_COMPONENT_UPLOAD; int option = VERSIONCHECK_MODE; lprintf(LOG_DEBUG,"ipmi_hpmfwupg_main()"); lprintf(LOG_NOTICE,"\nPICMG HPM.1 Upgrade Agent %d.%d.%d: \n", HPMFWUPG_VERSION_MAJOR, HPMFWUPG_VERSION_MINOR, HPMFWUPG_VERSION_SUBMINOR); if ( (argc == 0) || (strcmp(argv[0], "help") == 0) ) { HpmfwupgPrintUsage(); return ERR_USAGE; } if ( (strcmp(argv[0], "check") == 0) ) { /* hpm check */ if (argv[1] == NULL) { rc = HpmfwupgTargetCheck(intf,VIEW_MODE); } else { /* hpm check */ rc = HpmfwupgTargetCheck(intf,0); if (rc == HPMFWUPG_SUCCESS) { rc = HpmfwupgUpgrade(intf, argv[1],0,DEFAULT_COMPONENT_UPLOAD,VIEW_MODE); } } } else if ( strcmp(argv[0], "upgrade") == 0) { int i =0; if (fdebug) option |= DEBUG_MODE; if (g_channel_buf_size > 0) printf("Large buffer size %d specified\n", g_channel_buf_size ); for (i=1; i< argc ; i++) { if (strcmp(argv[i],"activate") == 0) { activateFlag = 1; } /* hpm upgrade all */ if (strcmp(argv[i],"all") == 0) { option &= ~(VERSIONCHECK_MODE); option &= ~(VIEW_MODE); option |= FORCE_MODE_ALL; } /* hpm upgrade component */ if (strcmp(argv[i],"component") == 0) { if (i+1 < argc) { componentId = atoi(argv[i+1]); option &= ~(VERSIONCHECK_MODE); option &= ~(VIEW_MODE); option |= FORCE_MODE_COMPONENT; if( verbose ) { lprintf(LOG_NOTICE,"Component Id %d provided",componentId ); } /* Error Checking */ if (componentId >= HPMFWUPG_COMPONENT_ID_MAX) { lprintf(LOG_NOTICE,"Given component ID %d exceeds Max Comp ID %d\n", componentId, HPMFWUPG_COMPONENT_ID_MAX-1); return HPMFWUPG_ERROR; } } if (componentId == DEFAULT_COMPONENT_UPLOAD) { /* That indicates the user has given component on console but not * given any ID */ lprintf(LOG_NOTICE,"No component Id provided\n"); return HPMFWUPG_ERROR; } } if (strcmp(argv[i],"debug") == 0) { option |= DEBUG_MODE; } } rc = HpmfwupgTargetCheck(intf,0); if (rc == HPMFWUPG_SUCCESS) { /* Call the Upgrade function to start the upgrade */ rc = HpmfwupgUpgrade(intf, argv[1],activateFlag,componentId,option); } } else if ( (argc >= 1) && (strcmp(argv[0], "activate") == 0) ) { struct HpmfwupgActivateFirmwareCtx cmdCtx; if ( (argc == 2) && (strcmp(argv[1], "norollback") == 0) ) cmdCtx.req.rollback_override = 1; else cmdCtx.req.rollback_override = 0; rc = HpmfwupgActivateFirmware(intf, &cmdCtx, NULL); } else if ( (argc == 1) && (strcmp(argv[0], "targetcap") == 0) ) { struct HpmfwupgGetTargetUpgCapabilitiesCtx cmdCtx; verbose++; rc = HpmfwupgGetTargetUpgCapabilities(intf, &cmdCtx); } else if ( (argc == 3) && (strcmp(argv[0], "compprop") == 0) ) { struct HpmfwupgGetComponentPropertiesCtx cmdCtx; cmdCtx.req.componentId = atob(argv[1]); cmdCtx.req.selector = atob(argv[2]); verbose++; rc = HpmfwupgGetComponentProperties(intf, &cmdCtx); } else if ( (argc == 1) && (strcmp(argv[0], "abort") == 0) ) { struct HpmfwupgAbortUpgradeCtx cmdCtx; verbose++; rc = HpmfwupgAbortUpgrade(intf, &cmdCtx); } else if ( (argc == 1) && (strcmp(argv[0], "upgstatus") == 0) ) { struct HpmfwupgGetUpgradeStatusCtx cmdCtx; verbose++; rc = HpmfwupgGetUpgradeStatus(intf, &cmdCtx, NULL); } else if ( (argc == 1) && (strcmp(argv[0], "rollback") == 0) ) { struct HpmfwupgManualFirmwareRollbackCtx cmdCtx; verbose++; rc = HpmfwupgManualFirmwareRollback(intf, &cmdCtx, NULL); } else if ( (argc == 1) && (strcmp(argv[0], "rollbackstatus") == 0) ) { struct HpmfwupgQueryRollbackStatusCtx cmdCtx; verbose++; rc = HpmfwupgQueryRollbackStatus(intf, &cmdCtx, NULL); } else if ( (argc == 1) && (strcmp(argv[0], "selftestresult") == 0) ) { struct HpmfwupgQuerySelftestResultCtx cmdCtx; verbose++; rc = HpmfwupgQuerySelftestResult(intf, &cmdCtx, NULL); } else { HpmfwupgPrintUsage(); } return rc; } #ifdef METACOMMAND int i_hpm(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { void *intf = NULL; int rc = 0; int c, i; char *s1; printf("%s ver %s\n", progname,progver); set_loglevel(LOG_NOTICE); while ( (c = getopt( argc, argv,"m:z:T:V:J:EYF:P:N:R:U:Z:x?")) != EOF ) switch (c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'z': g_channel_buf_size = atoi(optarg); if (g_channel_buf_size < HPMFWUPG_SEND_DATA_COUNT_LAN) rc = ERR_BAD_LENGTH; else if (g_channel_buf_size > IPMI_REQBUF_SIZE) rc = LAN_ERR_BADLENGTH; if (rc != 0) { printf("Invalid buffer size %d\n",g_channel_buf_size); return rc; } break; case 'x': fdebug = 1; verbose = 1; set_loglevel(LOG_DEBUG); break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; case '?': HpmfwupgPrintUsage(); return ERR_USAGE; break; } for (i = 0; i < optind; i++) { argv++; argc--; } rc = ipmi_hpmfwupg_main(intf, argc, argv); ipmi_close_(); // show_outcome(progname,rc); return rc; } /* end ihpm.c */ ipmiutil-3.1.5/util/idiscover.c0000644000076400007640000007454613566765324016606 0ustar mgportalloggers/* * idiscover.c * Discover all IPMI-LAN-enabled nodes on this network or subnet. * This program is not completely reliable yet, not all IPMI-LAN-enabled * nodes respond. * Currently this utility is compiled with NO_THREADS, but threads can * be enabled by commenting out this flag. * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2006 Intel Corporation. * Copyright (c) 2009 Kontron America, Inc. * * 10/27/06 Andy Cress - created * 05/01/07 Andy Cress - added -g for GetChannelAuthCap method, * added -a logic for broadcast ping, * updated WIN32 logic * 09/20/07 Andy Cress - fixed send/receive thread order * 07/15/08 Andy Cress - added -r for ping repeats * 11/21/08 Andy Cress - detect eth intf and broadcast ip addr * 01/04/16 Andy Cress - v1.11, allow 0 if fBroadcastOk (-a) */ /*M* Copyright (c) 2006, Intel Corporation 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 Corporation 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*/ #if defined(HAVE_CONFIG_H) #include "config.h" #endif #ifdef WIN32 #include #include #include #include #include #include #include "getopt.h" #define NO_THREADS 1 typedef unsigned int socklen_t; WSADATA lan_ws; /*global for WSA*/ #elif defined(DOS) #include #include #include #include #include "getopt.h" #define NO_THREADS 1 #else /* Linux, BSD, Solaris */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #include #ifndef HAVE_CONFIG_H typedef unsigned int socklen_t; #endif #else #include #endif /* comment out NO_THREADS to use this utility in Linux with threads */ #define NO_THREADS 1 #endif #ifndef ETH_P_IP #define ETH_P_IP 0x0800 /* Internet Protocol packet, see linux/if_ether.h */ #endif /* TODO: fix RAW for -m in Solaris, FreeBSD, Windows (works in Linux) */ #ifdef SOLARIS #include #define RAW_DOMAIN AF_INET #define RAW_PROTO IPPROTO_RAW static char frawok = 0; /*raw not working in Solaris*/ #elif BSD #define RAW_DOMAIN AF_INET #define RAW_PROTO IPPROTO_RAW static char frawok = 0; /*raw not working in FreeBSD*/ #elif HPUX #define RAW_DOMAIN AF_INET #define RAW_PROTO IPPROTO_RAW static char frawok = 0; /*raw not working in HPUX*/ #elif MACOS #define RAW_DOMAIN AF_INET #define RAW_PROTO IPPROTO_RAW static char frawok = 0; /*raw not working in MacOS*/ #elif WIN32 #define RAW_DOMAIN AF_INET #define RAW_PROTO IPPROTO_ICMP static char frawok = 0; /*raw not working in Windows*/ #else #define RAW_DOMAIN AF_PACKET #define RAW_PROTO htons(ETH_P_IP) static char frawok = 1; /*raw works in Linux*/ #endif #include #include "ipmicmd.h" #ifndef INET_ADDRSTRLEN #define INET_ADDRSTRLEN 16 #endif #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 #endif #define RMCP_PRI_RMCP_PORT 0x26F #define SZ_PING 12 #define IPMI_PING_MAX_LEN 50 /* usu 28 */ #define CMD_GET_CHAN_AUTH_CAP 0x38 #ifdef WIN32 int GetFirstIP(uchar *ipaddr, uchar *macadr, char *ipname, char fdb); /*ilan.c*/ #endif /* * Global variables */ static char * progver = "1.11"; static char * progname = "idiscover"; static char fdebug = 0; static char fping = 1; static char fraw = 0; static char fBroadcastOk = 0; static char fcanonical = 0; static int broadcast_pings = 1; //static uchar ipmi_maj = 0; //static uchar ipmi_min = 0; //static uchar netfn; static ushort g_port = RMCP_PRI_RMCP_PORT; static SockType g_sockfd = 0; static SockType g_sockraw = 0; static int g_limit = 30; /* after this many 'other' packets, stop. */ static struct sockaddr_in _srcaddr; // static struct sockaddr_in _destaddrlist[255]; static struct in_addr _startAddr, _endAddr; static char g_startDest[MAXHOSTNAMELEN+1] = {'\0'}; static char g_endDest[MAXHOSTNAMELEN+1] = {'\0'}; static char g_interface[INET_ADDRSTRLEN+1] = {""}; /*e.g. "eth0"*/ static int g_num_packets = 0; static int g_npings = 0; static int g_npongs = 0; static int g_recv_status = 0; static int g_wait = 1; /* num sec to wait */ static int g_delay = 0; /* num usec between sends */ static int g_repeat = 1; /* number of times to repeat ping to each node */ static char bdelim = BDELIM; /* '|' */ #ifdef METACOMMAND extern FILE *fpdbg; /*from ipmicmd.c*/ extern char *strlasterr(int rv); /*from ipmilan.c*/ #else void dump_buf(char *tag, uchar *pbuf, int sz, char fshowascii) { uchar line[17]; uchar a; int i, j; FILE *fpdbg; fpdbg = stdout; line[0] = 0; line[16] = 0; j = 0; fprintf(fpdbg,"%s (len=%d): ", tag,sz); for (i = 0; i < sz; i++) { if (i % 16 == 0) { j = 0; fprintf(fpdbg,"%s\n %04x: ",line,i); } if (fshowascii) { a = pbuf[i]; if (a < 0x20 || a > 0x7f) a = '.'; line[j++] = a; } fprintf(fpdbg,"%02x ",pbuf[i]); } if (j < 16) { line[j] = 0; for (i = 0; i < (16-j); i++) fprintf(fpdbg," "); } fprintf(fpdbg,"%s\n",line); return; } #endif void printerr( const char *pattn, ...) { va_list arglist; FILE *fderr; // fderr = fopen("/tmp/idiscover.log","a+"); // if (fderr == NULL) return; fderr = stderr; va_start(arglist, pattn); vfprintf(fderr, pattn, arglist); va_end(arglist); // fclose(fderr); } static char *showlasterr(void) { char *str; #ifdef WIN32 static char strbuf[80]; int rv; char *desc; rv = WSAGetLastError(); #ifdef METACOMMAND /* get descriptions from strlasterr in ipmilan.c */ desc = strlasterr(rv); #else if (rv == WSAECONNRESET) desc = "Connection reset"; /*10054*/ else if (rv == WSAECONNREFUSED) desc = "Connection refused"; /*10061*/ else if (rv == WSAEHOSTUNREACH) desc = "No route to host"; /*10065*/ else desc = ""; #endif sprintf(strbuf,"LastError = %d %s",rv,desc); str = strbuf; #else str = strerror(errno); #endif return(str); } static void cleanup(void) { SockType *pfd; int i; for (i = 0; i < 2; i++) { if (i == 0) pfd = &g_sockfd; else pfd = &g_sockraw; if (*pfd > 0) { #ifdef WIN32 closesocket(*pfd); WSACleanup(); #else close(*pfd); #endif } *pfd = 0; } } void show_usage(void) { printf("Usage: %s [-abegix] \n",progname); printf(" -a all nodes, enables broadcast ping\n"); printf(" -b beginning IP address (x.x.x.x), required\n"); printf(" -e ending IP address (x.x.x.x), default is begin IP\n"); printf(" -g use GetChanAuthCap instead of RMCP ping\n"); printf(" -i interface name, default is eth0\n"); printf(" -m get MAC addresses with a raw broadcast ping\n"); printf(" -p N specific Port (IPMI LAN port=623)\n"); printf(" -r N number of Repeat pings to each node (default=1)\n"); // printf(" -s specific subnet\n"); printf(" -x show eXtra debug messages\n"); } static int os_sleep(unsigned int s, unsigned int u) { #ifdef WIN32 if (s == 0) { if (u >= 1000) Sleep(u/1000); } else { Sleep(s * 1000); } #else /*Linux*/ #ifdef SELECT_TIMER struct timeval tv; tv.tv_sec = s; tv.tv_usec = u; if (select(1, NULL, NULL, NULL, &tv) < 0) printerr("select: %s\n", showlasterr()); #else if (s == 0) { usleep(u); } else { sleep(s); } #endif #endif return 0; } void split_ip(uint addr, uchar *ip) { ip[3] = (addr & 0x000000ff); ip[2] = (addr & 0x0000ff00) >> 8; ip[1] = (addr & 0x00ff0000) >> 16; ip[0] = (addr & 0xff000000) >> 24; } int ntoi(int addr) { return(addr); } void show_ip(int saddr) { uchar ip[4]; split_ip(saddr,ip); printerr("%d.%d.%d.%d\n",ip[0],ip[1],ip[2],ip[3]); } static int ipmilan_sendto(SockType s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) { int n; #ifdef NEED_PAD int fusepad = 0; /* Never need a pad byte for ping/pong packets */ if (len == 56 || len == 84 || len == 112 || len == 128 || len == 156) { fusepad = 1; len += 1; } #endif n = (int)sendto(s,msg,len,flags,to,tolen); // if (fusepad && (n > 0)) n--; return(n); } static int ipmilan_recvfrom(SockType s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) { int rv; rv = (int)recvfrom(s,buf,len,flags,from,fromlen); /* Sometimes the OS sends an ECONNREFUSED error, but * retrying will catch the BMC's reply packet. */ #ifdef WIN32 if (rv < 0) { int err; err = WSAGetLastError(); if (err == WSAECONNREFUSED) /*10061*/ rv = (int)recvfrom(s,buf,len,flags,from,fromlen); } #else if ((rv < 0) && (errno == ECONNREFUSED)) rv = (int)recvfrom(s,buf,len,flags,from,fromlen); #endif return(rv); } #if defined(WIN32) int inet_aton(const char *cp, struct in_addr *inp) { int rv; int adr; inp->s_addr = inet_addr(cp); adr = (int)inp->s_addr; if (adr == INADDR_NONE) rv = 0; else rv = 1; /*success*/ return(rv); } #elif defined(SOLARIS) || defined(HPUX) int find_ifname(char *ifname) { return(-1); } #else #include int find_ifname(char *ifname) { struct ifaddrs *ifaddr, *ifa; int rv = -1; if (getifaddrs(&ifaddr) == -1) return(rv); for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) continue; if (strcmp(ifa->ifa_name,"lo") == 0) continue; /* if here, we have a valid ifname */ strcpy(ifname,ifa->ifa_name); if (fdebug) printf("find_ifname: found %s\n",ifname); rv = 0; break; } freeifaddrs(ifaddr); return(rv); } #endif int sock_init( char *_interface, char *_startIP, char *_endIP) { int rv; uchar *pb; uchar val; #ifdef WIN32 DWORD rvl; rvl = WSAStartup(0x0101,&lan_ws); if (rvl != 0) { printerr("init: WSAStartup(1.1) error %ld\n", rvl); return((int)rvl); } #else char findif; #endif if ((g_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SockInvalid) { printerr("socket: %s\n", showlasterr()); return(-1); } memset(&_srcaddr, 0, sizeof(_srcaddr)); _srcaddr.sin_family = AF_INET; _srcaddr.sin_port = htons(0); _srcaddr.sin_addr.s_addr = htonl(INADDR_ANY); #ifdef WIN32 { int ret; uchar osip[4]; uchar osmac[6]; uchar osname[64]; char ipstr[20]; char *temp_start; if (fBroadcastOk && (g_startDest[0] == 0)) { ret = GetFirstIP(osip,osmac,osname,fdebug); /*ilan.c*/ if (ret == 0) { // osip[3] = 0xFF; /*255 for broadcast*/ sprintf(ipstr,"%d.%d.%d.255",osip[0],osip[1],osip[2]); temp_start = ipstr; strcpy(g_startDest,temp_start); strcpy(g_endDest,temp_start); } else { /*use some defaults*/ strcpy(g_startDest,"255.255.255.255"); strcpy(g_endDest,"255.255.255.255"); } } } #elif defined(HPUX) { /*find the OS eth interface to use*/ char devname[INET_ADDRSTRLEN+1]; int i, n; n = 0; sprintf(devname,"lan%d",n); } #else { /*find the OS eth interface to use*/ struct sockaddr_in temp_sockaddr; char *temp_start; struct ifreq ifr; char devname[INET_ADDRSTRLEN+1]; int i, n; if (_interface == NULL) findif = 1; else if (_interface[0] == 0) findif = 1; else findif = 0; if (findif) { n = find_ifname(devname); if (n >= 0) { _interface = devname; findif = 0; /*found, do not find again below */ } } if (findif) { /* try again to find the first active ethN interface */ n = -1; for (i = 0; (i < 16) && (n == -1); i++) { #ifdef SOLARIS sprintf(devname,"e1000g%d",i); #elif BSD sprintf(devname,"em%d",i); #else sprintf(devname,"eth%d",i); #endif strcpy(ifr.ifr_name, devname); ifr.ifr_addr.sa_family = AF_INET; if (ioctl(g_sockfd, SIOCGIFADDR, &ifr) >= 0) { /* valid IP address, so active interface, use it */ temp_sockaddr = *((struct sockaddr_in *)&ifr.ifr_addr); memcpy(&_srcaddr.sin_addr.s_addr, &temp_sockaddr.sin_addr.s_addr, sizeof(_srcaddr.sin_addr.s_addr)); strcpy(g_interface, devname); temp_start = inet_ntoa(temp_sockaddr.sin_addr); if (temp_start == NULL) temp_start = ""; else if (fBroadcastOk && (g_startDest[0] == 0)) { pb = (uchar *)&temp_sockaddr.sin_addr.s_addr; pb[3] = 0xFF; /*255 for broadcast*/ temp_start = inet_ntoa(temp_sockaddr.sin_addr); strcpy(g_startDest,temp_start); strcpy(g_endDest,temp_start); } printf("sock_init: found %s with %s\n",devname,temp_start); n = i; break; } } if (n < 0) rv = LAN_ERR_OTHER; /*-13*/ } else { /* valid _interface string */ if (strchr(_interface, '.') != NULL) { /* assume it is an IP address*/ if ((rv = inet_pton(AF_INET, _interface, &_srcaddr.sin_addr)) < 0) printerr("inet_pton: %s\n", showlasterr()); if (rv == 0) printerr("invalid interface address\n"); return(rv); } else { /* assume interface name, like eth0 */ strncpy(ifr.ifr_name, _interface, IFNAMSIZ); ifr.ifr_addr.sa_family = AF_INET; if (ioctl(g_sockfd, SIOCGIFADDR, &ifr) < 0) { printerr("ioctl(%s): %s\n", _interface, showlasterr()); return(-1); } temp_sockaddr = *((struct sockaddr_in *)&ifr.ifr_addr); memcpy(&_srcaddr.sin_addr.s_addr, &temp_sockaddr.sin_addr.s_addr, sizeof(_srcaddr.sin_addr.s_addr)); if (fBroadcastOk && (g_startDest[0] == 0)) { pb = (uchar *)&temp_sockaddr.sin_addr.s_addr; pb[3] = 0xFF; /*255 for broadcast*/ temp_start = inet_ntoa(temp_sockaddr.sin_addr); strcpy(g_startDest,temp_start); strcpy(g_endDest,temp_start); } } } } #endif if (fBroadcastOk) { rv = setsockopt(g_sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast_pings, sizeof(broadcast_pings)); if (rv) { printerr("setsockopt: %s\n", showlasterr()); return(-1); } } if (bind(g_sockfd, (struct sockaddr *)&_srcaddr, sizeof(_srcaddr)) < 0) { printerr("bind: %s\n", showlasterr()); return(-1); } rv = inet_aton(_startIP, &_startAddr); if (rv ) { _startAddr.s_addr = ntohl(_startAddr.s_addr); if (fdebug) show_ip(_startAddr.s_addr); pb = (unsigned char*)&_startAddr.s_addr; if (!fBroadcastOk && (pb[0] < 1) ) printerr("Malformed begin IP: %s\n", _startIP); else if (!fBroadcastOk && (pb[0] >254) ) printerr("Malformed begin IP: %s\n", _startIP); else if (fBroadcastOk) { val = pb[0] & 0x0f; if (val == 0x0f) rv = 0; else if (val == 0x00) rv = 0; else printerr("Malformed begin broadcast IP: %s\n", _startIP); } else rv = 0; } else { printerr("Invalid begin IP: %s\n", _startIP); } if (rv) return(rv); rv = inet_aton(_endIP, &_endAddr); if (rv ) { _endAddr.s_addr = ntohl(_endAddr.s_addr); if (fdebug) show_ip(_endAddr.s_addr); pb = (unsigned char*)&_endAddr.s_addr; if (!fBroadcastOk && (pb[0] < 1) ) printerr("Malformed end IP: %s\n", _endIP); else if (!fBroadcastOk && (pb[0] >254) ) printerr("Malformed end IP: %s\n", _endIP); else rv = 0; } else { printerr("Invalid end IP: %s\n", _endIP); } /* calculate g_num_packets */ g_num_packets = ntoi(_endAddr.s_addr) - ntoi(_startAddr.s_addr) + 1; if (fdebug) printerr("g_num_packets = %d\n",g_num_packets); if (g_num_packets < 1) g_num_packets = 0; return(rv); } /*end sock_init*/ void *receiveThread(void *p) { uchar buffer[IPMI_PING_MAX_LEN]; struct timeval tv; fd_set rset; int rv, len; static int needlf = 0; char host[200]; SockType sockrecv; int nothers = 0; int addr_type = AF_INET; /*or AF_INET6*/ #ifndef WIN32 struct hostent *h_ent = NULL; char serv[200]; int r; #endif sockrecv = g_sockfd; if (fraw) { /* opening SOCK_RAW requires admin/root privilege. */ if ((g_sockraw = socket(RAW_DOMAIN, SOCK_RAW,RAW_PROTO)) == SockInvalid) { printerr("raw socket: %s\n", showlasterr()); fraw = 0; } else { sockrecv = g_sockraw; if (fdebug) printf("g_sockraw = %d\n",g_sockraw); } } /* receive while loop */ do { tv.tv_sec = g_wait; tv.tv_usec = 0; FD_ZERO(&rset); FD_SET(sockrecv, &rset); g_recv_status = 0; if (fdebug) printerr("waiting for ping %d response\n",g_npings); if ((rv = select((int)(sockrecv+1), &rset, NULL, NULL, &tv)) < 0) { printerr("select: %s\n", showlasterr()); cleanup(); exit(rv); // error, exit idiscover recv thread } if (fdebug) printerr("select rv = %d\n",rv); if (rv > 0) { struct sockaddr_in from; socklen_t fromlen; char rstr[40]; char macstr[20]; struct in_addr from_ip; char estr[40]; if (needlf) { printf("\n"); needlf = 0; } g_recv_status = 1; fromlen = sizeof(from); len = ipmilan_recvfrom(sockrecv, buffer, IPMI_PING_MAX_LEN, 0, (struct sockaddr *)&from, &fromlen); if (fdebug) printerr("recvfrom rv = %d\n",rv); if (len < 0) { printerr("ipmilan_recvfrom: %s\n", showlasterr()); continue; } if (fdebug) { /* can we get the MAC addr of the responder also? */ // dump_buf("from_addr",(uchar *)&from,fromlen,0); dump_buf("recvfrom",buffer,len,0); } g_recv_status = 2; g_npongs++; macstr[0] = 0; if (fraw) { /* Raw packet, include MAC address string */ /* * Sample raw packet for UDP ping response * dst_mac src_mac eth_p iphdr * 0000: 00 07 e9 06 15 31 00 0e 0c 2b b5 81 08 00 45 00 * udp src_ip dst_ip * 0010: 00 38 00 00 40 00 40 11 b6 01 c0 a8 01 c2 c0 a8 * rmcp * 0020: 01 a1 02 6f 80 1e 00 24 0e d1 06 00 ff 06 00 00 * 0030: 11 be */ if ((buffer[23] != 0x11) || (buffer[42] != 0x06)) { /* [23]: 0x11==UDP, 0x06==TCP ; [42]: 0x06 ==RMCP */ if (nothers > g_limit) { if (fdebug) printf("got %d other packets, stop.\n",nothers); break; } nothers++; continue; } if (buffer[6] == 0xFF || buffer[26] == 0xFF) /*broadcast*/ continue; sprintf(macstr,"%02x:%02x:%02x:%02x:%02x:%02x %c", buffer[6], buffer[7], buffer[8], /*06=src_mac*/ buffer[9], buffer[10], buffer[11], bdelim); memcpy(&from_ip,&buffer[26],4); /*26=src_ip*/ } else { memcpy(&from_ip,&from.sin_addr,4); } host[0] = 0; #ifndef WIN32 /* Linux, BSD, Solaris, MacOS */ #if !defined(CROSS_COMPILE) h_ent = gethostbyaddr((void *)&from_ip,4,addr_type); if (h_ent != NULL) { strncpy(host,h_ent->h_name,sizeof(host)); } else if (!fraw) #endif { r = getnameinfo((struct sockaddr *)&from, fromlen, host, sizeof(host), serv, sizeof(serv), 0); if (r) host[0] = 0; else if (host[0] >= '0' && host[0] <= '9') host[0] = 0; } #endif // parse the received pong rstr[0] = 0; if (fping == 0 && len > 0) { /* -g and got rsp data */ /* parse GetChanAuthcap response into rstr */ /* 4 bytes RMCP, 10 bytes IPMI session, then msg */ /* 6 bytes msg hdr, then rsp data */ /* 20 = ccode, 21 = chan, 22 = auth type support */ if (buffer[20] != 0) /*ccode error*/ sprintf(rstr,"%c (ccode=0x%02x)",bdelim,buffer[20]); else /*ccode is ok*/ sprintf(rstr,"%c (channel %d)",bdelim,buffer[21]); } if (fcanonical) { estr[0] = 0; rstr[0] = 0; } else { sprintf(estr,"response from %c ",bdelim); } /* &buffer[0] = source MAC, &buffer[6] = destination MAC */ printf("%.2d%c %s%s %s \t%c %s %s\n", g_npongs,bdelim,estr,macstr,inet_ntoa(from_ip), bdelim,host,rstr); } else { /*ping, no answer*/ if (!fBroadcastOk) { printf("."); fflush(stdout); /*show progress*/ needlf = 1; } } } #ifdef NO_THREADS while(fBroadcastOk && rv > 0); #else while(1); #endif return(p); } /* * send_ping_pkt: * RMCP Ping buffer, sent as a UDP packet to port 0x026f. * rmcp.ver = 0x06 // RMCP Version 1.0 * rmcp.resvd = 0x00 // RESERVED * rmcp.seq = 0xff // no RMCP ACK * rmcp.class = 0x06 // RMCP_CLASS_ASF * asf.iana = 0x000011BE // ASF_RMCP_IANA (hi-lo) * asf.type = 0x80 // ASF_TYPE_PING * asf.tag = 0x00 // ASF sequence number * asf.resvd = 0x00 // RESERVED * asf.len = 0x00 */ int send_ping_pkt(struct sockaddr_in *_daddr, uchar seq) { uchar pingbuf[SZ_PING] = {06,0,0xFF,06,0x00,0x00,0x11,0xBE,0x80,0,0,0 }; int rv, len; pingbuf[9] = seq; len = sizeof(pingbuf); if (fdebug) dump_buf("send_ping",pingbuf,len,0); rv = ipmilan_sendto(g_sockfd, pingbuf, len, 0, (struct sockaddr *)_daddr, sizeof(struct sockaddr_in)); return(rv); } static int send_poke1(struct sockaddr_in *_daddr) { int rv; uchar asfpkt[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x20, 0x18, 0xc8, 0xc2, 0x01, 0x01, 0x3c }; if (fdebug) dump_buf("send_poke1",asfpkt,16,0); rv = ipmilan_sendto(g_sockfd, asfpkt, 16, 0, (struct sockaddr *)_daddr, sizeof(struct sockaddr_in)); return rv; } static uchar cksum(const uchar *buf, register int len) { register uchar csum; register int i; /* 8-bit 2s compliment checksum */ csum = 0; for (i = 0; i < len; i++) csum = (csum + buf[i]) % 256; csum = -csum; return(csum); } static int send_getauth(struct sockaddr_in *_daddr, uchar seq) { int rv, len; // static uchar swseq = 0; uchar getauthpkt[23] = { 0x06, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x20, 0x18, 0xc8, 0x81, 0x04, 0x38, 0x0e, 0x04, 0x31 }; /* * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 * 06 00 ff 07 00 00 00 00 00 00 00 00 00 09 20 18 c8 81 04 38 0e 04 31 * [RMCP hdr ] [IPMI session hdr (len)] [IPMI msg ] [data] */ // getauthpkt[8] = 0x00; /* seq always 00 for GetChanAuthCap */ getauthpkt[21] = 0x02; /*requested priv_level: 2=user, 4=admin*/ getauthpkt[22] = cksum(&getauthpkt[17],5); len = sizeof(getauthpkt); if (fdebug) dump_buf("send_getauth",getauthpkt,len,0); rv = ipmilan_sendto(g_sockfd, getauthpkt, len, 0, (struct sockaddr *)_daddr, sizeof(struct sockaddr_in)); if (fdebug) printf("send_getauth: rv = %d\n",rv); return rv; } int send_probe(struct sockaddr_in *_daddr, uchar seq) { int rv; if (fBroadcastOk) { rv = setsockopt(g_sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast_pings, sizeof(broadcast_pings)); if (fdebug) { char *estr; if (rv) estr = showlasterr(); else estr = ""; printerr("setsockopt(broadcast): rv=%d %s\n", rv,estr); } } if (fping) rv = send_ping_pkt( _daddr, seq); else rv = send_getauth( _daddr, seq); return(rv); } void *sendThread(void *p) { int i, j, n; // char _dest[MAXHOSTNAMELEN+1]; char _dest_ip[INET_ADDRSTRLEN+1]; struct sockaddr_in _destaddr; uchar o[4]; uint ip; uchar _seq; int rv; n = g_num_packets; /*num*/ ip = _startAddr.s_addr; for (i = 0; i < n; i++) { split_ip(ip,o); if (o[3] == 0) continue; if (!fBroadcastOk && (o[3] == 255)) continue; sprintf(_dest_ip,"%d.%d.%d.%d",o[0],o[1],o[2],o[3]); /* set _destaddr */ _destaddr.sin_family = AF_INET; _destaddr.sin_port = htons(g_port); if ( !inet_aton( _dest_ip, &_destaddr.sin_addr)) { printerr("inet_aton error %s\n",_dest_ip); continue; } for (j=0; j= 0) { receiveThread(NULL); } } #endif /* sleep an interval (g_delay usec) */ if (g_delay > 0) os_sleep(0,g_delay); } /*end-for g_repeat*/ ip++; /* increment to next IP */ } return(p); } #ifdef METACOMMAND int i_discover(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int rv = 0; int c; #ifndef NO_THREADS char message[32]; pthread_t thread[2]; int iret[2]; #endif #ifdef METACOMMAND fpdbg = stdout; #endif printf("%s ver %s\n", progname,progver); while ( (c = getopt( argc, argv,"ab:ce:gi:l:mp:r:s:x?")) != EOF ) switch(c) { case 'a': fBroadcastOk = 1; fping = 1; break; /*all (broadcast ping)*/ case 'c': /*canonical, CSV*/ fcanonical = 1; bdelim = BCOMMA; break; case 'm': /* show MAC address, use raw, requires root priv */ fBroadcastOk = 1; fping = 1; fraw = 1; break; /*all (broadcast ping)*/ case 'l': g_limit = atoi(optarg); break; case 'g': fping = 0; break; /*use get chan auth cap method */ case 'b': /*begin*/ strncpy(g_startDest,optarg,MAXHOSTNAMELEN); break; case 'e': /*end*/ strncpy(g_endDest,optarg,MAXHOSTNAMELEN); break; case 'i': /*interface*/ strncpy(g_interface,optarg,sizeof(g_interface)); break; case 'p': /*port/socket*/ g_port = (ushort)atoi(optarg); break; case 'r': /*repeat N times*/ g_repeat = atoi(optarg); break; case 's': /*subnet*/ /* copy optarg from 10.243.42.0 or similar, to * begin/end range. */ break; case 'x': fdebug = 1; break; /* debug messages */ default: if (fdebug) printerr("getopt(%c) default\n",c); show_usage(); rv = ERR_USAGE; goto do_exit; } #ifdef WIN32 /* Winsock inet_aton() does not like 255.255.255.255 */ if (!fBroadcastOk && (g_startDest[0] == 0) ) { show_usage(); printerr("A beginning IP is required, using -b\n"); goto do_exit; } #else if (g_startDest[0] == 0) { strcpy(g_startDest,"255.255.255.255"); /* INADDR_BROADCAST */ fBroadcastOk = 1; } #endif if (fraw == 1) { if (frawok == 0) { printf("Warning: SOCK_RAW not yet implemented on this OS\n"); } #ifdef LINUX else { c = geteuid(); if (c > 1) printf("Must be root/superuser to use SOCK_RAW\n"); } #endif } if (g_endDest[0] == 0 || fBroadcastOk) strcpy(g_endDest,g_startDest); /*only one IP address*/ if (fdebug) printerr("intf=%s begin=%s end=%s port=%d\n", g_interface,g_startDest,g_endDest,g_port); rv = sock_init(g_interface, g_startDest, g_endDest); if (fdebug) printerr("sock_init rv = %d, sockfd = %d\n",rv,g_sockfd); if (rv != 0) { show_usage(); printerr("sock_init error %d\n",rv); goto do_exit; } printf("Discovering IPMI Devices:\n"); #ifdef NO_THREADS sendThread(NULL); #else iret[1] = pthread_create( &thread[1], NULL, receiveThread, (void*) message); iret[0] = pthread_create( &thread[0], NULL, sendThread, (void*) message); pthread_join( thread[0], NULL); pthread_join( thread[1], NULL); #endif // if (fdebug) printf("\n%s: %d pings sent, %d responses\n",progname,g_npings,g_npongs); do_exit: cleanup(); return(rv); } /* end main()*/ /* end idiscover.c */ ipmiutil-3.1.5/util/oem_fujitsu.c0000644000076400007640000006635713566765324017151 0ustar mgportalloggers/* * oem_fujitsu.c * * This module handles OEM-specific functions for Fujitsu-Siemens firmware. * * References: * http://manuals.ts.fujitsu.com/file/4390/irmc_s2-ug-en.pdf * * Authors: Andy Cress arcress at users.sourceforge.net, and * Dan Lukes dan at obluda.cz * * Copyright (c) 2010 Kontron America, Inc. * * 08/17/10 Andy Cress v1.0 new, with source input from Dan Lukes */ /*M* Copyright (c) 2010 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 Kontron 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*/ #ifdef WIN32 #include #endif #include #include #include #include "ipmicmd.h" #include "ievents.h" #include "oem_fujitsu.h" /* extern void get_mfgid(int *vend, int *prod); * from ipmicmd.h*/ /* extern int get_lan_options(); * from ipmicmd.h */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil fujitsuoem"; #else static char * progver = "3.08"; static char * progname = "ifujitsuoem"; #endif static char fdebug = 0; static char freadok = 1; #define ERRLED 0 /*GEL - red Global Error LED*/ #define WARNLED 1 /*CSS - yellow warning LED*/ #define IDLED 2 /*ID - blue Identify LED*/ #define NETFN_FUJITSU_IRMCS2 0xB8 #define CMD_FUJITSU_IRMCS2 0xF5 #define CMD_SPEC_FUJITSU_SET_ID_LED 0xB0 #define CMD_SPEC_FUJITSU_GET_ID_LED 0xB1 #define CMD_SPEC_FUJITSU_GET_ERR_LED 0xB3 #define LED_OFF 0 #define LED_ON 1 #define LED_BLINK 2 /* * get_alarmss_fujitsu * returns an array of 3 bytes: * offset 0 = ID blue LED state (0=off, 1=on, 2=blink) * offset 1 = CSS yellow LED state (0=off, 1=on, 2=blink) * offset 2 = GEL red LED state (0=off, 1=on, 2=blink) */ int get_alarms_fujitsu(uchar *rgalarms ) { int rv = -1; uchar idata[16]; uchar rdata[16]; int rlen; ushort icmd; uchar cc; int vend_id, prod_id; if (rgalarms == NULL) return(ERR_BAD_PARAM); memset(rgalarms,0,3); /* check if iRMC s2 */ get_mfgid(&vend_id,&prod_id); if (vend_id != VENDOR_FUJITSU) return(LAN_ERR_NOTSUPPORT); if (FUJITSU_PRODUCT_IS_iRMC_S1(prod_id)) return(LAN_ERR_NOTSUPPORT); /* get error, warning, id led statuses */ icmd = CMD_FUJITSU_IRMCS2 | (IPMI_NET_FN_OEM_GROUP_RQ << 8); idata[0] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0x0000FF); idata[1] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0x00FF00) >> 8; idata[2] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0xFF0000) >> 16; idata[3] = CMD_SPEC_FUJITSU_GET_ID_LED; rlen = sizeof(rdata); rv = ipmi_cmd_mc(icmd, idata, 4, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; if (rv != 0) return(rv); rgalarms[0] = (rdata[3] & 0x03); /*id led, after the IANA response */ icmd = CMD_FUJITSU_IRMCS2 | (IPMI_NET_FN_OEM_GROUP_RQ << 8); idata[0] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0x0000FF); idata[1] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0x00FF00) >> 8; idata[2] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0xFF0000) >> 16; idata[3] = CMD_SPEC_FUJITSU_GET_ERR_LED; rlen = sizeof(rdata); rv = ipmi_cmd_mc(icmd, idata, 4, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; switch(rdata[3]) { case 1: rgalarms[1] = LED_OFF; rgalarms[2] = LED_ON; break; case 2: rgalarms[1] = LED_OFF; rgalarms[2] = LED_BLINK; break; case 3: rgalarms[1] = LED_ON; rgalarms[2] = LED_OFF; break; case 4: rgalarms[1] = LED_ON; rgalarms[2] = LED_ON; break; case 5: rgalarms[1] = LED_ON; rgalarms[2] = LED_BLINK; break; case 6: rgalarms[1] = LED_BLINK; rgalarms[2] = LED_OFF; break; case 7: rgalarms[1] = LED_BLINK; rgalarms[2] = LED_ON; break; case 8: rgalarms[1] = LED_BLINK; rgalarms[2] = LED_BLINK; break; case 0: default: rgalarms[1] = LED_OFF; rgalarms[2] = LED_OFF; break; } return(rv); } static char *led_str(uchar b) { char *pstr; switch(b) { case LED_ON: pstr = "ON"; break; case LED_BLINK: pstr = "Blink"; break; case LED_OFF: default: pstr = "off"; break; } return(pstr); } /* * show_alarms_fujitsu * offset 0 = ID blue LED state (0=off, 1=on, 2=blink) * offset 1 = CSS yellow LED state (0=off, 1=on, 2=blink) * offset 2 = GEL red LED state (0=off, 1=on, 2=blink) */ int show_alarms_fujitsu(uchar *rgalarms) { if (rgalarms == NULL) return(ERR_BAD_PARAM); /* show error, warning, id led statuses */ printf("iRMC S2 ID LED (blue) = %s\n",led_str(rgalarms[0])); printf("iRMC S2 CSS LED (yellow) = %s\n",led_str(rgalarms[1])); printf("iRMC S2 GEL LED (red) = %s\n",led_str(rgalarms[2])); return(0); } /* * set_alarms_fujitsu * num: only the ID LED can be set, so num==0 * val: 0=LED_OFF, 1=LED_ON */ int set_alarms_fujitsu(uchar num, uchar val) { int rv = -1; uchar idata[16]; uchar rdata[16]; int rlen; ushort icmd; uchar cc; int vend_id, prod_id; get_mfgid(&vend_id,&prod_id); if (vend_id != VENDOR_FUJITSU) return(LAN_ERR_NOTSUPPORT); if (FUJITSU_PRODUCT_IS_iRMC_S1(prod_id)) return(LAN_ERR_NOTSUPPORT); /* set the specified LED number to val */ icmd = CMD_FUJITSU_IRMCS2 | (IPMI_NET_FN_OEM_GROUP_RQ << 8); idata[0] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0x0000FF); idata[1] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0x00FF00) >> 8; idata[2] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0xFF0000) >> 16; idata[3] = CMD_SPEC_FUJITSU_SET_ID_LED; if (val == 0xFF) idata[4] = LED_ON; else if (val == 0) idata[4] = LED_OFF; else idata[4] = LED_BLINK; rlen = sizeof(rdata); rv = ipmi_cmd_mc(icmd, idata, 5, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; return(rv); } /* * read_sel_fujitsu * * Fujitsu OEM * http://manuals.ts.fujitsu.com/file/4390/irmc_s2-ug-en.pdf * * Request * 0x2E - OEM network function * 0xF5 - OEM cmd * 0x?? - Fujitsu IANA (LSB first) * 0x?? - Fujitsu IANA * 0x?? - Fujitsu IANA * 0x43 - Command Specifier * 0x?? - Record ID (LSB first) * 0x?? - Record ID ; 0x0000 = "first record", 0xFFFF = "last record" * 0x?? - Offset (in response SEL text) * 0x?? - MaxResponseDataSize (size of converted SEL data 16:n in response, * maximum is 100, some only handle 64) * * Response * 0xF5 - OEM cmd * 0x?? - Completion code * 0 0x?? - Fujitsu IANA (LSB first) * 1 0x?? - Fujitsu IANA * 2 0x?? - Fujitsu IANA * 3 0x?? - Next Record ID (LSB) * 4 0x?? - Next Record ID (MSB) * 5 0x?? - Actual Record ID (LSB) * 6 0x?? - Actual Record ID (MSB) * 7 0x?? - Record type * 8 0x?? - timestamp (LSB first) * 9 0x?? - timestamp * 10 0x?? - timestamp * 11 0x?? - timestamp * 12 0x?? - severity * bit 7 - CSS component * bit 6-4 - 000 = INFORMATIONAL * 001 = MINOR * 010 = MAJOR * 011 = CRITICAL * 1xx = unknown * bit 3-0 - reserved * 13 0x?? - data length (of the whole text) * 14 0x?? - converted SEL data * requested number of bytes starting at requested offset * (MaxResponseDataSize-1 bytes of data) ..... * 0x00 - trailing '\0' character */ int read_sel_fujitsu(uint16_t id, char *buf, int sz, char fdbg) { int rv = -1; uint8_t bytes_rq[IPMI_OEM_MAX_BYTES]; uint8_t bytes_rs[IPMI_OEM_MAX_BYTES]; char textbuf[IPMI_OEM_MAX_BYTES]; int rs_len, text_len, data_len, chunk_len; int max_read_length; uint16_t actual_record_id = id; uint32_t timestamp = 0; // uint16_t next_record_id; // uint8_t record_type; uint8_t severity = 0; uint8_t ccode; char timestr[40]; char *severity_text = NULL; uint8_t offset = 0; int vend_id, prod_id; fdebug = fdbg; if (buf == NULL) return(rv); max_read_length = IPMI_OEM_MAX_BYTES; data_len = IPMI_OEM_MAX_BYTES; /* This command requires admin privilege, so check and print a warning if Fujitsu and not admin. */ get_mfgid(&vend_id,&prod_id); if (vend_id == VENDOR_FUJITSU) { /* connected to Fujitsu MC */ int auth, priv; if (FUJITSU_PRODUCT_IS_iRMC_S1(prod_id)) { max_read_length = 32; data_len = 80; } rv = get_lan_options(NULL,NULL,NULL,&auth,&priv,NULL,NULL,NULL); if ((rv == 0) && (priv < 4)) { /*remote and not admin priv*/ printf("*** Admin privilege (-V 4) required for full OEM decoding.\n"); } } memset(textbuf,0,sizeof(textbuf)); bytes_rq[0] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0x0000FF); bytes_rq[1] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0x00FF00) >> 8; bytes_rq[2] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0xFF0000) >> 16; bytes_rq[3] = IPMI_OEM_FUJITSU_COMMAND_SPECIFIER_GET_SEL_ENTRY_LONG_TEXT; bytes_rq[4] = (id & 0x00FF); bytes_rq[5] = (id & 0xFF00) >> 8; bytes_rq[7] = (uchar)max_read_length; while (offset < data_len) { bytes_rq[6] = offset; /* Do not ask BMC for data beyond data_len, request partial if so. */ if (offset + max_read_length > data_len) bytes_rq[7] = data_len - offset; rs_len = sizeof(bytes_rs); rv = ipmi_cmdraw(IPMI_CMD_OEM_FUJITSU_SYSTEM, IPMI_NET_FN_OEM_GROUP_RQ, BMC_SA, PUBLIC_BUS, BMC_LUN, bytes_rq, 9, bytes_rs, &rs_len, &ccode, fdebug); if (fdebug) printf("read_sel_fujitsu rv = %d, cc = %x\n", rv, ccode); if (rv == 0 && ccode != 0) rv = ccode; if (rv != 0) return(rv); if (fdebug) dump_buf("read_sel_fujitsu data",bytes_rs,rs_len,1); if (offset == 0) { /* only need to set these on the first pass */ actual_record_id = bytes_rs[5] + (bytes_rs[6] << 8); timestamp = bytes_rs[8] + (bytes_rs[9] << 8) + (bytes_rs[10] << 16) + (bytes_rs[11] << 24); severity = (bytes_rs[12] >> 3); data_len = bytes_rs[13]; if (data_len > IPMI_OEM_MAX_BYTES) data_len = IPMI_OEM_MAX_BYTES; } chunk_len = rs_len - 14; if ((offset + chunk_len) > IPMI_OEM_MAX_BYTES) chunk_len = IPMI_OEM_MAX_BYTES - offset; memcpy(&textbuf[offset],&bytes_rs[14],chunk_len); offset += (uint8_t)chunk_len; } textbuf[IPMI_OEM_MAX_BYTES-1]='\0'; /*stringify*/ text_len = strlen_(textbuf); switch (severity) { case 0: severity_text = "INFORMATIONAL:"; break; case 1: severity_text = "MINOR:"; break; case 2: severity_text = "MAJOR:"; break; case 3: severity_text = "CRITICAL:"; break; case 4: case 5: case 6: case 7: severity_text = ""; break; case 8: severity_text = "INFORMATIONAL/CSS:"; break; case 9: severity_text = "MINOR/CSS:"; break; case 10: severity_text = "MAJOR/CSS:"; break; case 11: severity_text = "CRITICAL/CSS:"; break; case 12: case 13: case 14: case 15: severity_text = "unknown/CSS:"; break; } fmt_time(timestamp, timestr, sizeof(timestr)); snprintf(buf, sz, "%u | %s | %s %s\n", (int)actual_record_id, timestr, severity_text, textbuf); return rv; } /* * decode_sel_fujitsu * inputs: * evt = the 16-byte IPMI SEL event * outbuf = points to the output string buffer * outsz = size of the output buffer * outputs: * rv = 0 if this event was successfully interpreted here, * non-zero otherwise, to use default interpretations. * outbuf = will contain the interpreted event text string (if rv==0) */ int decode_sel_fujitsu(uint8_t *evt, char *outbuf, int outsz, char fdesc, char fdbg) { int rv = -1; uint16_t id; uint8_t rectype; int oemid; uint32_t timestamp; char mybuf[64]; char *type_str = NULL; char *gstr = NULL; char *pstr = NULL; ushort genid; int sevid; fdebug = fdbg; id = evt[0] + (evt[1] << 8); if (freadok) { rv = read_sel_fujitsu(id, outbuf, outsz, fdbg); if (rv == 0) return(rv); /*success, done*/ } freadok = 0; /*not fujitsu or not local, so do not retry */ sevid = SEV_INFO; /* instead try to decode some events manually */ rectype = evt[2]; timestamp = evt[3] + (evt[4] << 8) + (evt[5] << 16) + (evt[6] << 24); genid = evt[7] | (evt[8] << 8); if (rectype == 0xc1) { /* OEM type C1 */ oemid = evt[7] + (evt[8] << 8) + (evt[9] << 16); if (oemid == VENDOR_FUJITSU) { type_str = "Fujitsu"; gstr = "BMC "; switch(evt[10]) { case 0x09: sprintf(mybuf,"iRMC S2 CLI/Telnet user %d login from %d.%d.%d.%d", evt[11], evt[12], evt[13], evt[14], evt[15]); break; case 0x0a: sprintf(mybuf,"iRMC S2 CLI/Telnet user %d logout from %d.%d.%d.%d", evt[11], evt[12], evt[13], evt[14], evt[15]); break; default: sprintf(mybuf,"iRMC S2 Event %02x %02x %02x %02x %02x %02x", evt[10], evt[11], evt[12], evt[13], evt[14], evt[15]); break; } format_event(id,timestamp, sevid, genid, type_str, evt[10],NULL,mybuf,NULL,outbuf,outsz); rv = 0; } /*endif fujitsu oem */ } else if (rectype == 0x02) { type_str = "iRMC S2"; gstr = "BMC "; sprintf(mybuf,"%02x [%02x %02x %02x]", evt[12],evt[13],evt[14],evt[15]); switch(evt[10]) { /*sensor type*/ case 0xc8: switch(evt[13]) { case 0x29: sprintf(mybuf,"CLI/Telnet user %d login", evt[15]); break; case 0x2a: sprintf(mybuf,"CLI/Telnet user %d logout", evt[15]); break; case 0x21: sprintf(mybuf,"Browser user %d login", evt[15]); break; case 0x22: sprintf(mybuf,"Browser user %d logout", evt[15]); break; case 0x23: sprintf(mybuf,"Browser user %d auto-logout", evt[15]); break; default: /*mybuf has the raw bytes*/ break; } pstr = mybuf; rv = 0; break; case 0xca: if (evt[13] == 0x26) pstr = "Paging: Email - notification failed"; else if (evt[13] == 0xa6) pstr = "Paging: Email - DNS failed"; else pstr = mybuf; rv = 0; break; case 0xe1: sevid = SEV_MAJ; if (evt[13] == 0x0f) pstr = "MC access degraded"; else pstr = mybuf; rv = 0; break; case 0xec: if (evt[13] == 0xa0) { sprintf(mybuf,"Firmware flash version %d.%d", (evt[14] & 0x0f),evt[15]); } pstr = mybuf; rv = 0; break; case 0xee: type_str = "iRMC S2"; if (evt[12] == 0x0a && evt[13] == 0x80) pstr = "Automatic restart after power fail"; else pstr = mybuf; rv = 0; break; default: break; } if (rv == 0) { format_event(id,timestamp, sevid, genid, type_str, evt[11],NULL,pstr,NULL,outbuf,outsz); /*evt[11] = sensor number */ } } return rv; } /* * Fujitsu iRMC S1 / iRMC S2 OEM Sensor logic */ /* 0xDD */ const char * const ipmi_sensor_type_oem_fujitsu_system_power_consumption[] = { /* EN 0x00 */ "System Power Consumption within Limit", /* EN 0x01 */ "System Power Consumption above Warning Level", /* EN 0x02 */ "System Power Consumption above Critical Level", /* EN 0x03 */ "System Power Consumption limiting disabled", NULL }; unsigned int ipmi_sensor_type_oem_fujitsu_system_power_consumption_max_index = 0x03; /* 0xDE */ const char * const ipmi_sensor_type_oem_fujitsu_memory_status[] = { /* EN 0x00 */ "Empty slot", /* EN 0x01 */ "OK", /* EN 0x02 */ "Reserved", /* EN 0x03 */ "Error", /* EN 0x04 */ "Fail", /* EN 0x05 */ "Prefailure", /* EN 0x06 */ "Reserved", /* EN 0x07 */ "Unknown", NULL }; unsigned int ipmi_sensor_type_oem_fujitsu_memory_status_max_index = 0x07; /* 0xDF */ const char * const ipmi_sensor_type_oem_fujitsu_memory_config[] = { /* EN 0x00 */ "Normal", /* EN 0x01 */ "Disabled", /* EN 0x02 */ "Spare module", /* EN 0x03 */ "Mirrored module", /* EN 0x04 */ "RAID module", /* EN 0x05 */ "Not Usable", /* EN 0x06 */ "Unspecified state(6)", /* EN 0x07 */ "Unspecified state(7)", NULL }; unsigned int ipmi_sensor_type_oem_fujitsu_memory_config_max_index = 0x07; /* 0xE1 */ const char * const ipmi_sensor_type_oem_fujitsu_memory[] = { /* EN 0x00 */ "Non Fujitsu memory module detected", /* EN 0x01 */ "Memory module replaced", /* EN 0x02 */ "Fatal general memory error", /* EN 0x03 */ "Recoverable general memory error", /* EN 0x04 */ "Recoverable ECC memory error", /* EN 0x05 */ "Recoverable CRC memory error", /* EN 0x06 */ "Fatal CRC memory error", /* EN 0x07 */ "Recoverable thermal memory event", /* EN 0x08 */ "Fatal thermal memory error", /* EN 0x09 */ "Too many correctable memory errors", /* EN 0x0A */ "Uncorrectable Parity memory error", /* EN 0x0B */ "Memory Modules swapped", /* EN 0x0C */ "Memory Module moved", /* EN 0x0D */ "Memory removed", /* EN 0x0E */ "Memory Re-inserted", /* EN 0x0F */ "Memory module(s) changed", NULL }; unsigned int ipmi_sensor_type_oem_fujitsu_memory_max_index = 0x0F; /* 0xE3 */ const char * const ipmi_sensor_type_oem_fujitsu_hw_error[] = { /* EN 0x00 */ "TPM Error", /* EN 0x01 */ "Reserved", /* EN 0x02 */ "No usable CPU", NULL }; unsigned int ipmi_sensor_type_oem_fujitsu_hw_error_max_index = 0x02; /* 0xE4 */ const char * const ipmi_sensor_type_oem_fujitsu_sys_error[] = { /* EN 0x00 */ "System configuration Data error", /* EN 0x01 */ "Resource Conflict", /* Slot in EventData3 */ /* EN 0x02 */ "IRQ not configured", /* Slot in EventData3 */ /* EN 0x03 */ "Device node allocation error", /* Device in EventData3 */ /* EN 0x04 */ "Expansion ROM Slot not initialized", /* Slot in EventData3 */ NULL }; unsigned int ipmi_sensor_type_oem_fujitsu_sys_error_max_index = 0x04; /* 0xE6 */ const char * const ipmi_sensor_type_oem_fujitsu_fan_status[] = { /* EN 0x00 */ "FAN on, running", /* EN 0x01 */ "FAN failed", /* EN 0x02 */ "FAN prefailure", /* EN 0x03 */ "Redundant FAN failed", /* EN 0x04 */ "FAN not manageable", /* EN 0x05 */ "FAN not installed", /* EN 0x06 */ "FAN unspecified state(6)", /* EN 0x07 */ "FAN in init phase", NULL }; unsigned int ipmi_sensor_type_oem_fujitsu_fan_status_max_index = 0x07; /* 0xE8 */ const char * const ipmi_sensor_type_oem_fujitsu_psu_status[] = { /* EN 0x00 */ "Power supply - Not present", /* EN 0x01 */ "Power supply - OK", /* EN 0x02 */ "Power supply - Failed", /* EN 0x03 */ "Redundant power supply - AC failed", /* EN 0x04 */ "Redundant power supply - DC failed", /* EN 0x05 */ "Power supply - Critical Temperature", /* EN 0x06 */ "Power supply - Not manageable", /* EN 0x07 */ "Power supply - Fan failure predicted", /* EN 0x08 */ "Power supply - Fan failed", /* EN 0x09 */ "Power supply - Power Save Mode", NULL }; unsigned int ipmi_sensor_type_oem_fujitsu_psu_status_max_index = 0x09; /* 0xE9 */ const char * const ipmi_sensor_type_oem_fujitsu_psu_redundancy[] = { /* EN 0x00 */ "Power Supply - redundancy present", NULL }; unsigned int ipmi_sensor_type_oem_fujitsu_psu_redundancy_max_index = 0x00; /* 0xEC */ const char * const ipmi_sensor_type_oem_fujitsu_flash[] = { /* EN 0x00 */ "Online firmware flash", /* EN 0x01 */ "Online firmware flash: reboot", /* EN 0x02 */ "BIOS TFTP Flash: OK", /* EN 0x03 */ "BIOS TFTP Flash: failed", /* EN 0x04 */ "iRMC TFTP Flash: OK", /* EN 0x05 */ "iRMC TFTP Flash: failed", NULL }; unsigned int ipmi_sensor_type_oem_fujitsu_flash_max_index = 0x05; /* 0xEF */ const char * const ipmi_sensor_type_oem_fujitsu_config_backup[] = { /* EN 0x00 */ "Chassis IDPROM: Motherboard Exchange detected", /* EN 0x01 */ "Chassis IDPROM: Read or Write error", /* EN 0x02 */ "Chassis IDPROM: Restore successful", /* EN 0x03 */ "Chassis IDPROM: Restore failed", /* EN 0x04 */ "Chassis IDPROM: Backup successful", /* EN 0x05 */ "Chassis IDPROM: Backup failed", /* EN 0x06 */ "Chassis IDPROM: Feature disabled", /* EN 0x07 */ "Chassis IDPROM: Function Not Available", /* EN 0x08 */ "Reserved", /* EN 0x09 */ "Reserved", /* EN 0x0A */ "Reserved", /* EN 0x0B */ "Reserved", /* EN 0x0C */ "Reserved", /* EN 0x0D */ "Reserved", /* EN 0x0E */ "Reserved", /* EN 0x0F */ "NVRAM defaults loaded", NULL }; unsigned int ipmi_sensor_type_oem_fujitsu_config_backup_max_index = 0x0F; /* 0xEF */ const char * const ipmi_sensor_type_oem_fujitsu_i2c_bus[] = { /* EN 0x00 */ "I2C Bus Error", /* EN 0x01 */ "I2C Bus OK", /* EN 0x02 */ "I2C Bus Disabled", /* EN 0x03 */ "I2C Bus Failed", NULL }; unsigned int ipmi_sensor_type_oem_fujitsu_i2c_bus_max_index = 0x03; static char * get_array_message (unsigned int offset, unsigned int offset_max, const char * const string_array[]) { if (offset > offset_max) return("unknown"); return((char *)string_array[offset]); } static char *get_oem_reading_string(uchar sensor_type, uchar offset) { char * pstr = ""; /* * OEM Interpretation * Fujitsu iRMC S1 / iRMC S2 */ switch (sensor_type) { case IPMI_SENSOR_TYPE_OEM_FUJITSU_I2C_BUS: return (get_array_message (offset, ipmi_sensor_type_oem_fujitsu_i2c_bus_max_index, ipmi_sensor_type_oem_fujitsu_i2c_bus)); case IPMI_SENSOR_TYPE_OEM_FUJITSU_SYSTEM_POWER_CONSUMPTION: return (get_array_message (offset, ipmi_sensor_type_oem_fujitsu_system_power_consumption_max_index, ipmi_sensor_type_oem_fujitsu_system_power_consumption)); case IPMI_SENSOR_TYPE_OEM_FUJITSU_MEMORY_STATUS: return (get_array_message (offset, ipmi_sensor_type_oem_fujitsu_memory_status_max_index, ipmi_sensor_type_oem_fujitsu_memory_status)); case IPMI_SENSOR_TYPE_OEM_FUJITSU_MEMORY_CONFIG: return (get_array_message (offset, ipmi_sensor_type_oem_fujitsu_memory_config_max_index, ipmi_sensor_type_oem_fujitsu_memory_config)); case IPMI_SENSOR_TYPE_OEM_FUJITSU_MEMORY: return (get_array_message (offset, ipmi_sensor_type_oem_fujitsu_memory_max_index, ipmi_sensor_type_oem_fujitsu_memory)); case IPMI_SENSOR_TYPE_OEM_FUJITSU_HW_ERROR: return (get_array_message (offset, ipmi_sensor_type_oem_fujitsu_hw_error_max_index, ipmi_sensor_type_oem_fujitsu_hw_error)); case IPMI_SENSOR_TYPE_OEM_FUJITSU_SYS_ERROR: return (get_array_message (offset, ipmi_sensor_type_oem_fujitsu_sys_error_max_index, ipmi_sensor_type_oem_fujitsu_sys_error)); case IPMI_SENSOR_TYPE_OEM_FUJITSU_FAN_STATUS: return (get_array_message (offset, ipmi_sensor_type_oem_fujitsu_fan_status_max_index, ipmi_sensor_type_oem_fujitsu_fan_status)); case IPMI_SENSOR_TYPE_OEM_FUJITSU_PSU_STATUS: return (get_array_message (offset, ipmi_sensor_type_oem_fujitsu_psu_status_max_index, ipmi_sensor_type_oem_fujitsu_psu_status)); case IPMI_SENSOR_TYPE_OEM_FUJITSU_PSU_REDUNDANCY: return (get_array_message (offset, ipmi_sensor_type_oem_fujitsu_psu_redundancy_max_index, ipmi_sensor_type_oem_fujitsu_psu_redundancy)); case IPMI_SENSOR_TYPE_OEM_FUJITSU_FLASH: return (get_array_message (offset, ipmi_sensor_type_oem_fujitsu_flash_max_index, ipmi_sensor_type_oem_fujitsu_flash)); case IPMI_SENSOR_TYPE_OEM_FUJITSU_CONFIG_BACKUP: return (get_array_message (offset, ipmi_sensor_type_oem_fujitsu_config_backup_max_index, ipmi_sensor_type_oem_fujitsu_config_backup)); /* These are reserved */ case IPMI_SENSOR_TYPE_OEM_FUJITSU_COMMUNICATION: case IPMI_SENSOR_TYPE_OEM_FUJITSU_EVENT: default: break; } return(pstr); } static char *get_oem_sensor_type_string (uint8_t sensor_type) { switch (sensor_type) { case IPMI_SENSOR_TYPE_OEM_FUJITSU_I2C_BUS : return ("OEM I2C Bus"); case IPMI_SENSOR_TYPE_OEM_FUJITSU_SYSTEM_POWER_CONSUMPTION: return ("OEM Power Consumption"); case IPMI_SENSOR_TYPE_OEM_FUJITSU_MEMORY_STATUS : return ("OEM Memory Status"); case IPMI_SENSOR_TYPE_OEM_FUJITSU_MEMORY_CONFIG : return ("OEM Memory Config"); case IPMI_SENSOR_TYPE_OEM_FUJITSU_MEMORY : return ("OEM Memory"); case IPMI_SENSOR_TYPE_OEM_FUJITSU_FAN_STATUS : return ("OEM Fan Status"); case IPMI_SENSOR_TYPE_OEM_FUJITSU_PSU_STATUS : return ("OEM PSU Status"); case IPMI_SENSOR_TYPE_OEM_FUJITSU_PSU_REDUNDANCY: return ("OEM PSU Redundancy"); case IPMI_SENSOR_TYPE_OEM_FUJITSU_COMMUNICATION : return ("OEM Communication"); case IPMI_SENSOR_TYPE_OEM_FUJITSU_FLASH : return ("OEM Flash"); case IPMI_SENSOR_TYPE_OEM_FUJITSU_EVENT : return ("OEM Event"); case IPMI_SENSOR_TYPE_OEM_FUJITSU_CONFIG_BACKUP : return ("OEM Config Backup"); default : break; /* fall into generic case below */ } return (""); } int decode_sensor_fujitsu(uchar *sdr,uchar *reading,char *pstring, int slen) { int rv = -1; char *typestr = NULL; char *readstr = NULL; uchar stype; int vend_id, prod_id; /* Only get here if vend_id == VENDOR_FUJITSU */ if (sdr == NULL || reading == NULL) return(rv); if (pstring == NULL || slen == 0) return(rv); stype = sdr[12]; typestr = get_oem_sensor_type_string(stype); get_mfgid(&vend_id,&prod_id); if (vend_id == IPMI_IANA_ENTERPRISE_ID_FUJITSU && (prod_id >= IPMI_FUJITSU_PRODUCT_ID_MIN && prod_id <= IPMI_FUJITSU_PRODUCT_ID_MAX)) { readstr = get_oem_reading_string(stype,reading[2]); if (readstr != NULL && (readstr[0] != 0)) rv = 0; } else readstr = ""; snprintf (pstring, slen, "%s = %s",typestr,readstr); return(rv); } #ifdef METACOMMAND int i_fujitsuoem(int argc, char **argv) { printf("%s ver %s\n", progname,progver); return(0); } #endif /* end oem_fujitsu.c */ ipmiutil-3.1.5/util/idcmi.h0000644000076400007640000000522413566765324015674 0ustar mgportalloggers/* * idcmi.h * Data Center Manageability Interface (DCMI) command support * * Change history: * 11/17/2011 ARCress - created * *--------------------------------------------------------------------- */ /*M* Copyright (c) 2011 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 Kontron 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*/ #ifndef IPMI_DCMI_H #define IPMI_DCMI_H #define CC_DCMI_INVALID_COMMAND 0xC1 #define CC_DCMI_RECORD_NOT_PRESENT 0xCB #define NETFN_DCMI 0x2C /* for DCMI 1.0 and greater */ #define CMD_DCMI_GET_CAPAB 0x01 #define CMD_DCMI_GET_POWREAD 0x02 #define CMD_DCMI_GET_POWLIMIT 0x03 #define CMD_DCMI_SET_POWLIMIT 0x04 #define CMD_DCMI_ACT_POWLIMIT 0x05 #define CMD_DCMI_GET_ASSETTAG 0x06 #define CMD_DCMI_GET_SENSORINF 0x07 #define CMD_DCMI_SET_ASSETTAG 0x08 #define CMD_DCMI_GET_MCIDSTR 0x09 #define CMD_DCMI_SET_MCIDSTR 0x0A /* for DCMI 1.5 only */ #define CMD_DCMI_SET_THERMLIM 0x0B #define CMD_DCMI_GET_THERMLIM 0x0C #define CMD_DCMI_GET_TEMPRDNGS 0x10 #define CMD_DCMI_SET_CONFIG 0x12 #define CMD_DCMI_GET_CONFIG 0x13 /* CMD_DCMI_SET_POWLIMIT options */ #define CORRECTION_TIME 0x01 #define EXCEPTION_ACTION 0x02 #define POWER_LIMIT 0x03 #define SAMPLE_PERIOD 0x04 #endif /* end idcmi.h */ ipmiutil-3.1.5/util/md2.c0000644000076400007640000000656613566765324015276 0ustar mgportalloggers/* * md2.c * Used in ipmilan.c * * 05/26/2006 ARCress - copied from freeipmi ipmi-md2.c, * added md2_sum() subroutine, added WIN32 flag * 08/14/2008 ARCress - moved md2 routines from md2.c to md2.h */ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2002-2008, 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 Corporation 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. *----------------------------------------------------------------------*/ #include #include #include #include #include #undef MD2_GPL #undef MD2_LIB #if defined(ALLOW_GNU) #define MD2_GPL 1 /*use md2.h GPL code*/ #else /* if here, ALLOW_GPL is not defined, check for lanplus libcrypto. */ #if defined(HAVE_LANPLUS) #define MD2_LIB 1 /*use MD2 version from lanplus libcrypto */ #endif /* if libcrypto does not have EVP_md2, then skip MD2. */ #if defined(SKIP_MD2) #undef MD2_LIB #endif #endif /* use GPL md2.h only if "configure --enable-gpl" set ALLOW_GPL */ #ifdef MD2_GPL /* * The md2.h contains some GPL code that may not be desired in some cases. * If GPL is not desired, the md2.h can be deleted without modifying the * configure/make process. * If GPL is ok, then "configure --enable-gpl" should be used. */ #include "md2.h" #else /* else MD2_GPL is not set */ #ifdef MD2_LIB /* Use EVP_md2() from the openssl libcrypto.so */ #include void md2_sum(unsigned char *pdata, int sdata, unsigned char *digest) { EVP_MD_CTX ctx; unsigned int mdlen; static int fmd2added = 0; const EVP_MD *md = NULL; md = EVP_md2(); if (fmd2added == 0) { EVP_add_digest(md); fmd2added = 1; } EVP_MD_CTX_init(&ctx); EVP_DigestInit_ex(&ctx, md, NULL); EVP_DigestUpdate(&ctx, pdata, sdata); mdlen = 16; EVP_DigestFinal_ex(&ctx, digest, &mdlen); EVP_MD_CTX_cleanup(&ctx); } #endif #endif /*end md2.c */ ipmiutil-3.1.5/util/ipmims.cpp0000644000076400007640000004742513566765324016451 0ustar mgportalloggers/*M* // $Workfile: ipmims.cpp $ // $Revision: 1.0 $ // $Modtime: 08 Sep 2008 13:31:14 $ // $Author: arcress at users.sourceforge.net $ // // This implements support for the Microsoft Windows 2003 R2 IPMI driver. // Note that this should be compiled with /TP (as C++). // // 09/08/08 ARCress - created. // 04/27/11 Jay Krell - fixed WIN64-unsafe logic // 09/30/13 ARCress - fixed Win2012 x64 SafeArrayDestroy fault // *M*/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2008, Intel Corporation Copyright (c) 2009 Kontron America, Inc. Copyright (c) 2013 Andy Cress All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Intel Corporation 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. *----------------------------------------------------------------------*/ #ifdef WIN32 /* Microsoft IPMI drver is only valid in Windows */ #define _WIN32_DCOM #pragma once #include #include #include //deprecated iostream.h #include //ole32.lib #include #include #ifdef ALONE #define uchar unsigned char #define ushort unsigned short #define ulong unsigned long #else #include "ipmicmd.h" extern "C" { extern ipmi_cmd_t ipmi_cmds[NCMDS]; } #endif static char fmsopen = 0; static char fdebugms = 0; static IWbemLocator *pLoc = 0; static IWbemServices *pSvc = 0; static IWbemClassObject* pClass = NULL; static IEnumWbemClassObject* pEnumerator = NULL; static IWbemClassObject* pInstance = NULL; static VARIANT varPath; #define NVAR 32 /* Wbem error return codes, returned by WMI */ #ifdef RES_ALL #define NRES 82 #else #define NRES 10 #endif static struct { char *desc; int val; } res_list[NRES] = { {"WBEM_E_FAILED", 0x80041001 }, {"WBEM_E_NOT_FOUND", 0x80041002 }, {"WBEM_E_ACCESS_DENIED", 0x80041003 }, {"WBEM_E_PROVIDER_FAILURE", 0x80041004 }, {"WBEM_E_TYPE_MISMATCH", 0x80041005 }, {"WBEM_E_OUT_OF_MEMORY", 0x80041006 }, {"WBEM_E_INVALID_CONTEXT", 0x80041007 }, {"WBEM_E_INVALID_PARAMETER", 0x80041008 }, {"WBEM_E_NOT_AVAILABLE", 0x80041009 }, {"WBEM_E_CRITICAL_ERROR", 0x8004100A } #ifdef RES_ALL , {"WBEM_E_CRITICAL_ERROR", 0x8004100A } , {"WBEM_E_INVALID_STREAM", 0x8004100B }, {"WBEM_E_NOT_SUPPORTED", 0x8004100C }, {"WBEM_E_INVALID_SUPERCLASS", 0x8004100D }, {"WBEM_E_INVALID_NAMESPACE", 0x8004100E }, {"WBEM_E_INVALID_OBJECT", 0x8004100F }, {"WBEM_E_INVALID_CLASS", 0x80041010 }, {"WBEM_E_PROVIDER_NOT_FOUND", 0x80041011 }, {"WBEM_E_INVALID_PROVIDER_REGISTRATION", 0x80041012 }, {"WBEM_E_PROVIDER_LOAD_FAILURE", 0x80041013 }, {"WBEM_E_INITIALIZATION_FAILURE", 0x80041014 }, {"WBEM_E_TRANSPORT_FAILURE", 0x80041015 }, {"WBEM_E_INVALID_OPERATION", 0x80041016 }, {"WBEM_E_INVALID_QUERY", 0x80041017 }, {"WBEM_E_INVALID_QUERY_TYPE", 0x80041018 }, {"WBEM_E_ALREADY_EXISTS", 0x80041019 }, {"WBEM_E_OVERRIDE_NOT_ALLOWED", 0x8004101A }, {"WBEM_E_PROPAGATED_QUALIFIER", 0x8004101B }, {"WBEM_E_PROPAGATED_PROPERTY", 0x8004101C }, {"WBEM_E_UNEXPECTED", 0x8004101D }, {"WBEM_E_ILLEGAL_OPERATION", 0x8004101E }, {"WBEM_E_CANNOT_BE_KEY", 0x8004101F }, {"WBEM_E_INCOMPLETE_CLASS", 0x80041020 }, {"WBEM_E_INVALID_SYNTAX", 0x80041021 }, {"WBEM_E_NONDECORATED_OBJECT", 0x80041022 }, {"WBEM_E_READ_ONLY", 0x80041023 }, {"WBEM_E_PROVIDER_NOT_CAPABLE", 0x80041024 }, {"WBEM_E_CLASS_HAS_CHILDREN", 0x80041025 }, {"WBEM_E_CLASS_HAS_INSTANCES", 0x80041026 }, {"WBEM_E_QUERY_NOT_IMPLEMENTED", 0x80041027 }, {"WBEM_E_ILLEGAL_NULL", 0x80041028 }, {"WBEM_E_INVALID_QUALIFIER_TYPE", 0x80041029 }, {"WBEM_E_INVALID_PROPERTY_TYPE", 0x8004102A }, {"WBEM_E_VALUE_OUT_OF_RANGE", 0x8004102B }, {"WBEM_E_CANNOT_BE_SINGLETON", 0x8004102C }, {"WBEM_E_INVALID_CIM_TYPE", 0x8004102D }, {"WBEM_E_INVALID_METHOD", 0x8004102E }, {"WBEM_E_INVALID_METHOD_PARAMETERS", 0x8004102F }, {"WBEM_E_SYSTEM_PROPERTY", 0x80041030 }, {"WBEM_E_INVALID_PROPERTY", 0x80041031 }, {"WBEM_E_CALL_CANCELLED", 0x80041032 }, {"WBEM_E_SHUTTING_DOWN", 0x80041033 }, {"WBEM_E_PROPAGATED_METHOD", 0x80041034 }, {"WBEM_E_UNSUPPORTED_PARAMETER", 0x80041035 }, {"WBEM_E_MISSING_PARAMETER_ID", 0x80041036 }, {"WBEM_E_INVALID_PARAMETER_ID", 0x80041037 }, {"WBEM_E_NONCONSECUTIVE_PARAMETER_IDS", 0x80041038 }, {"WBEM_E_PARAMETER_ID_ON_RETVAL", 0x80041039 }, {"WBEM_E_INVALID_OBJECT_PATH", 0x8004103A }, {"WBEM_E_OUT_OF_DISK_SPACE", 0x8004103B }, {"WBEM_E_BUFFER_TOO_SMALL", 0x8004103C }, {"WBEM_E_UNSUPPORTED_PUT_EXTENSION", 0x8004103D }, {"WBEM_E_UNKNOWN_OBJECT_TYPE", 0x8004103E }, {"WBEM_E_UNKNOWN_PACKET_TYPE", 0x8004103F }, {"WBEM_E_MARSHAL_VERSION_MISMATCH", 0x80041040 }, {"WBEM_E_MARSHAL_INVALID_SIGNATURE", 0x80041041 }, {"WBEM_E_INVALID_QUALIFIER", 0x80041042 }, {"WBEM_E_INVALID_DUPLICATE_PARAMETER", 0x80041043 }, {"WBEM_E_TOO_MUCH_DATA", 0x80041044 }, {"WBEM_E_SERVER_TOO_BUSY", 0x80041045 }, {"WBEM_E_INVALID_FLAVOR", 0x80041046 }, {"WBEM_E_CIRCULAR_REFERENCE", 0x80041047 }, {"WBEM_E_UNSUPPORTED_CLASS_UPDATE", 0x80041048 }, {"WBEM_E_CANNOT_CHANGE_KEY_INHERITANCE", 0x80041049 }, {"WBEM_E_CANNOT_CHANGE_INDEX_INHERITANCE", 0x80041050 }, {"WBEM_E_TOO_MANY_PROPERTIES", 0x80041051 }, {"WBEM_E_UPDATE_TYPE_MISMATCH", 0x80041052 }, {"WBEM_E_UPDATE_OVERRIDE_NOT_ALLOWED", 0x80041053 }, {"WBEM_E_UPDATE_PROPAGATED_METHOD", 0x80041054 }, {"WBEM_E_METHOD_NOT_IMPLEMENTED", 0x80041055 }, {"WBEM_E_METHOD_DISABLED", 0x80041056 }, {"WBEMESS_E_REGISTRATION_TOO_BROAD", 0x80042001 }, {"WBEMESS_E_REGISTRATION_TOO_PRECISE", 0x80042002 } #endif }; /* * Microsoft_IPMI methods: * void RequestResponse( * [in] uint8 Command, * [out] uint8 CompletionCode, * [in] uint8 Lun, * [in] uint8 NetworkFunction, * [in] uint8 RequestData[], * [out] uint32 ResponseDataSize, * [in] uint32 RequestDataSize, * [in] uint8 ResponderAddress, * [out] uint8 ResponseData * ); * * void SMS_Attention( * [out] boolean AttentionSet, * [out] uint8 StatusRegisterValue * ); */ static void cleanup_wmi(void) { VariantClear(&varPath); if (pInstance != NULL) pInstance->Release(); if (pEnumerator != NULL) pEnumerator->Release(); if (pClass != NULL) pClass->Release(); if (pSvc != 0) pSvc->Release(); if (pLoc != 0) pLoc->Release(); CoUninitialize(); } static void dumpbuf(uchar *p, int len, char fwrap) { int i; for (i = 0; i < len; i++) { if (fwrap) { if ((i % 16) == 0) printf("\n%04x: ",i); } printf(" %02x",p[i]); } printf("\n"); return; } static char *res_str(HRESULT res) { char *pstr = ""; int i; for (i = 0; i < NRES; i++) { if (res_list[i].val == res) { pstr = &res_list[i].desc[0]; break; } } return (pstr); } extern "C" { int ipmi_open_ms(char fdebugcmd) { int bRet = -1; HRESULT hres; ULONG dwCount = NULL; fdebugms = fdebugcmd; // Initialize COM. hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { if (fdebugcmd) printf("ipmi_open_ms: CoInitializeEx error\n"); return bRet; } // Obtain the initial locator to Windows Management // on a particular host computer. hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc); if (FAILED(hres)) { CoUninitialize(); if (fdebugcmd) printf("ipmi_open_ms: CreateInstance(WbemLoc) error\n"); return bRet; } // Connect to the root\cimv2 namespace with the current user // and obtain pointer pSvc to make IWbemServices calls. hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\WMI"), NULL, NULL, 0, NULL, 0, 0, &pSvc ); if (FAILED(hres)) { pLoc->Release(); CoUninitialize(); if (fdebugcmd) printf("ipmi_open_ms: ConnectServer error\n"); return bRet; } // Set the IWbemServices proxy so that impersonation // of the user (client) occurs. hres = CoSetProxyBlanket( pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE ); if (FAILED(hres)) { if (fdebugcmd) printf("ipmi_open_ms: Cannot SetProxyBlanket\n"); cleanup_wmi(); return bRet; // Program has failed. } hres = pSvc->GetObject( L"Microsoft_IPMI", 0, NULL, &pClass, NULL); if (FAILED(hres)) { cleanup_wmi(); if (fdebugcmd) printf("ipmi_open_ms: cannot open microsoft_ipmi driver (ipmidrv.sys)\n"); return bRet; } hres = pSvc->CreateInstanceEnum( L"microsoft_ipmi", 0, NULL, &pEnumerator); if (FAILED(hres)) { cleanup_wmi(); if (fdebugcmd) printf("ipmi_open_ms: cannot open microsoft_ipmi Enum\n"); return bRet; } hres = pEnumerator->Next( WBEM_INFINITE, 1, &pInstance, &dwCount); if (FAILED(hres)) { if (fdebugcmd) printf("ipmi_open_ms: Cannot get microsoft_ipmi instance\n"); cleanup_wmi(); return bRet; } VariantInit(&varPath); hres = pInstance->Get(_bstr_t(L"__RelPath"), 0, &varPath, NULL, 0); if (FAILED(hres)) { if (fdebugcmd) printf("ipmi_open_ms: Cannot get instance Path %s\n","__RelPath"); cleanup_wmi(); return bRet; } else { /*success*/ if (fdebugcmd) printf("ipmi_open_ms: ObjectPath: %ls\n",V_BSTR(&varPath)); // usually L"Microsoft_IPMI.InstanceName=\"Root\\SYSTEM\\0003_0\"", fmsopen = 1; bRet = 0; } return bRet; } int ipmi_close_ms(void) { int bRet = -1; if (fmsopen) { cleanup_wmi(); fmsopen = 0; bRet = 0; } return bRet; } int ipmi_cmdraw_ms(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int bRet; HRESULT hres; IWbemClassObject* pInParams = NULL; /*class definition*/ IWbemClassObject* pInReq = NULL; /*instance*/ IWbemClassObject* pOutResp = NULL; VARIANT varCmd, varNetfn, varLun, varSa, varSize, varData; SAFEARRAY* psa = NULL; long i; uchar *p; fdebugms = fdebugcmd; if (!fmsopen) { bRet = ipmi_open_ms(fdebugcmd); if (bRet != 0) return(bRet); } bRet = -1; hres = pClass->GetMethod(L"RequestResponse",0,&pInParams,NULL); if (FAILED(hres)) { if (fdebugcmd) printf("ipmi_cmdraw_ms: Cannot get RequestResponse method\n"); return (bRet); } #ifdef WDM_FIXED /* see http://support.microsoft.com/kb/951242 for WDM bug info */ hres = pInParams->SpawnInstance(0,&pInReq); if (FAILED(hres)) { if (fdebugcmd) printf("ipmi_cmdraw_ms: Cannot get RequestResponse instance\n"); return (bRet); } // also substitute pInReq for pInParams below if this gets fixed. #endif VariantInit(&varCmd); varCmd.vt = VT_UI1; varCmd.bVal = cmd; hres = pInParams->Put(_bstr_t(L"Command"), 0, &varCmd, 0); // VariantClear(&varCmd); if (FAILED(hres)) goto MSRET; VariantInit(&varNetfn); varNetfn.vt = VT_UI1; varNetfn.bVal = netfn; hres = pInParams->Put(_bstr_t(L"NetworkFunction"), 0, &varNetfn, 0); // VariantClear(&varNetfn); if (FAILED(hres)) goto MSRET; VariantInit(&varLun); varLun.vt = VT_UI1; varLun.bVal = lun; hres = pInParams->Put(_bstr_t(L"Lun"), 0, &varLun, 0); // VariantClear(&varLun); if (FAILED(hres)) goto MSRET; VariantInit(&varSa); varSa.vt = VT_UI1; varSa.bVal = sa; hres = pInParams->Put(_bstr_t(L"ResponderAddress"), 0, &varSa, 0); // VariantClear(&varSa); if (FAILED(hres)) goto MSRET; VariantInit(&varSize); varSize.vt = VT_I4; varSize.lVal = sdata; hres = pInParams->Put(_bstr_t(L"RequestDataSize"), 0, &varSize, 0); // VariantClear(&varSize); if (FAILED(hres)) goto MSRET; SAFEARRAYBOUND rgsabound[1]; rgsabound[0].cElements = sdata; rgsabound[0].lLbound = 0; psa = SafeArrayCreate(VT_UI1,1,rgsabound); if(!psa) { printf("ipmi_cmdraw_ms: SafeArrayCreate failed\n"); goto MSRET; } #ifdef SHOULD_WORK_BUT_NO /* The SafeArrayPutElement does not put the data in the right * place, so skip this and copy the raw data below. */ VARIANT tvar; if (fdebugcmd && sdata > 0) { printf("psa1(%p):",psa); dumpbuf((uchar *)psa,42,1); } for(i =0; i< sdata; i++) { VariantInit(&tvar); tvar.vt = VT_UI1; tvar.bVal = pdata[i]; hres = SafeArrayPutElement(psa, &i, &tvar); // VariantClear(&tvar); if (FAILED(hres)) { printf("ipmi_cmdraw_ms: SafeArrayPutElement(%d) failed\n",i); goto MSRET; } } /*end for*/ if (fdebugcmd && sdata > 0) { printf("psa2(%p):",psa); dumpbuf((uchar *)psa,42,1); } #endif /* Copy the real RequestData into psa */ memcpy(psa->pvData,pdata,sdata); VariantInit(&varData); varData.vt = VT_ARRAY | VT_UI1; varData.parray = psa; hres = pInParams->Put(_bstr_t(L"RequestData"), 0, &varData, 0); // VariantClear(&varData); if (FAILED(hres)) { printf("Put(RequestData) error %x\n",hres); goto MSRET; } #ifdef TEST_METHODS IWbemClassObject* pOutSms = NULL; if (fdebugcmd) printf("ipmi_cmdraw_ms: calling SMS_Attention(%ls)\n", V_BSTR(&varPath)); hres = pSvc->ExecMethod( V_BSTR(&varPath), _bstr_t(L"SMS_Attention"), 0, NULL, NULL, &pOutSms, NULL); if (FAILED(hres)) { printf("ipmi_cmdraw_ms: SMS_Attention method error %x\n",hres); goto MSRET; } if (fdebugcmd) printf("ipmi_cmdraw_ms: SMS_Attention method ok\n"); /* This does work, without input parameters */ pOutSms->Release(); #endif hres = pSvc->ExecMethod( V_BSTR(&varPath), _bstr_t(L"RequestResponse"), 0, NULL, pInParams, &pOutResp, NULL); if (fdebugcmd) { printf("ipmi_cmdraw_ms(cmd=%x,netfn=%x,lun=%x,sa=%x,sdata=%d)" " RequestResponse ret=%x\n", cmd,netfn,lun,sa,sdata,hres); if (sdata > 0) { printf("ipmi_cmdraw_ms: req data(%d):",sdata); dumpbuf(pdata,sdata,0); } } if (FAILED(hres)) { printf("ipmi_cmdraw_ms: RequestResponse error %x %s\n", hres,res_str(hres)); #ifdef EXTRA_DESC /* This does not usually add any meaning for IPMI. */ BSTR desc; IErrorInfo *pIErrorInfo; GetErrorInfo(0,&pIErrorInfo); pIErrorInfo->GetDescription(&desc); printf("ipmi_cmdraw_ms: ErrorInfoDescr: %ls\n",desc); SysFreeString(desc); #endif bRet = -1; /*fall through for cleanup and return*/ } else { /*successful, get ccode and response data */ VARIANT varByte, varRSz, varRData; VariantInit(&varByte); VariantInit(&varRSz); VariantInit(&varRData); long rlen; hres = pOutResp->Get(_bstr_t(L"CompletionCode"),0, &varByte, NULL, 0); if (FAILED(hres)) goto MSRET; if (fdebugcmd) printf("ipmi_cmdraw_ms: CompletionCode %x returned\n", V_UI1(&varByte) ); *pcc = V_UI1(&varByte); hres = pOutResp->Get(_bstr_t(L"ResponseDataSize"),0, &varRSz, NULL, 0); if (FAILED(hres)) goto MSRET; rlen = V_I4(&varRSz); if (rlen > 1) rlen--; /*skip cc*/ if (rlen > *sresp) { if (fdebugcmd) printf("ResponseData truncated from %d to %d\n", rlen,*sresp); rlen = *sresp; /*truncate*/ } *sresp = (int)rlen; hres = pOutResp->Get(_bstr_t(L"ResponseData"),0, &varRData, NULL,0); if (FAILED(hres)) { /*ignore failure */ if (fdebugcmd) printf("Get ResponseData error %x\n",hres); } else { /* success */ #ifdef SHOULD_WORK_BUT_NO uchar *pa; p = (uchar*)varRData.parray->pvData; pa = (uchar*)varRData.parray; printf("pa=%p, pa+12=%p p=%p\n",pa,(pa+12),p); if (fdebugcmd) { printf("Data.vt = %04x, Data.parray(%p):", varRData.vt, varRData.parray); // 0x2011 means VT_ARRAY | VT_UI1 dumpbuf((uchar *)varRData.parray,40,1); } /* The SafeArrayGetElement does not get the data from the right * place, so skip this and copy the raw data below. */ VARIANT rgvar[NVAR]; if (rlen > NVAR) *pcc = 0xEE; for (i = 0; i <= rlen; i++) VariantInit(&rgvar[i]); /* copy the response data from varRData to presp */ for( i = 0; i <= rlen; i++) { hres = SafeArrayGetElement(varRData.parray, &i, &rgvar[i]); if (FAILED(hres)) { if (fdebugcmd) printf("ipmi_cmdraw_ms: SafeArrayGetElement(%d) failed\n",i); break; } if (fdebugcmd) { printf("Data[%d] vt=%02x val=%02x, rgvar(%p):",i, rgvar[i].vt, V_UI1(&rgvar[i]),&rgvar[i]); dumpbuf((uchar *)&rgvar[i],12,0); } /* skip the completion code */ // if (i > 0) presp[i-1] = V_UI1(&rgvar[i]); } /*end for*/ #endif /* * parray from a GetDeviceId response: * 0015CEE0: 01 00 80 00 01 00 00 00 00 00 00 00 00 cf 15 00 * 0015CEF0: 10 00 00 00 00 00 00 00 03 00 06 00 95 01 08 00 * ^- datalen=0x10 * 0015CF00: 00 20 01 00 19 02 9f 57 01 ... * ^- start of data (cc=00, ...) */ /* Copy the real ResponseData into presp. */ p = (uchar*)varRData.parray->pvData; for( i = 0; i <= rlen; i++) { /* skip the completion code */ if (i > 0) presp[i-1] = p[i]; } if (fdebugcmd) { printf("ipmi_cmdraw_ms: resp data(%d):",rlen+1); dumpbuf(p,rlen+1,0); } } bRet = 0; } MSRET: #define CLEAN_OK 1 #ifdef CLEAN_OK /* VariantClear(&var*) should be done by pInParams->Release() */ if (psa != NULL) SafeArrayDestroy(psa); if (pInParams != NULL) pInParams->Release(); if (pOutResp != NULL) pOutResp->Release(); #endif return(bRet); } #ifndef ALONE int ipmi_cmd_ms(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int bRet = -1; int i; fdebugms = fdebugcmd; for (i = 0; i < NCMDS; i++) { if (ipmi_cmds[i].cmdtyp == cmd) break; } if (i >= NCMDS) { printf("ipmi_cmd_ms: Unknown command %04x\n",cmd); return(-1); } if (cmd >= CMDMASK) cmd = cmd & CMDMASK; /* unmask it */ bRet = ipmi_cmdraw_ms((uchar)cmd,ipmi_cmds[i].netfn,ipmi_cmds[i].lun, ipmi_cmds[i].sa, ipmi_cmds[i].bus, pdata,sdata,presp,sresp,pcc,fdebugcmd); return (bRet); } #endif } /* end C */ #ifdef TEST_BIN int main(int argc, char **argv) { uchar rdata[40]; int i, rv; int rlen = 0; uchar cc; fdebugms = 1; rlen = sizeof(rdata); rv = ipmi_cmdraw_ms(0x01, 0x06, 0, 0x20, 0, /*get_device_id*/ NULL, 0, rdata, &rlen, &cc, fdebugms); printf("ipmi_cmdraw_ms ret=%d, cc=%02x\n",rv,cc); if (rv == 0) { printf(" ** Return Code: %2.2X\n", cc); printf(" ** Data[%d]:",rlen); for (i=0; i < rlen; i++) printf(" %2.2X", rdata[i]); printf("\n"); } ipmi_close_ms(); return 0; } #endif #endif /* endif WIN32 */ /* end ipmims.cpp */ ipmiutil-3.1.5/util/ipmiutil2-64.mak0000644000076400007640000003361613566765324017303 0ustar mgportalloggers# This makefile will build the ipmiutil util directory (x64 without lanplus) # # First download getopt.c getopt.h # Then download and build openssl for Windows # LIBC_RT=libcmt.lib /NODEFAULTLIB:"msvcirt.lib" # LIBC_RT=msvcrt.lib /NODEFAULTLIB:"msvcirt.lib" MARCH=X64 #MARCH=IX86 # The ipmiutil directory SRC_D=. LIB_D=..\lib L2_D=$(LIB_D)\lanplus L3_D=$(LIB_D)\lanplus\inc INSTALLTOP=install TMP_D=tmp INC=/I$(SRC_D) /I$(L2_D) /I$(L3_D) CMD_OBJ = getopt.obj ipmicmd.obj imbapi.obj md5.obj md2.obj \ ipmilan.obj ipmims.obj subs.obj CMD_OBJ = $(CMD_OBJ) ipmilanplus.obj # To remove lanplus support use the empty LANPLUS variables L2_OBJ= L2_LIB= LF_LANPLUS= CF_LANPLUS= #L2_OBJ = $(L2_D)\helper.obj $(L2_D)\ipmi_strings.obj $(L2_D)\lanplus.obj \ # $(L2_D)\lanplus_crypt_impl.obj $(L2_D)\lanplus_dump.obj \ # $(L2_D)\lanplus_strings.obj $(L2_D)\lanplus_crypt.obj #L2_LIB=lanplus.lib #LF_LANPLUS=/LIBPATH:$(LIB_D) $(L2_OBJ) ssleay32.lib libeay32.lib #CF_LANPLUS=/D HAVE_LANPLUS # Set your compiler options # To remove any GPL dependencies, use the CF_EX line with NON_GPL # CFLAGS_O=/W3 /O2 /Zi /MD /GF /Gy /nologo # CFLAGS_O=/W3 /O2 /Zi /MD /nologo # CFLAGS_O=/W3 /O2 /Zi /MT /nologo CFLAGS_O=/W3 /O2 /Zi /MT /nologo CF_EX=/DWIN32 $(CF_LANPLUS) $(INC) /D_CONSOLE /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DHAVE_STRING_H CF_SAM=/DWIN32 $(INC) /D_CONSOLE /D_CRT_SECURE_NO_DEPRECATE /DHAVE_STRING_H CFLAGS=$(CFLAGS_O) $(CF_EX) /DSKIP_MD2 CFLAGS_M=$(CFLAGS_O) $(CF_EX) /DSKIP_MD2 /DMETACOMMAND CFLAGS_SAM=$(CFLAGS_O) $(CF_SAM) LFLAGS=/nologo /subsystem:console /machine:$(MARCH) /opt:ref #LFLAGS=/nologo /subsystem:console /machine:IX86 /opt:ref #LFLAGS=/nologo /subsystem:console /machine:IX86 /opt:ref /debug # LFLAGS_D=/nologo /subsystem:console /machine:I386 /opt:ref /dll # CFLAGS_W=/O2 /D_CONSOLE /D_MBCS /EHsc /ML /W3 /Zi /TP CFLAGS_W=/TP /EHsc $(CFLAGS) LFLAGS_W=/nologo /subsystem:console /machine:$(MARCH) /opt:ref LIBS_W=comsuppw.lib wbemuuid.lib # gdi32.lib comdlg32.lib shell32.lib uuid.lib CC=cl LINK=link MKDIR=-mkdir MKLIB=lib RM=del CP=copy LIBS_EX = advapi32.lib kernel32.lib wsock32.lib ws2_32.lib $(LIBS_W) $(LIBC_RT) LIBS_PEF = /LIBPATH:$(LIB_D) iphlpapi.lib # LIBS_EX+=wsock32.lib user32.lib gdi32.lib HEADER=ipmicmd.h imb_api.h ipmilan.h ipmidir.h ipmilanplus.h \ ipmiutil.h SHOWSEL = showsel TARG_EXE=ievents.exe $(SHOWSEL)msg.dll ipmi_sample.exe ipmi_sample_evt.exe $(SAMP_DLL) # alarms.exe ihealth.exe $(SHOWSEL).exe $(SHOWSEL)msg.dll \ # ireset.exe ifru.exe ilan.exe iserial.exe wdt.exe \ # getevent.exe sensor.exe icmd.exe isolconsole.exe idiscover.exe \ # ievents.exe SAMP_LIB = ipmiutil.lib SAMP_DLL = ipmiutillib.dll E_EXE=ipmiutil.exe E_OBJ=$(TMP_D)\ipmiutil.obj \ $(TMP_D)\ialarms.obj $(TMP_D)\ihealth.obj $(TMP_D)\iwdt.obj \ $(TMP_D)\ireset.obj $(TMP_D)\ifru.obj $(TMP_D)\ilan.obj \ $(TMP_D)\iserial.obj $(TMP_D)\icmd.obj $(TMP_D)\isol.obj \ $(TMP_D)\isolwin.obj $(TMP_D)\AnsiTerm.obj $(TMP_D)\idiscover.obj \ $(TMP_D)\iconfig.obj $(TMP_D)\igetevent.obj $(TMP_D)\isensor.obj \ $(TMP_D)\isel.obj $(TMP_D)\ievents.obj \ $(TMP_D)\ipicmg.obj $(TMP_D)\ifirewall.obj \ $(TMP_D)\iekanalyzer.obj $(TMP_D)\ifru_picmg.obj \ $(TMP_D)\oem_kontron.obj $(TMP_D)\ihpm.obj $(TMP_D)\ifwum.obj \ $(TMP_D)\oem_fujitsu.obj $(TMP_D)\oem_intel.obj $(TMP_D)\oem_lenovo.obj \ $(TMP_D)\oem_asus.obj $(TMP_D)\iuser.obj \ $(TMP_D)\oem_sun.obj $(TMP_D)\oem_dell.obj $(TMP_D)\oem_hp.obj \ $(TMP_D)\oem_supermicro.obj $(TMP_D)\itsol.obj $(TMP_D)\idcmi.obj \ $(TMP_D)\oem_quanta.obj $(TMP_D)\oem_newisys.obj $(CMD_OBJ) mem_if.obj ################################################################### all: banner $(TMP_D) exe banner: @echo Building ipmiutil $(TMP_D): $(MKDIR) $(TMP_D) @echo created $(TMP_D) lib: $(L2_OBJ) cd $(LIB_D) nmake /nologo -f ipmilib.mak cd ../util exe: $(E_EXE) $(TARG_EXE) install: $(MKDIR) $(INSTALLTOP) $(MKDIR) $(INSTALLTOP)\bin $(CP) $(E_EXE) $(INSTALLTOP)\bin xcopy $(TARG_EXE) $(INSTALLTOP)\bin xcopy *.dll $(INSTALLTOP)\bin clean: $(RM) *.obj 2>NUL $(RM) $(TARG_EXE) 2>NUL $(RM) *.exe 2>NUL $(RM) $(TMP_D)\*.obj 2>NUL distclean: $(RM) *.obj 2>NUL $(RM) $(TARG_EXE) 2>NUL $(RM) *.exe 2>NUL $(RM) $(TMP_D)\*.* 2>NUL rmdir $(TMP_D) 2>NUL $(RM) *.rc 2>NUL $(RM) *.bin 2>NUL $(RM) *.RES 2>NUL $(RM) getopt.* 2>NUL getopt.obj: getopt.c $(CC) /c $(CFLAGS) getopt.c imbapi.obj: imbapi.c $(CC) /c $(CFLAGS_M) imbapi.c ipmicmd.obj: ipmicmd.c $(CC) /c $(CFLAGS) ipmicmd.c ipmilan.obj: ipmilan.c $(CC) /c $(CFLAGS) ipmilan.c ipmilanplus.obj: ipmilanplus.c $(CC) /c $(CFLAGS_M) ipmilanplus.c md5.obj: md5.c $(CC) /c $(CFLAGS) md5.c md2.obj: md2.c $(CC) /c $(CFLAGS) md2.c ievents.obj: ievents.c $(CC) /c $(CFLAGS) ievents.c ialarms.obj: ialarms.c $(CC) /c $(CFLAGS) ialarms.c ihealth.obj: ihealth.c $(CC) /c $(CFLAGS) ihealth.c igetevent.obj: igetevent.c $(CC) /c $(CFLAGS) igetevent.c mem_if.obj: mem_if.c $(CC) /c $(CFLAGS_W) mem_if.c ipmims.obj: ipmims.cpp $(CC) /c $(CFLAGS_W) ipmims.cpp isel.obj: isel.c $(CC) /c $(CFLAGS) isel.c ireset.obj: ireset.c $(CC) /c $(CFLAGS) ireset.c ireset.exe: ireset.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ireset.exe ireset.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) ifru.obj: ifru.c $(CC) /c $(CFLAGS) ifru.c ifru.exe: ifru.obj mem_if.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ifru.exe ifru.obj mem_if.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) ilan.obj: ilan.c $(CC) /c $(CFLAGS) ilan.c ilan.exe: ilan.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ilan.exe ilan.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_PEF) $(LIBS_EX) iserial.obj: iserial.c $(CC) /c $(CFLAGS) iserial.c iserial.exe: iserial.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:iserial.exe iserial.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) isensor.obj: isensor.c $(CC) /c $(CFLAGS) isensor.c isensor.exe: isensor.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:isensor.exe isensor.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) iwdt.obj: iwdt.c $(CC) /c $(CFLAGS) iwdt.c iwdt.exe: iwdt.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:iwdt.exe iwdt.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) isol.obj: isol.c $(CC) /c $(CFLAGS) isol.c isolwin.obj: isolwin.c $(CC) /c $(CFLAGS) isolwin.c isol.exe: isol.obj isolwin.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:isol.exe isol.obj isolwin.obj \ $(CMD_OBJ) $(LF_LANPLUS) $(LIBS_EX) icmd.obj: icmd.c $(CC) /c $(CFLAGS) icmd.c icmd.exe: icmd.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:icmd.exe icmd.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) idiscover.obj: idiscover.c $(CC) /c $(CFLAGS) idiscover.c idiscover.exe: idiscover.obj getopt.obj $(LINK) $(LFLAGS) /OUT:idiscover.exe idiscover.obj getopt.obj \ $(LF_LANPLUS) $(LIBS_EX) ialarms.exe: ialarms.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ialarms.exe ialarms.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) ihealth.exe: ihealth.obj mem_if.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ihealth.exe ihealth.obj mem_if.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) igetevent.exe: igetevent.obj ievents.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:igetevent.exe igetevent.obj ievents.obj \ $(CMD_OBJ) $(LF_LANPLUS) $(LIBS_EX) isel.exe: isel.obj ievents.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:isel.exe isel.obj ievents.obj \ $(CMD_OBJ) $(LF_LANPLUS) $(LIBS_EX) $(SHOWSEL).mc: $(CP) ..\scripts\$(SHOWSEL).mc . $(SHOWSEL)msg.dll: $(SHOWSEL).mc mc -U $(SHOWSEL).mc rc -r $(SHOWSEL).rc $(LINK) /machine:$(MARCH) -dll -noentry -out:$(SHOWSEL)msg.dll $(SHOWSEL).res mem_if.exe: $(TMP_D)\mem_if.obj $(LINK) $(LFLAGS_W) /OUT:mem_if.exe $(TMP_D)\mem_if.obj $(LIBS_EX) $(TMP_D)\mem_if.obj: mem_if.c $(CC) /c $(CFLAGS_W) /DCOMP_BIN /Fo$(TMP_D)\mem_if.obj mem_if.c ievents.exe: ievents.c $(CC) /c $(CFLAGS) /DALONE ievents.c $(LINK) $(LFLAGS) /OUT:ievents.exe ievents.obj $(LIBS_EX) $(RM) ievents.obj ipmims.exe: ipmims.cpp $(CC) /c $(CFLAGS_W) /DALONE /DTEST_BIN ipmims.cpp $(LINK) $(LFLAGS_W) /OUT:ipmims.exe ipmims.obj $(LIBS_EX) $(RM) ipmims.obj $(TMP_D)\ievents.obj: ievents.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ievents.obj ievents.c $(TMP_D)\ipmiutil.obj: ipmiutil.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ipmiutil.obj ipmiutil.c $(TMP_D)\ialarms.obj: ialarms.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ialarms.obj ialarms.c $(TMP_D)\ihealth.obj: ihealth.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ihealth.obj ihealth.c $(TMP_D)\iconfig.obj: iconfig.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iconfig.obj iconfig.c $(TMP_D)\ipicmg.obj: ipicmg.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ipicmg.obj ipicmg.c $(TMP_D)\ifirewall.obj: ifirewall.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifirewall.obj ifirewall.c $(TMP_D)\ifwum.obj: ifwum.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifwum.obj ifwum.c $(TMP_D)\ihpm.obj: ihpm.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ihpm.obj ihpm.c $(TMP_D)\idcmi.obj: idcmi.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\idcmi.obj idcmi.c $(TMP_D)\iuser.obj: iuser.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iuser.obj iuser.c $(TMP_D)\oem_fujitsu.obj: oem_fujitsu.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_fujitsu.obj oem_fujitsu.c $(TMP_D)\oem_kontron.obj: oem_kontron.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_kontron.obj oem_kontron.c $(TMP_D)\oem_intel.obj: oem_intel.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_intel.obj oem_intel.c $(TMP_D)\oem_sun.obj: oem_sun.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_sun.obj oem_sun.c $(TMP_D)\oem_dell.obj: oem_dell.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_dell.obj oem_dell.c $(TMP_D)\oem_hp.obj: oem_hp.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_hp.obj oem_hp.c $(TMP_D)\oem_supermicro.obj: oem_supermicro.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_supermicro.obj oem_supermicro.c $(TMP_D)\oem_lenovo.obj: oem_lenovo.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_lenovo.obj oem_lenovo.c $(TMP_D)\oem_asus.obj: oem_asus.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_asus.obj oem_asus.c $(TMP_D)\oem_quanta.obj: oem_quanta.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_quanta.obj oem_quanta.c $(TMP_D)\oem_newisys.obj: oem_newisys.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_newisys.obj oem_newisys.c $(TMP_D)\iekanalyzer.obj: iekanalyzer.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iekanalyzer.obj iekanalyzer.c $(TMP_D)\ifru_picmg.obj: ifru_picmg.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifru_picmg.obj ifru_picmg.c $(TMP_D)\ifru.obj: ifru.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifru.obj ifru.c $(TMP_D)\ireset.obj: ireset.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ireset.obj ireset.c $(TMP_D)\ilan.obj: ilan.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ilan.obj ilan.c $(TMP_D)\iserial.obj: iserial.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iserial.obj iserial.c $(TMP_D)\isensor.obj: isensor.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isensor.obj isensor.c $(TMP_D)\icmd.obj: icmd.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\icmd.obj icmd.c $(TMP_D)\igetevent.obj: igetevent.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\igetevent.obj igetevent.c $(TMP_D)\isel.obj: isel.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isel.obj isel.c $(TMP_D)\isol.obj: isol.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isol.obj isol.c $(TMP_D)\isolwin.obj: isolwin.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isolwin.obj isolwin.c $(TMP_D)\itsol.obj: itsol.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\itsol.obj itsol.c $(TMP_D)\AnsiTerm.obj: AnsiTerm.cpp $(CC) /c $(CFLAGS_W) /Fo$(TMP_D)\AnsiTerm.obj AnsiTerm.cpp $(TMP_D)\idiscover.obj: idiscover.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\idiscover.obj idiscover.c $(TMP_D)\iwdt.obj: iwdt.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iwdt.obj iwdt.c $(E_EXE): $(E_OBJ) $(LINK) $(LFLAGS) /OUT:$(E_EXE) $(E_OBJ) $(LF_LANPLUS) $(LIBS_PEF) $(LIBS_EX) ipmi_sample.obj: ipmi_sample.c $(CC) /c $(CFLAGS_SAM) ipmi_sample.c $(SAMP_LIB): $(CMD_OBJ) mem_if.obj $(CC) /c $(CFLAGS_SAM) ipmilanplus.c $(MKLIB) /OUT:$(SAMP_LIB) /nologo $(CMD_OBJ) mem_if.obj del ipmilanplus.obj $(SAMP_DLL): $(CMD_OBJ) mem_if.obj $(CC) /D_WINDLL /D_USRDLL /c $(CFLAGS_SAM) ipmilanplus.c $(LINK) /DLL $(LFLAGS) /OUT:$(SAMP_DLL) /def:ipmiutillib.def $(CMD_OBJ) mem_if.obj $(LIBS_PEF) $(LIBS_EX) del ipmilanplus.obj ipmi_sample.exe: $(SAMP_LIB) ipmi_sample.obj $(LINK) $(LFLAGS) /OUT:ipmi_sample.exe ipmi_sample.obj $(SAMP_LIB) $(LIBS_PEF) $(LIBS_EX) ipmi_sample2.exe: $(SAMP_LIB) ipmi_sample.c isensor.c ievents.c $(CC) /c $(CFLAGS_SAM) /DGET_SENSORS ipmi_sample.c $(CC) /c $(CFLAGS_SAM) isensor.c $(CC) /c $(CFLAGS_SAM) ievents.c $(LINK) $(LFLAGS) /OUT:ipmi_sample2.exe ipmi_sample.obj isensor.obj ievents.obj $(SAMP_LIB) $(LIBS_PEF) $(LIBS_EX) del isensor.obj ievents.obj ipmi_sample_evt.obj: ipmi_sample_evt.c $(HEADER) $(CC) /c $(CFLAGS_SAM) ipmi_sample_evt.c isensor2.obj: isensor.c isensor.h $(HEADER) $(CC) /c /Foisensor2.obj $(CFLAGS_SAM) isensor.c ievents2.obj: ievents.c ievents.h $(HEADER) $(CC) /c /Foievents2.obj $(CFLAGS_SAM) /DSENSORS_OK ievents.c ipmi_sample_evt.exe: $(SAMP_LIB) ipmi_sample_evt.obj ievents2.obj isensor2.obj $(LINK) $(LFLAGS) /OUT:ipmi_sample_evt.exe ipmi_sample_evt.obj ievents2.obj isensor2.obj $(SAMP_LIB) $(LIBS_PEF) $(LIBS_EX) ipmiutil-3.1.5/util/ialarms.c0000644000076400007640000005646713566765324016251 0ustar mgportalloggers/* * ialarms.c * * This tool reads and sets the alarms panel on an Intel Telco chassis. * Note that the Intel Server Management software will set these alarms * based on firmware-detected thresholds and events. * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2003-2006 Intel Corporation. * Copyright (c) 2009 Kontron America, Inc. * * 02/25/03 Andy Cress - created * 04/08/03 Andy Cress - added -i for ChassisIdentify * 04/30/03 Andy Cress - only try to set ID on/off if option specified * 01/20/04 Andy Cress - mods for mBMC w Chesnee platform * 05/05/04 Andy Cress - call ipmi_close before exit * 10/11/04 Andy Cress 1.4 - if -o set relays too (fsetall) * 11/01/04 Andy Cress 1.5 - add -N / -R for remote nodes * 03/07/05 Andy Cress 1.6 - add bus for Intel TIGI2U * 03/28/05 Andy Cress 1.7 - add check for BMC TAM if setting alarms * 06/22/05 Andy Cress 1.8 - adding fpicmg for ATCA alarm LEDs * 03/17/06 Andy Cress 1.9 - adding BUS_ID7 for Harbison * 04/20/07 Andy Cress 1.25 - adding disk Enclosure HSC LEDs */ /*M* Copyright (c) 2003-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 Corporation 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 #include #include #include #include #include #ifdef WIN32 #include "getopt.h" #elif defined(DOS) #include #include "getopt.h" #elif defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #include "ipmicmd.h" #include "oem_intel.h" /* * Global variables */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil alarms"; #else static char * progver = "3.08"; static char * progname = "ialarms"; #endif static char fdebug = 0; static char fbmctam = 0; static char fpicmg = 0; static char fHasAlarms = 0; static char fNSC = 0; static char fHasEnc = 0; /* Has disk Enclosure HSC? */ static int maxdisks = 6; /* default to max of 6 disks */ static uchar fdoencl = 1; static uchar picmg_id = 0; /* always 0 for picmg */ static uchar fru_id = 0; /* fru device id */ //static uchar led_id = 0; /* 0 = blue led, 1,2,3=led1,2,3 */ static uchar ipmi_maj, ipmi_min; #define ENC_LED_WRITE 0x21 // only used for Ballenger-CT HSC #define ENC_LED_READ 0x20 // only used for Ballenger-CT HSC #define NETFN_ENC 0x30 #define NETFN_PICMG 0x2c #define PICMG_GET_LED_PROPERTIES 0x05 #define PICMG_SET_LED_STATE 0x07 #define PICMG_GET_LED_STATE 0x08 #ifdef METACOMMAND extern int get_alarms_fujitsu(uchar *rgalarms); extern int show_alarms_fujitsu(uchar *rgalarms); extern int set_alarms_fujitsu(uchar num, uchar val); extern int get_led_status_intel(uchar *pstate); #endif #ifdef ALONE extern int get_led_status_intel(uchar *pstate); #endif static uchar busid = PRIVATE_BUS_ID; static uchar enc_sa = HSC_SA; static char fRomley = 0; static char fGrantley = 0; static int get_enc_leds(uchar *val) { uchar idata[16]; uchar rdata[16]; int rlen, i; int rv = 0; uchar cc; char *pstr = NULL; rlen = sizeof(rdata); for (i = 0; i < 3; i++) { rv = ipmi_cmdraw( ENC_LED_READ, NETFN_ENC, enc_sa, PUBLIC_BUS,BMC_LUN, idata,0, rdata, &rlen, &cc, fdebug); if (fdebug) printf("get_enc_leds() rv=%d cc=%x val=%02x\n",rv,cc,rdata[0]); if (rv == 0 && cc == 0x83) os_usleep(0,50000); /* HSC busy, wait 50ms */ else break; } if (rv != 0) pstr = decode_rv(rv); else if (cc != 0) pstr = decode_cc(0,cc); /* if get cc==0x83 here, the power state may be soft-off */ if (rv == 0 && cc != 0) rv = cc; if (rv == 0) { /*success*/ *val = rdata[0]; } else /*error*/ printf("get_enc_leds: error %s\n",pstr); return(rv); } static int set_enc_leds(uchar val) { uchar idata[16]; uchar rdata[16]; int rlen; int rv = 0; uchar cc; idata[0] = val; rlen = sizeof(rdata); rv = ipmi_cmdraw( ENC_LED_WRITE, NETFN_ENC, enc_sa, PUBLIC_BUS,BMC_LUN, idata,1, rdata, &rlen, &cc, fdebug); if (fdebug) printf("set_enc_leds(%02x) rv = %d, cc = %x\n",val,rv,cc); if (rv == 0 && cc != 0) rv = cc; return(rv); } static void show_enc_leds(uchar val) { char *enc_pattn = "disk slot %d LED: %s\n"; uchar mask; int i, n; if (fdebug) printf("val = %02x\n",val); n = maxdisks; if (n > 8) n = 8; mask = 0x01; /* Ballenger HSC only supports 6 slots, some support 8 */ for (i = 0; i < n; i++) { if (val & mask) printf(enc_pattn,i,"ON"); else printf(enc_pattn,i,"off"); mask = (mask << 1); } } static int set_chassis_id(uchar val) { uchar inputData[4]; uchar responseData[16]; int responseLength = 4; uchar completionCode; int ret; uchar ilen; ilen = 1; inputData[0] = val; /* #seconds to turn on id, 0=turn off */ /* IPMI 2.0 has an optional 2nd byte, * if 01, turn ID on indefinitely. */ if (val == 255 && ipmi_maj >= 2) { inputData[1] = 1; ilen = 2; } /* CHASSIS_IDENTIFY=0x04, using NETFN_CHAS (=00) */ ret = ipmi_cmd(CHASSIS_IDENTIFY, inputData, ilen, responseData, &responseLength, &completionCode, fdebug); if (ret == 0 && completionCode != 0) ret = completionCode; if (ret != 0) { printf("set_chassis_id: ret = %d, ccode %02x, value = %02x\n", ret, completionCode, val); } return(ret); } /*end set_chassis_id*/ static int get_alarms_picmg(uchar *rgv, uchar picmgid, uchar fruid, uchar led) { uchar inputData[4]; uchar responseData[16]; int responseLength; uchar completionCode; int ret, i; if (rgv == NULL) return(ERR_BAD_PARAM); inputData[0] = picmgid; inputData[1] = fruid; inputData[2] = led; // 0 = blue led responseLength = sizeof(responseData); ret = ipmi_cmdraw( PICMG_GET_LED_STATE, NETFN_PICMG, BMC_SA, PUBLIC_BUS,BMC_LUN, inputData,3, responseData, &responseLength, &completionCode, fdebug); if ((ret != 0) || (completionCode != 0)) { if (fdebug) printf("get_alarms_picmg(%d,%d,%d): ret = %d, ccode %02x\n", picmgid,fruid,led,ret, completionCode); if (ret == 0) ret = completionCode; return(ret); } /* if here, success */ if (fdebug) { printf("get_alarms_picmg(%d,%d,%d): ", picmgid,fruid,led); for (i = 0; i < responseLength; i++) printf("%02x ",responseData[i]); printf("\n"); } memcpy(rgv,responseData,responseLength); return(ret); } static int set_alarms_picmg(uchar val, uchar picmgid, uchar fruid, uchar led, char color) { uchar inputData[6]; uchar responseData[16]; int responseLength; uchar completionCode; int ret, i; inputData[0] = picmgid; inputData[1] = fruid; inputData[2] = led; // 0 = blue led inputData[3] = val; inputData[4] = 0; switch(color) { case 'w': i = 6; break; case 'o': i = 5; break; case 'a': i = 4; break; case 'g': i = 3; break; case 'r': i = 2; break; case 'b': default: i = 1; break; } inputData[5] = (uchar)i; // 1 = blue responseLength = sizeof(responseData); ret = ipmi_cmdraw( PICMG_SET_LED_STATE, NETFN_PICMG, BMC_SA, PUBLIC_BUS,BMC_LUN, inputData,6, responseData, &responseLength, &completionCode, fdebug); if ((ret != 0) || (completionCode != 0)) { printf("set_alarms_picmg(%02x,%d,%d,%d): ret = %d, ccode %02x\n", val,picmgid,fruid,led,ret, completionCode); if (ret == 0) ret = completionCode; return(ret); } printf("set_alarms_picmg(%02x,%d,%d,%d): ", val,picmgid,fruid,led); for (i = 0; i < responseLength; i++) printf("%02x ",responseData[i]); printf("\n"); return(ret); /* success */ } static void show_alarms_picmg(uchar *v, uchar pid, uchar fruid, uchar led) { char led_str[10]; char state_str[20]; char *func_str; char *color_str; if (v == NULL) return; if (fdebug) printf("picmg(%d,%d,%d) alarm LED state is %02x %02x %02x %02x %02x\n", pid,fruid,led,v[0],v[1],v[2],v[3],v[4]); switch(led) { case 0: strcpy(led_str,"HSLed"); break; /*Blue LED*/ default: sprintf(led_str," Led%d",led); break; } state_str[0] = 0; if (v[1] & 0x01) strcat(state_str,"local"); if (v[1] & 0x02) strcat(state_str," override"); if (v[1] & 0x04) strcat(state_str," lamptest"); switch(v[2]) { case 0x00: func_str = "off"; break; case 0xFF: func_str = "ON"; break; default: func_str = "Blink"; break; /*duration of blink/off*/ } /* v[3] is duration of blink/on in tens of msec */ switch(v[4]) { case 6: color_str = "white"; break; case 5: color_str = "orange"; break; case 4: color_str = "amber"; break; case 3: color_str = "green"; break; case 2: color_str = "red"; break; case 1: default: color_str = "blue"; break; } printf("picmg(%d,%d) %s is %s,%s,%s\n",fruid,led,led_str, state_str,func_str,color_str); } #ifdef METACOMMAND int i_alarms(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int ret = 0; int c; uchar fsetled = 0; uchar fsetall = 0; uchar fsetdisk = 0; uchar fsetid = 0; uchar fcrit = 2; uchar fmaj = 2; uchar fmin = 2; uchar fpow = 2; uchar fdiska = 2; uchar fdiskb = 2; uchar fdiskn = 2; uchar ndisk = 0; int fid = 0; uchar alarms = 0; uchar rgalarms[10] = {0,0,0,0,0,0}; uchar newvalue = 0xff; uchar diskled = 0xff; uchar encled = 0; uchar devrec[16]; uchar ledn = 0; uchar ledv = 0; char ledc = 'c'; int i; int flags = 0; int prod_id, vend_id; printf("%s ver %s\n", progname,progver); /* default to admin privilege if get/set alarms remotely */ parse_lan_options('V',"4",0); while ( (c = getopt( argc, argv,"rxa:b:c:d:efm:n:p:i:ow:Z:EF:P:N:R:U:T:V:J:Y?")) != EOF ) switch(c) { case 'r': fsetled=0; fsetid=0; fsetdisk = 0; break; /* read only */ case 'a': fdiska = atob(optarg); /* set disk A LED value */ fsetdisk = 1; break; case 'b': fdiskb = atob(optarg); /* set disk B LED value */ fsetdisk = 2; break; case 'c': fcrit = atob(optarg); /* set critical alarm value */ fsetled = 1; break; case 'd': ndisk = optarg[0] & 0x0f; /* set disk N LED on or off */ fdiskn = optarg[1] & 0x0f; fsetdisk = 3; break; case 'e': fdoencl = 0; /* skip disk/enclosure LEDs */ case 'f': fdiska = 10; /* set all disk LEDs off */ fsetdisk = 1; break; case 'm': fmaj = atob(optarg); /* set major alarm value */ fsetled = 1; break; case 'n': fmin = atob(optarg); /* set minor alarm value */ fsetled = 1; break; case 'p': fpow = atob(optarg); /* set power alarm value */ fsetled = 1; break; case 'w': ledn = optarg[0] & 0x0f; /* set picmg LED N on or off */ ledv = optarg[1] & 0x0f; ledc = optarg[2]; /*color char, usu 'b' for blue*/ fsetled = 1; break; case 'i': fid = atoi(optarg); /* set chassis id on/off */ if (fid > 255) { printf("Adjusting %d to max 255 sec for ID\n",fid); fid = 255; } fsetid=1; break; case 'o': fcrit=0; fmaj=0; fmin=0; fpow=0; /* set all alarms off */ fsetdisk = 1; fdiska = 0; fdiskb = 0; fsetall=1; fsetled = 1; fsetid=1; fid=0; break; case 'x': fdebug = 1; break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: printf("Usage: %s [-abcdfimnoprx -NUPRETVFY]\n", progname); printf(" where -r means read-only\n"); printf(" -i5 sets Chassis ID on for 5 sec\n"); printf(" -i0 sets Chassis ID off\n"); printf(" -a1 sets Disk A Fault on\n"); printf(" -a0 sets Disk A Fault off\n"); printf(" -b1 sets Disk B Fault on\n"); printf(" -b0 sets Disk B Fault off\n"); printf(" -c1 sets Critical Alarm on\n"); printf(" -c0 sets Critical Alarm off\n"); printf(" -d31 sets Disk 3 Fault on (disks 0-6)\n"); printf(" -d30 sets Disk 3 Fault off\n"); printf(" -e skip disk Enclosure LEDs\n"); printf(" -f sets all Disk Fault LEDs off\n"); printf(" -m1 sets Major Alarm on\n"); printf(" -m0 sets Major Alarm off\n"); printf(" -n1 sets Minor Alarm on\n"); printf(" -n0 sets Minor Alarm off\n"); printf(" -p1 sets Power Alarm on\n"); printf(" -p0 sets Power Alarm off\n"); printf(" -o sets all Alarms off\n"); printf(" -w21b writes picmg LED 2 on(1) color=blue(b)\n"); printf(" -x show eXtra debug messages\n"); print_lan_opt_usage(0); ret = ERR_USAGE; goto do_exit; } /* * Check the Device ID to determine which bus id to use. */ ret = ipmi_getdeviceid(devrec,16,fdebug); if (ret != 0) { goto do_exit; } else { int j; if (fdebug) { printf("devid: "); for (j = 0; j < 16; j++) printf("%02x ",devrec[j]); printf("\n"); } ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; prod_id = devrec[9] + (devrec[10] << 8); vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16); printf("-- %s version %x.%x, IPMI version %d.%d \n", "BMC", devrec[2], devrec[3], ipmi_maj, ipmi_min); } #ifdef TEST_ENC fHasEnc = 1; fHasAlarms = 0; fbmctam = 0; fpicmg = 0; fRomley = 1; maxdisks = 8; #else ret = ipmi_getpicmg(devrec,16,fdebug); if (ret == 0) { fpicmg = 1; fHasAlarms = 1; } else ret = 0; /* ignore error if not picmg */ #if defined(METACOMMAND) || defined(ALONE) { uchar rgalarms[3]; uchar idstate; char *pmsg; switch(vend_id) { case VENDOR_NSC: /* for Intel TIGPT1U */ case VENDOR_INTEL: /* requires oem_intel.c */ /* check_prod_capab */ ret = detect_capab_intel(vend_id,prod_id,&flags,&maxdisks,fdebug); busid = (uchar)ret; if (fdebug) printf("prod_capab: busid=%x, flags=%02x\n",busid,flags); if ((flags & HAS_ALARMS_MASK) != 0) fHasAlarms = 1; if ((flags & HAS_BMCTAM_MASK) != 0) fbmctam = 1; if ((flags & HAS_ENCL_MASK) != 0) fHasEnc = 1; if ((flags & HAS_PICMG_MASK) != 0) fpicmg = 1; if ((flags & HAS_NSC_MASK) != 0) fNSC = 1; if ((flags & HAS_ROMLEY_MASK) != 0) fRomley = 1; if ((flags & HAS_GRANTLEY_MASK) != 0) fGrantley = 1; /* get ID LED status */ ret = get_led_status_intel(&idstate); if (ret == 0) { switch(idstate) { case 1: pmsg = "ON"; break; case 2: pmsg = "Blink"; break; default: pmsg = "off"; break; } printf("ID LED: %s\n",pmsg); } break; #ifdef METACOMMAND case VENDOR_KONTRON: if (prod_id == 1590) { fHasEnc = 1; maxdisks = 8; } break; case VENDOR_FUJITSU: printf("Getting Fujitsu alarm LEDs ...\n"); ret = get_alarms_fujitsu(rgalarms); if (fdebug) printf("get_alarms_fujitsu ret = %d\n",ret); /* if ret != 0, fall through and try default methods */ if (ret == 0) { show_alarms_fujitsu(rgalarms); if (fsetid) { printf("\nSetting fujitsu ID LED to %02x ...\n", fid); ret = set_alarms_fujitsu(0, (uchar)fid); printf("set_alarms_fujitsu ret = %d\n",ret); ret = get_alarms_fujitsu(rgalarms); if (ret == 0) show_alarms_fujitsu(rgalarms); } fHasAlarms = 0; /*skip the other LED functions*/ } break; case VENDOR_SUN: printf("Do get_alarms_sun() \n"); // TODO: add this /* ret = get_alarms_sun(); if (ret == 0) show_alarms_sun() if (fsetled) { printf("\nSetting sun(%d) alarm LED to %02x %c...\n", ledn,ledv,ledc); ret = set_alarms_sun(ledv,ledn,ledc); printf("set_alarms_sun ret = %d\n",ret); ret = get_alarms_sun(rgalarms,ledn); if (ret == 0) show_alarms_sun(rgalarms,ledn); } */ break; #endif default: break; } } #endif #endif if (fHasAlarms) { /* get the telco picmg or intel alarm LED states */ if (fpicmg) { for (i = 0; i < 5; i++) { ret = get_alarms_picmg(rgalarms,picmg_id,fru_id,(uchar)i); if (ret == 0) show_alarms_picmg(rgalarms,picmg_id,fru_id,(uchar)i); } } else { alarms = get_alarms_intel(busid); if (alarms == 0) { /* failed to get alarm panel data */ if (fHasAlarms) { /* baseboard which may have Telco alarm panel*/ printf("Could not obtain Telco LED states, Telco alarm panel " "may not be present.\n\n"); } fHasAlarms = 0; } else { /* have Telco alarm panel data */ ret = 0; show_alarms_intel(alarms); } } if (fsetled) { if (fpicmg) { printf("\nSetting picmg(%d,%d) alarm LED to %02x %c...\n", fru_id,ledn,ledv,ledc); ret = set_alarms_picmg(ledv,picmg_id,fru_id,ledn,ledc); printf("set_alarms_picmg ret = %d\n",ret); ret = get_alarms_picmg(rgalarms,picmg_id,fru_id,ledn); if (ret == 0) show_alarms_picmg(rgalarms,picmg_id,fru_id,ledn); } else { /* not picmg, set Intel Telco Alarm LEDs */ if (fbmctam) { /* Platform supports BMC Telco Alarms Manager */ ret = check_bmctam_intel(); } /*endif fbmctam*/ if (ret == LAN_ERR_ABORT) { printf("Conflict with BMC TAM - Skipping TAM LEDs.\n"); } else { if (fsetall) newvalue = 0xFF; /* alarms and relays */ else { newvalue = alarms; if (fcrit == 1) newvalue &= 0xFD; /*bit1 = 0*/ else if (fcrit == 0) newvalue |= 0xF2; if (fmaj == 1) newvalue &= 0xFB; /*bit2 = 0*/ else if (fmaj == 0) newvalue |= 0xF4; if (fmin == 1) newvalue &= 0xF7; /*bit3 = 0*/ else if (fmin == 0) newvalue |= 0xF8; if (fpow == 1) newvalue &= 0xFE; /*bit0 = 0*/ else if (fpow == 0) newvalue |= 0xF1; } printf("\nSetting alarms to %02x ...\n",newvalue); ret = set_alarms_intel(newvalue,busid); alarms = get_alarms_intel(busid); show_alarms_intel(alarms); } } /*end else Intel*/ } /*endif fsetled*/ } /*endif fHasAlarms*/ if (fsetid) { printf("Setting ID LED to %d ...\n\n",fid); ret = set_chassis_id((uchar)fid); } if (fHasEnc && fdoencl) { /* disk enclosure exists */ if (fRomley || fGrantley) { /* Romley (Patsburg) */ int rv; /*do not change ret*/ rv = get_enc_leds_intel(&encled); if (rv == 0) { show_enc_leds_intel(encled,maxdisks); if (fsetdisk) { /* Set fault if user param, and disk is present. */ if (fsetall) newvalue = 0x00; /* all LEDs off */ else if (fdiska == 10) newvalue = 0x00; else { newvalue = encled; if (fdiskb == 1) newvalue |= 0x02; else if (fdiskb == 0) newvalue &= 0xFD; if (fdiska == 1) newvalue |= 0x01; else if (fdiska == 0) newvalue &= 0xFE; if (fdiskn == 1) newvalue |= (0x01 << ndisk); else if (fdiskn == 0) newvalue &= ~(0x01 << ndisk); } printf("\nSetting Enclosure LEDs to %02x ...\n",newvalue); ret = set_enc_leds_intel(newvalue); ret = get_enc_leds_intel(&encled); show_enc_leds_intel(encled,maxdisks); } } } else { /* Vitesse disk Enclosure chipset */ ret = get_enc_leds(&encled); if (ret == 0) { show_enc_leds(encled); if (fsetdisk) { /* Set fault if user param, and disk is present. */ if (fsetall) newvalue = 0x00; /* all LEDs off */ else if (fdiska == 10) newvalue = 0x00; else { newvalue = encled; if (fdiskb == 1) newvalue |= 0x02; else if (fdiskb == 0) newvalue &= 0xFD; if (fdiska == 1) newvalue |= 0x01; else if (fdiska == 0) newvalue &= 0xFE; if (fdiskn == 1) newvalue |= (0x01 << ndisk); else if (fdiskn == 0) newvalue &= ~(0x01 << ndisk); } printf("\nSetting Enclosure LEDs to %02x ...\n",newvalue); ret = set_enc_leds(newvalue); ret = get_enc_leds(&encled); show_enc_leds(encled); } } } /*end-else Vitesse*/ } /*endif fHasEnc*/ else if (fNSC && fdoencl) { /*Chesnee NSC platform has special disk LEDs*/ diskled = get_nsc_diskleds(busid); show_nsc_diskleds(diskled); if (fsetdisk) { newvalue = diskled; // newvalue |= 0xFC; /*leave upper bits high (off) */ /* Set fault if user param, and disk is present. */ if (fdiskb == 1) newvalue &= 0xFE; /*bit0=0*/ else if (fdiskb == 0) newvalue |= 0x01; if (fdiska == 1) newvalue &= 0xFD; /*bit1=0*/ else if (fdiska == 0) newvalue |= 0x02; else if (fdiska == 10) newvalue = 0x00; printf("\nSetting Disk LEDs to %02x ...\n",newvalue); ret = set_nsc_diskleds(newvalue,busid); diskled = get_nsc_diskleds(busid); show_nsc_diskleds(diskled); } } do_exit: ipmi_close_(); // show_outcome(progname,ret); return (ret); } /* end main()*/ /* end ialarms.c */ ipmiutil-3.1.5/util/itsol.c0000644000076400007640000004631113566765324015736 0ustar mgportalloggers/* * Copyright (c) 2005 Tyan Computer Corp. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution 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. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #include #include #include #include #include #include #ifdef WIN32 #include #include #include #include #include "getopt.h" #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int typedef uint32_t socklen_t; #define inet_ntop InetNtop #define inet_pton InetPton int InetPton(int af, char *pstr, void *addr); /*see ws2_32.dll*/ char *InetNtop(int af, void *addr, char *pstr, int sz); char *InetNtop(int af, void *addr, char *pstr, int sz) { return NULL; }; int gettimeofday(struct timeval *tv, struct timezone *tz); #undef POLL_OK #else #include #include #include #include #include #include #include #include #include #include #if defined(HAVE_CONFIG_H) #include "config.h" #endif #if defined(HPUX) /* getopt is defined in stdio.h */ #undef POLL_OK #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #include #undef POLL_OK #else #include #include #define POLL_OK 1 #endif #if defined (HAVE_SYS_TERMIOS_H) #include #else // #if defined(HAVE_TERMIOS_H) #include #endif #endif #include "ipmicmd.h" #include "itsol.h" extern int verbose; extern char fdebug; /*from ipmicmd.c*/ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil tsol"; #else static char * progver = "3.08"; static char * progname = "itsol"; #endif static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static char hostname[SZGNODE]; static SockType sockfd = -1; static char sol_escape_char = '~'; static struct timeval _start_keepalive; static int _in_raw_mode = 0; static int _altterm = 0; static SOCKADDR_T haddr; static int haddrlen = 0; static int hauth, hpriv, hcipher; #ifdef WIN32 #define NI_MAXHOST 80 #define NI_MAXSERV 80 struct pollfd { int fd; short events; short revents; }; struct winsize { int x; int y; }; #else static struct termios _saved_tio; static struct winsize _saved_winsize; #endif static int ipmi_tsol_command(void * intf, char *recvip, int port, unsigned char cmd) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char data[6]; unsigned ip1, ip2, ip3, ip4; if (sscanf(recvip, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) != 4) { lprintf(LOG_ERR, "Invalid IP address: %s", recvip); return -1; } memset(&req, 0, sizeof(struct ipmi_rq)); req.msg.netfn = IPMI_NETFN_TSOL; req.msg.cmd = cmd; req.msg.data_len = 6; req.msg.data = data; memset(data, 0, sizeof(data)); data[0] = ip1; data[1] = ip2; data[2] = ip3; data[3] = ip4; data[4] = (port & 0xff00) >> 8; data[5] = (port & 0xff); rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { lprintf(LOG_ERR, "Unable to perform TSOL command"); return rv; } if (rv > 0) { lprintf(LOG_ERR, "Unable to perform TSOL command: %s", decode_cc(0,rv)); return -1; } return 0; } static int ipmi_tsol_start(void * intf, char *recvip, int port) { return ipmi_tsol_command(intf, recvip, port, IPMI_TSOL_CMD_START); } static int ipmi_tsol_stop(void * intf, char *recvip, int port) { return ipmi_tsol_command(intf, recvip, port, IPMI_TSOL_CMD_STOP); } static int ipmi_tsol_send_keystroke(void * intf, char *buff, int length) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char data[16]; static unsigned char keyseq = 0; memset(&req, 0, sizeof(struct ipmi_rq)); req.msg.netfn = IPMI_NETFN_TSOL; req.msg.cmd = IPMI_TSOL_CMD_SENDKEY; req.msg.data_len = length + 2; req.msg.data = data; memset(data, 0, sizeof(data)); data[0] = length + 1; memcpy(data + 1, buff, length); data[length + 1] = keyseq++; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (verbose) { if (rv < 0) { lprintf(LOG_ERR, "Unable to send keystroke"); return rv; } if (rv > 0) { lprintf(LOG_ERR, "Unable to send keystroke: %s", decode_cc(0,rv)); return -1; } } return length; } static int tsol_keepalive(void * intf) { struct timeval end; int rv; gettimeofday(&end, 0); if (end.tv_sec - _start_keepalive.tv_sec <= 30) return 0; // intf->keepalive(intf); rv = lan_keepalive(1); /*1=getdevid, 2=empty sol*/ gettimeofday(&_start_keepalive, 0); return rv; } static void print_escape_seq(void *intf) { lprintf(LOG_NOTICE, " %c. - terminate connection\r\n" " %c^Z - suspend ipmiutil\r\n" " %c^X - suspend ipmiutil, but don't restore tty on restart\r\n" " %c? - this message\r\n" " %c%c - send the escape character by typing it twice\r\n" " (Note that escapes are only recognized immediately after newline.)\r", sol_escape_char, sol_escape_char, sol_escape_char, sol_escape_char, sol_escape_char, sol_escape_char); } #ifdef WIN32 static int leave_raw_mode(void) { return(0); } static int enter_raw_mode(void) { return(0); } static void set_terminal_size(int rows, int cols) { return; } static void do_terminal_cleanup(void) { int err; err = get_LastError(); lprintf(LOG_ERR, "Exiting due to error %d", err); show_LastError("",err); } static void suspend_self(int restore_tty) { return; } #else static int leave_raw_mode(void) { if (!_in_raw_mode) return -1; else if (tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio) == -1) lperror(LOG_ERR, "tcsetattr(stdin)"); else if (tcsetattr(fileno(stdout), TCSADRAIN, &_saved_tio) == -1) lperror(LOG_ERR, "tcsetattr(stdout)"); else _in_raw_mode = 0; return 0; } static int enter_raw_mode(void) { struct termios tio; if (tcgetattr(fileno(stdout), &_saved_tio) < 0) { lperror(LOG_ERR, "tcgetattr failed"); return -1; } tio = _saved_tio; if (_altterm) { tio.c_iflag &= (ISTRIP | IGNBRK ); tio.c_cflag &= ~(CSIZE | PARENB | IXON | IXOFF | IXANY); tio.c_cflag |= (CS8 |CREAD) | (IXON|IXOFF|IXANY); tio.c_lflag &= 0; tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; } else { tio.c_iflag |= IGNPAR; tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL | IEXTEN); tio.c_oflag &= ~OPOST; tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; } if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) < 0) lperror(LOG_ERR, "tcsetattr(stdin)"); else if (tcsetattr(fileno(stdout), TCSADRAIN, &tio) < 0) lperror(LOG_ERR, "tcsetattr(stdout)"); else _in_raw_mode = 1; return 0; } static void do_terminal_cleanup(void) { if (_saved_winsize.ws_row > 0 && _saved_winsize.ws_col > 0) ioctl(fileno(stdout), TIOCSWINSZ, &_saved_winsize); leave_raw_mode(); if (errno) lprintf(LOG_ERR, "Exiting due to error %d -> %s", errno, strerror(errno)); } static void set_terminal_size(int rows, int cols) { struct winsize winsize; if (rows <= 0 || cols <= 0) return; /* save initial winsize */ ioctl(fileno(stdout), TIOCGWINSZ, &_saved_winsize); /* set new winsize */ winsize.ws_row = rows; winsize.ws_col = cols; ioctl(fileno(stdout), TIOCSWINSZ, &winsize); } static void suspend_self(int restore_tty) { leave_raw_mode(); kill(getpid(), SIGTSTP); if (restore_tty) enter_raw_mode(); } #endif static int do_inbuf_actions(void *intf, char *in_buff, int len) { static int in_esc = 0; static int last_was_cr = 1; int i; for(i = 0; i < len ;) { if (!in_esc) { if (last_was_cr && (in_buff[i] == sol_escape_char)) { in_esc = 1; memmove(in_buff, in_buff + 1, len - i - 1); len--; continue; } } if (in_esc) { if (in_buff[i] == sol_escape_char) { in_esc = 0; i++; continue; } switch (in_buff[i]) { case '.': printf("%c. [terminated ipmiutil]\r\n", sol_escape_char); return -1; case 'Z' - 64: printf("%c^Z [suspend ipmiutil]\r\n", sol_escape_char); suspend_self(1); /* Restore tty back to raw */ break; case 'X' - 64: printf("%c^X [suspend ipmiutil]\r\n", sol_escape_char); suspend_self(0); /* Don't restore to raw mode */ break; case '?': printf("%c? [ipmiutil help]\r\n", sol_escape_char); print_escape_seq(intf); break; } memmove(in_buff, in_buff + 1, len - i - 1); len--; in_esc = 0; continue; } last_was_cr = (in_buff[i] == '\r' || in_buff[i] == '\n'); i++; } return len; } static void print_tsol_usage(void) { lprintf(LOG_NOTICE, "Usage: tsol [recvip] [port=NUM] [ro|rw] [rows=NUM] [cols=NUM] [altterm]"); lprintf(LOG_NOTICE, " recvip Receiver IP Address [default=local]"); lprintf(LOG_NOTICE, " port=NUM Receiver UDP Port [default=%d]", IPMI_TSOL_DEF_PORT); lprintf(LOG_NOTICE, " ro|rw Set Read-Only or Read-Write [default=rw]"); #ifdef POLL_OK { struct winsize winsize; ioctl(fileno(stdout), TIOCGWINSZ, &winsize); lprintf(LOG_NOTICE, " rows=NUM Set terminal rows [default=%d]", winsize.ws_row); lprintf(LOG_NOTICE, " cols=NUM Set terminal columns [default=%d]", winsize.ws_col); } #endif lprintf(LOG_NOTICE, " altterm Alternate terminal setup [default=off]"); } int ipmi_tsol_main(void * intf, int argc, char ** argv) { char *recvip = NULL; int result, i; int ip1, ip2, ip3, ip4; int read_only = 0, rows = 0, cols = 0; int port = IPMI_TSOL_DEF_PORT; #ifdef POLL_OK SOCKADDR_T sin, myaddr; socklen_t mylen; struct pollfd fds_wait[3], fds_data_wait[3], *fds; int fd_socket; int out_buff_fill, in_buff_fill; char out_buff[IPMI_BUF_SIZE * 8], in_buff[IPMI_BUF_SIZE]; char buff[IPMI_BUF_SIZE + 4]; char mystr[NI_MAXHOST]; #endif if (! is_remote()) { lprintf(LOG_ERR, "Error: Tyan SOL is only available over lan interface"); return -1; } for (i = 0; isa_family, &myaddr, mystr, sizeof(mystr)-1); if (recvip == NULL) { lprintf(LOG_ERR, "Unable to find local IP address"); return -1; } } printf("[Starting %sSOL with receiving address %s:%d]\r\n", read_only ? "Read-only " : "", recvip, port); set_terminal_size(rows, cols); enter_raw_mode(); /* * talk to smdc to start Console redirect - IP address and port as parameter * ipmiutil -I lan -H 192.168.168.227 -U Administrator raw 0x30 0x06 0xC0 0xA8 0xA8 0x78 0x1A 0x0A */ result = ipmi_tsol_start(intf, recvip, port); if (result < 0) { leave_raw_mode(); lprintf(LOG_ERR, "Error starting SOL"); return -1; } printf("[SOL Session operational. Use %c? for help]\r\n", sol_escape_char); gettimeofday(&_start_keepalive, 0); fd_socket = sockfd; fds_wait[0].fd = fd_socket; fds_wait[0].events = POLLIN; fds_wait[0].revents = 0; fds_wait[1].fd = fileno(stdin); fds_wait[1].events = POLLIN; fds_wait[1].revents = 0; fds_wait[2].fd = -1; fds_wait[2].events = 0; fds_wait[2].revents = 0; fds_data_wait[0].fd = fd_socket; fds_data_wait[0].events = POLLIN | POLLOUT; fds_data_wait[0].revents = 0; fds_data_wait[1].fd = fileno(stdin); fds_data_wait[1].events = POLLIN; fds_data_wait[1].revents = 0; fds_data_wait[2].fd = fileno(stdout); fds_data_wait[2].events = POLLOUT; fds_data_wait[2].revents = 0; out_buff_fill = 0; in_buff_fill = 0; fds = fds_wait; for (;;) { result = poll(fds, 3, 15*1000); if (result < 0) break; /* send keepalive packet */ tsol_keepalive(intf); if ((fds[0].revents & POLLIN) && (sizeof(out_buff) > out_buff_fill)){ socklen_t sin_len = sizeof(sin); result = recvfrom(fd_socket, buff, sizeof(out_buff) - out_buff_fill + 4, 0, (struct sockaddr *)&sin, &sin_len); /* read the data from udp socket, skip some bytes in the head */ if((result - 4) > 0 ){ int length = result - 4; #if 1 length = (unsigned char)buff[2] & 0xff; length *= 256; length += ((unsigned char)buff[3] & 0xff); if ((length <= 0) || (length > (result - 4))) length = result - 4; #endif memcpy(out_buff + out_buff_fill, buff + 4, length); out_buff_fill += length; } } if ((fds[1].revents & POLLIN) && (sizeof(in_buff) > in_buff_fill)) { result = read(fileno(stdin), in_buff + in_buff_fill, sizeof(in_buff) - in_buff_fill); // read from keyboard if (result > 0) { int bytes; bytes = do_inbuf_actions(intf, in_buff + in_buff_fill, result); if(bytes < 0) { result = ipmi_tsol_stop(intf, recvip, port); do_terminal_cleanup(); return result; } if (read_only) bytes = 0; in_buff_fill += bytes; } } if ((fds[2].revents & POLLOUT) && out_buff_fill) { result = write(fileno(stdout), out_buff, out_buff_fill); // to screen if (result > 0) { out_buff_fill -= result; if (out_buff_fill) { memmove(out_buff, out_buff + result, out_buff_fill); } } } if ((fds[0].revents & POLLOUT) && in_buff_fill) { /* * translate key and send that to SMDC using IPMI * ipmiutil cmd -N 192.168.168.227 -U Administrator 0x30 0x03 0x04 0x1B 0x5B 0x43 */ result = ipmi_tsol_send_keystroke(intf, in_buff, MIN(in_buff_fill,14)); if (result > 0) { gettimeofday(&_start_keepalive, 0); in_buff_fill -= result; if (in_buff_fill) { memmove(in_buff, in_buff + result, in_buff_fill); } } } fds = (in_buff_fill || out_buff_fill )? fds_data_wait : fds_wait; } #endif return 0; } #ifdef METACOMMAND int i_tsol(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { void *intf = NULL; int rc = 0; int c, i; char *s1; printf("%s ver %s\n", progname,progver); set_loglevel(LOG_NOTICE); while ( (c = getopt( argc, argv,"m:T:V:J:EYF:P:N:R:U:Z:x?")) != EOF ) switch (c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'x': fdebug = 1; verbose = 1; set_loglevel(LOG_DEBUG); break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; case '?': print_tsol_usage(); return ERR_USAGE; break; } for (i = 0; i < optind; i++) { argv++; argc--; } rc = ipmi_tsol_main(intf, argc, argv); ipmi_close_(); // show_outcome(progname,rc); return rc; } /* end itsol.c */ ipmiutil-3.1.5/util/Makefile.am0000644000076400007640000002164313566765324016475 0ustar mgportalloggers localedir = $(datadir)/locale OS_CF = @OS_CFLAGS@ @CROSS_CFLAGS@ OS_LF = @OS_LFLAGS@ @CROSS_LFLAGS@ AM_CPPFLAGS = $(OS_CF) -DLOCALEDIR=\"$(localedir)\" -I.. AM_CPPFLAGS += @IA64_CFLAGS@ @GPL_CFLAGS@ LDADD = $(OS_LF) # usu LD_SAMX = ../lib/libipmi_lanplus.a -lcrypto LDSAM = $(OS_LF) @LD_SAMX@ CFLAGS_SAMX = -O2 -g -I. -I.. $(OS_CF) @LANPLUS_CFLAGS@ CFLAGS_SAM = -O2 -g -I. -I.. $(OS_CF) # May be /usr/bin/install or /bin/install INSTALLBIN = install -c extradir = $(datadir)/ipmiutil inc_dir = $(includedir) tmpobj = obj tmpwin = tmp LIBDIR = @LIB_DIR@ CMDMOD = ipmicmd.c mem_if.c ipmidir.c imbapi.c ipmimv.c ipmild.c ipmibmc.c ipmilipmi.c subs.c CMDMOD += md5.c md2.c ipmilan.c CMDMOD += ipmilanplus.c # CMDMOD = ipmicmd.c mem_if.c @OS_DRIVERS@ # am: configure substitutions are not allowed in _SOURCES variables TMPOBJL = $(tmpobj)/ipmilanL.o $(tmpobj)/ipmilanplusL.o TMPOBJA = $(tmpobj)/ipmilanA.o $(tmpobj)/ipmilanplusA.o LIBOBJ = ipmicmd.o mem_if.o ipmidir.o imbapi.o ipmimv.o ipmild.o ipmibmc.o ipmilipmi.o subs.o md5.o md2.o @LIBSENSORS@ OEMMOD = oem_kontron.c oem_fujitsu.c oem_intel.c oem_sun.c oem_supermicro.c oem_dell.c oem_quanta.c oem_hp.c oem_newisys.c oem_lenovo.c oem_asus.c iekanalyzer.c # usu SAM2OBJ = isensor2.o ievents2.o L2OBJ = @SAM2OBJ@ # To build ipmiutil, need to use METACFLAGS for each .c/.o AM_CPPFLAGS += -I. -I.. -DMETACOMMAND METASOURCE = ipmiutil.c ialarms.c ihealth.c ievents.c ifru.c ifru_picmg.c igetevent.c ireset.c icmd.c ilan.c isensor.c isel.c iserial.c iwdt.c isol.c idiscover.c iconfig.c ipicmg.c ifirewall.c ifwum.c ihpm.c itsol.c idcmi.c iuser.c $(OEMMOD) $(CMDMOD) LDADD += -lpthread # The LanDesk library is proprietary, so it is incompatible with ALLOW_GPL. # To build with LanDesk support: # First copy the library to ../lib/libipmiapi.a # Then ./configure --enable-landesk # Result: # AM_CPPFLAGS += -DLINK_LANDESK # LDADD += -lipmiapi -L../lib AM_CPPFLAGS += @LANDESK_CFLAGS@ LDADD += @LANDESK_LDADD@ # For lanplus plugin support (IPMI LAN 2.0 RMCP+) used by SOL: # If ./configure --disable-lanplus # AM_CPPFLAGS += # LDADD += # Otherwise default result is lanplus enabled: # AM_CPPFLAGS += -DHAVE_LANPLUS # LDADD += -L../lib -lipmi_lanplus -L/usr/local/lib -lcrypto # LDADD += -L../lib -lintf_lanplus -L/usr/local/lib -lcrypto (older) # Could also use CMDMOD += ipmilan2.c instead, if completed. AM_CPPFLAGS += @LANPLUS_CFLAGS@ LDADD += @LANPLUS_LIB@ @LANPLUS_CRYPTO@ LANPLUS_OBJ = $(shell ar t @LANPLUS_LIB@ 2>/dev/null) # sbin_PROGRAMS are built by default and copied to /usr/sbin at install time # EXTRA_PROGRAMS are built by default but not included in the install package # TESTPROGS are not built by default. To build, do 'make ifruset', for example. bin_PROGRAMS = ipmiutil ievents idiscover sbin_PROGRAMS = ipmi_port iseltime DEV_LIB = libipmiutil.a # SHRLINK is libipmiutil.so.1 if OS supports it SHRLINK = @SHR_LINK@ SHR_LIB = $(SHRLINK) SHR_BLIB = libipmiutil.so LDNAME = -Wl,-soname,$(SHR_LIB) EXTRA_PROGRAMS = ipmi_sample ipmi_sample_evt TESTPROGS = libimbapi.a iconfig ipmimv ifruset ipmi_sample2 ialarms_enc # OLDPROGS are old/previous binaries that may exist and need to be deleted. OLDPROGS = alarms bmchealth fruconfig getevent hwreset icmd isolconsole pefconfig sensor showsel tmconfig wdt # To build an imb api library (libimbapi.a): libimbapi.a: imbapi.c mkdir -p $(tmpobj) $(CC) -I. -I.. $(OS_CF) -fPIC $(CFLAGS) -o $(tmpobj)/imbapi.o -c imbapi.c $(AR) cru libimbapi.a $(tmpobj)/imbapi.o $(RANLIB) libimbapi.a rm -f $(tmpobj)/imbapi.o $(tmpobj)/ipmilanplusL.o: ipmilanplus.c mkdir -p $(tmpobj) $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilanplusL.o -c ipmilanplus.c; $(tmpobj)/ipmilanL.o: ipmilan.c mkdir -p $(tmpobj) $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilanL.o -c ipmilan.c; $(tmpobj)/ipmilanplusA.o: ipmilanplus.c mkdir -p $(tmpobj) $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilanplusA.o -c ipmilanplus.c; $(tmpobj)/ipmilanA.o: ipmilan.c mkdir -p $(tmpobj) $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilanA.o -c ipmilan.c; # Build a lib to support all of the IPMI drivers (libipmiutil.a) # If LANPLUS_SAM = yes, include LANPLUS_OBJ, else do not. # See configure --enable-liblanplus to change this $(DEV_LIB): $(CMDMOD:.c=.o) @LANPLUS_LIB@ @LIBSENSORS@ $(TMPOBJL) $(TMPOBJA) if [ "x@LANPLUS_SAM@" = "xyes" ]; then \ ar x @LANPLUS_LIB@ ; \ $(AR) cru $(DEV_LIB) $(LIBOBJ) $(TMPOBJL) $(LANPLUS_OBJ); \ $(RANLIB) $(DEV_LIB); \ else \ $(AR) cru $(DEV_LIB) $(LIBOBJ) $(TMPOBJA) ; \ $(RANLIB) $(DEV_LIB) ; \ fi $(SHR_LIB): $(CMDMOD:.c=.o) @LANPLUS_LIB@ @LIBSENSORS@ $(TMPOBJL) $(TMPOBJA) if [ "x@LANPLUS_SAM@" = "xyes" ]; then \ ar x @LANPLUS_LIB@ ; \ $(CC) $(LDFLAGS) -shared $(LDNAME) -o $(SHR_LIB) $(LIBOBJ) $(TMPOBJL) $(LANPLUS_OBJ); \ else \ $(CC) $(LDFLAGS) -shared $(LDNAME) -o $(SHR_LIB) $(LIBOBJ) $(TMPOBJA) ; \ fi $(SHR_BLIB): $(SHR_LIB) ln -s $(SHR_LIB) $(SHR_BLIB) idiscover$(EXEEXT): idiscover.c $(CC) $(CFLAGS_SAM) $(LDFLAGS) $(OS_LF) -o idiscover idiscover.c ipmimv$(EXEEXT): ipmimv.c $(CC) $(CFLAGS_SAM) $(LDFLAGS) -DTEST_BIN -o ipmimv ipmimv.c ievents$(EXEEXT): ievents.c $(CC) $(CFLAGS_SAM) $(LDFLAGS) -DALONE -o ievents ievents.c isensor2.o: isensor.c $(CC) $(CFLAGS_SAM) -o isensor2.o -c isensor.c ievents2.o: ievents.c $(CC) $(CFLAGS_SAM) -DSENSORS_OK -o ievents2.o -c ievents.c ifru_picmg2.o: ifru_picmg.c $(CC) $(CFLAGS_SAM) -o ifru_picmg2.o -c ifru_picmg.c ifru2.o: ifru.c $(CC) $(CFLAGS_SAM) -o ifru2.o -c ifru.c isel2.o: isel.c $(CC) $(CFLAGS_SAM) -o isel2.o -c isel.c ipmi_sample.o: ipmi_sample.c $(CC) $(CFLAGS_SAM) -c ipmi_sample.c ipmi_sample2.o: ipmi_sample.c $(CC) $(CFLAGS_SAM) -D GET_SENSORS -D GET_FRU -o ipmi_sample2.o -c ipmi_sample.c ipmi_sample_evt.o: ipmi_sample_evt.c $(CC) $(CFLAGS_SAM) -o ipmi_sample_evt.o -c ipmi_sample_evt.c ipmi_sample$(EXEEXT): $(DEV_LIB) ipmi_sample.o isensor.o ievents.o $(CC) -g -O2 -o ipmi_sample ipmi_sample.o $(DEV_LIB) $(LDFLAGS) $(LDSAM) # To build ipmi_sample with GET_SENSORS enabled, need isensors.o, ievents.o # Note that this does not include oem_intel, etc. for OEM SEL decoding. ipmi_sample2$(EXEEXT): $(DEV_LIB) ipmi_sample2.o ifru2.o isel2.o ifru_picmg2.o $(L2OBJ) $(CC) -g -O2 -o ipmi_sample2 ipmi_sample2.o $(L2OBJ) ifru2.o ifru_picmg2.o isel2.o $(DEV_LIB) $(LDFLAGS) $(LDSAM) ipmi_sample_evt$(EXEEXT): $(DEV_LIB) ipmi_sample_evt.o $(L2OBJ) $(CC) -g -O2 -o ipmi_sample_evt ipmi_sample_evt.o $(L2OBJ) $(DEV_LIB) $(LDFLAGS) $(LDSAM) ialarms2.o: ialarms.c $(CC) $(CFLAGS_SAM) -DTEST_ENC -o ialarms2.o -c ialarms.c oem_intel2.o: oem_intel.c $(CC) $(CFLAGS_SAM) -DNO_EVENTS -o oem_intel2.o -c oem_intel.c ialarms_enc$(EXEEXT): $(DEV_LIB) ialarms2.o oem_intel2.o $(CC) -g -O2 -o ialarms_enc ialarms2.o oem_intel2.o $(DEV_LIB) $(LDFLAGS) $(LDSAM) ifruset.o: ifruset.c $(CC) $(CFLAGS_SAM) -c ifruset.c ifruset$(EXEEXT): $(DEV_LIB) ifruset.o ifru_picmg2.o $(CC) -g -O2 -o ifruset ifruset.o ifru_picmg2.o $(DEV_LIB) $(LDFLAGS) $(LDADD) iseltime.o: iseltime.c $(CC) $(CFLAGS_SAM) -c iseltime.c iseltime$(EXEEXT): $(DEV_LIB) iseltime.o $(CC) -g -O2 -o iseltime iseltime.o $(DEV_LIB) $(LDFLAGS) $(LDADD) iconfig$(EXEEXT): iconfig.c $(DEV_LIB) $(CC) $(CFLAGS_SAM) $(LDFLAGS) -o iconfig iconfig.c $(DEV_LIB) @LANPLUS_CRYPTO@ ipmi_port$(EXEEXT): ipmi_port.c $(CC) $(CFLAGS_SAM) $(LDFLAGS) -o ipmi_port ipmi_port.c # @LANPLUS_LIB@ is ../lib/libipmi_lanplus.a ../lib/libipmi_lanplus.a: cd ../lib; make ipmiutil_SOURCES = $(METASOURCE) ipmiutil$(EXEEXT): $(METASOURCE:.c=.o) @LANPLUS_LIB@ $(CC) $(CFLAGS) $(LDFLAGS) -o ipmiutil $(METASOURCE:.c=.o) $(LDADD) ievents_SOURCES = ievents.c idiscover_SOURCES = idiscover.c ipmi_port_SOURCES = ipmi_port.c EXTRA_DIST = imb_api.h ipmicmd.h ipmidir.h ipmilan.h ipmilanplus.h AnsiTerm.h ifirewall.h ifwum.h ihpm.h ipicmg.h ipmiutil.h md2.h oem_dell.h oem_fujitsu.h oem_intel.h oem_kontron.h oem_sun.h idcmi.h isensor.h iekanalyzer.h all-am: Makefile $(bin_PROGRAMS) $(sbin_PROGRAMS) $(EXTRA_PROGRAMS) $(DEV_LIB) $(SHRLINK) install-data-am: $(EXTRA_PROGRAMS) $(DEV_LIB) $(SHRLINK) @INS_LIB@ mkdir -p $(DESTDIR)$(extradir) @INS_LIB@ mkdir -p $(DESTDIR)$(LIBDIR) @INS_LIB@ mkdir -p $(DESTDIR)$(inc_dir) @INS_LIB@ cp -f ipmi_sample.c $(DESTDIR)$(extradir) @INS_LIB@ cp -f ipmi_sample_evt.c $(DESTDIR)$(extradir) @INS_LIB@ cp -f ipmicmd.h $(DESTDIR)$(inc_dir) @INS_LIB@ cp -f isensor.c ievents.c $(DESTDIR)$(extradir) @INS_LIB@ cp -f isensor.h ievents.h $(DESTDIR)$(extradir) @INS_LIB@ cp -f Makefile.sample $(DESTDIR)$(extradir)/Makefile @INS_LIB@ cp -f $(DEV_LIB) $(DESTDIR)$(LIBDIR) @INS_LIB@ if [ "x$(SHRLINK)" != "x" ]; then \ @INS_LIB@ cp -f $(SHRLINK) $(DESTDIR)$(LIBDIR) ; \ @INS_LIB@ cd $(DESTDIR); ln -sf $(LIBDIR)/$(SHRLINK) $(DESTDIR)$(LIBDIR)/$(SHR_BLIB); \ @INS_LIB@ fi clean-generic: rm -f $(DEV_LIB) $(EXTRA_PROGRAMS) $(OLDPROGS) $(TESTPROGS) $(SHRLINK) if [ -d $(tmpobj) ]; then rm -rf $(tmpobj) ; fi if [ -d $(tmpwin) ]; then rm -rf $(tmpwin) ; fi rm -f *.log *.tmp debug*.list *.o *.pdb *.lo *.la *.so ipmiutil-3.1.5/util/isensor.h0000644000076400007640000001100713566765324016265 0ustar mgportalloggers/* * isensor.h * common routines from isensor.c */ #define SDR_SZ 80 /*max SDR size*/ typedef struct { ushort recid; uchar sdrver; /*usu. 0x51 = v1.5*/ uchar rectype; /* 01, 02, 11, 12, c0 */ uchar reclen; uchar sens_ownid; uchar sens_ownlun; uchar sens_num; /*sdr[7]*/ uchar entity_id; uchar entity_inst; uchar sens_init; uchar sens_capab; uchar sens_type; /*sdr[12]*/ uchar ev_type; /*sdr[13]*/ uchar data1[6]; /*masks*/ uchar sens_units; /*sdr[20]*/ uchar sens_base; uchar sens_mod; uchar linear; uchar m; uchar m_t; uchar b; uchar b_a; uchar a_ax; uchar rx_bx; uchar flags; uchar nom_reading; uchar norm_max; uchar norm_min; uchar sens_max_reading; uchar sens_min_reading; uchar unr_threshold; uchar ucr_threshold; uchar unc_threshold; uchar lnr_threshold; uchar lcr_threshold; uchar lnc_threshold; uchar pos_hysteresis; uchar neg_hysteresis; uchar data3[3]; uchar id_strlen; uchar id_string[16]; } SDR01REC; typedef struct { ushort recid; uchar sdrver; /*usu. 0x51 = v1.5*/ uchar rectype; /* 01, 02, 11, 12, c0 */ uchar reclen; uchar sens_ownid; uchar sens_ownlun; uchar sens_num; uchar entity_id; uchar entity_inst; uchar sens_init; uchar sens_capab; uchar sens_type; uchar ev_type; uchar data1[6]; uchar sens_units; uchar sens_base; uchar sens_mod; uchar shar_cnt; uchar shar_off; uchar pos_hysteresis; uchar neg_hysteresis; uchar data2[4]; uchar id_strlen; uchar id_string[16]; } SDR02REC; typedef struct { /* 0x08 = Entity Association record */ ushort recid; uchar sdrver; /*usu. 0x51 = v1.5*/ uchar rectype; /* 01, 02, 11, 12, c0 */ uchar reclen; uchar contid; uchar continst; uchar flags; uchar edata[8]; } SDR08REC; typedef struct { /*0x14 = BMC Message Channel Info record */ ushort recid; uchar sdrver; /*usu. 0x51 = v1.5*/ uchar rectype; /* 01, 02, 11, 12, c0 */ uchar reclen; uchar mdata[8]; uchar mint; uchar eint; uchar rsvd; } SDR14REC; typedef struct { /*0x11 = FRU Locator*/ ushort recid; uchar sdrver; /*usu. 0x51 = v1.5*/ uchar rectype; /* 01, 02, 11, 12, c0 */ uchar reclen; uchar dev_access_adr; /*usu sa*/ uchar dev_slave_adr; /*usu fru_id*/ uchar access_lun; uchar chan_num; uchar reserved; uchar dev_type; uchar dev_typemod; uchar entity_id; uchar entity_inst; uchar oem; uchar id_strlen; uchar id_string[16]; } SDR11REC; typedef struct { /*0x12 = IPMB Locator, for MCs*/ ushort recid; uchar sdrver; /*usu. 0x51 = v1.5*/ uchar rectype; /* 01, 02, 11, 12, c0 */ uchar reclen; uchar dev_slave_adr; uchar chan_num; uchar power_state; uchar dev_capab; uchar reserved[3]; uchar entity_id; uchar entity_inst; uchar oem; uchar id_strlen; uchar id_string[16]; } SDR12REC; typedef struct { /*0xc0 = OEM Record*/ ushort recid; uchar sdrver; /*usu. 0x51 = v1.5*/ uchar rectype; /* 01, 02, 11, 12, c0 */ uchar reclen; uchar manuf_id[3]; /*Intel = 0x57,0x01,0x00 = 343.*/ uchar oem_data[60]; /* (reclen-3 bytes)*/ } SDRc0REC; int get_sdr_cache(uchar **pcache); void free_sdr_cache(uchar *pcache); int get_sdr_file(char *sdrfile, uchar **sdrlist); int find_nsdrs(uchar *pcache); int find_sdr_next(uchar *psdr, uchar *pcache, ushort id); int find_sdr_by_snum(uchar *psdr, uchar *pcache, uchar snum, uchar sa); int find_sdr_by_tag(uchar *psdr, uchar *pcache, char *tag, uchar dbg); int find_sdr_by_id(uchar *psdr, uchar *pcache, ushort id); void ShowSDR(char *tag, uchar *sdr); int GetSDRRepositoryInfo(int *nret, int *fdev); int GetSensorThresholds(uchar sens_num, uchar *data); int GetSensorReading(uchar sens_num, void *psdr, uchar *sens_data); int GetSensorReadingFactors(uchar snum, uchar raw, int *m, int *b, int * b_exp, int *r, int *a); double RawToFloat(uchar raw, uchar *psdr); char *decode_entity_id(int id); char *get_unit_type(int iunits, int ibase, int imod, int fshort); /* * 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. * * reading1 = sens_reading[2], reading2 = sens_reading[3] */ int decode_comp_reading(uchar type, uchar evtype, uchar num, uchar reading1, uchar reading2); /* end isensor.h */ ipmiutil-3.1.5/util/ifru.c0000664000076400007640000021360313566765324015553 0ustar mgportalloggers/* * ifru (was fruconfig.c) * * This tool reads the FRU configuration, and optionally sets the asset * tag field in the FRU data. See IPMI v1.5 spec section 28. * It can use either the Intel /dev/imb driver or VALinux /dev/ipmikcs. * * Author: Andy Cress arcress at users.sourceforge.net * * Copyright (c) 2009 Kontron America, Inc. * * 10/28/02 Andy Cress - created * 12/11/02 Andy Cress v0.9 - disable write until checksum fixed. * 12/13/02 Andy Cress v0.91 - don't abort if cc=c9 in load_fru loop. * 01/27/03 Andy Cress v0.92 - more debug, do checksums, * 01/28/03 Andy Cress v1.0 do writes in small chunks, tested w SCB2 & STL2 * 02/19/03 Andy Cress v1.1 also get System GUID * 03/10/03 Andy Cress v1.2 do better bounds checking on FRU size * 04/30/03 Andy Cress v1.3 Board Part# & Serial# reversed * 05/13/03 Andy Cress v1.4 Added Chassis fields * 06/19/03 Andy Cress v1.5 added errno.h (email from Travers Carter) * 05/03/04 Andy Cress v1.6 BladeCenter has no product area, only board area * 05/05/04 Andy Cress v1.7 call ipmi_close before exit, * added WIN32 compile options. * 11/01/04 Andy Cress v1.8 add -N / -R for remote nodes * 12/10/04 Andy Cress v1.9 add gnu freeipmi interface * 01/13/05 Andy Cress v1.10 add logic to scan SDRs for all FRU devices, * and interpret them * 01/17/05 Andy Cress v1.11 decode SPD Manufacturer * 01/21/05 Andy Cress v1.12 format SystemGUID display * 02/03/05 Andy Cress v1.13 fixed fwords bit mask in load_fru, * decode DIMM size from SPD also. * 02/04/05 Andy Cress v1.14 decode FRU Board Mfg DateTime * 03/16/05 Andy Cress v1.15 show Asset Tag Length earlier * 05/24/05 Andy Cress v1.16 only do write_asset if successful show_fru * 06/20/05 Andy Cress v1.17 handle Device SDRs also for ATCA * 08/22/05 Andy Cress v1.18 allow setting Product Serial Number also (-s), * also add -b option to show only baseboard data. * 10/31/06 Andy Cress v1.25 handle 1-char asset/serial strings (avoid c1) */ /*M* 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 Kontron 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*/ #ifdef WIN32 #include #include #include #include #include "getopt.h" #elif defined(DOS) #include #include #include #include #include "getopt.h" #else #include #include #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include #include "ipmicmd.h" #include "ipicmg.h" #include "oem_intel.h" #include "ifru.h" #define PICMG_CHILD 1 #define MIN_SDR_SZ 8 #ifndef URNLOOPS #define URNLOOPS 1000 #endif extern int get_BiosVersion(char *str); extern int get_SystemGuid(uchar *guid); extern void fmt_time(time_t etime, char *buf, int bufsz); /*see ievents.c*/ extern int get_LastError( void ); /* ipmilan.c */ extern int GetSDRRepositoryInfo(int *nret, int *fdev); /*isensor.h*/ #ifdef METACOMMAND extern int ipmi_kontronoem_main(void * intf, int argc, char ** argv); extern char *progver; /*from ipmiutil.c*/ static char *progname = "ipmiutil fru"; #else static char *progver = "3.11"; static char *progname = "ifru"; #endif static int vend_id = 0; static int prod_id = 0; static char fdebug = 0; static char fpicmg = 0; static char fonlybase = 0; static char fonlyhsc = 0; static int fwritefru = 0; static int fdevsdrs = 0; static char fshowlen = 0; static char ftestshow = 0; // static char fgetfru = 0; static char fdoanyway = 0; static char fprivset = 0; static char fset_mc = 0; static char fcanonical = 0; static char foemkontron = 0; static char fbasefru = 1; static char fdump = 0; static char frestore = 0; static char fchild = 0; /* =1 follow child MCs if picmg bladed*/ static char do_systeminfo = 1; static char do_guid = 1; static char bdelim = ':'; static uchar bmc_sa = BMC_SA; /*defaults to 0x20*/ static uchar guid[17] = ""; static char *binfile = NULL; static uchar *frubuf = NULL; #define FIELD_LEN 20 #define SZ_PRODAREA 520 /* product area max is 8*32 + 3 = 259 mod 8 = 264 */ static int sfru = 0; static int asset_offset = -1; static int asset_len = 0; static int sernum_offset = -1; static int sernum_len = 0; static int prodver_offset = -1; static int prodver_len = 0; static int chassis_offset = -1; static int chassis_len = 0; static char asset_tag[FIELD_LEN] = {0}; static char serial_num[FIELD_LEN] = {0}; static char prod_ver[FIELD_LEN] = {0}; static char chassis_name[FIELD_LEN] = {0}; static char ps_prod[FIELD_LEN] = {0}; static int maxprod = 0; static int ctype; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = 0; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static uchar g_fruid = 0; /* default to fruid 0 */ static uchar g_frutype = 0; static uchar lastfru[3] = {0,0,0}; /* g_frutype values (detected), see also FruTypeString * --TAG---- FRU IPMB * Baseboard = 0x0c 0x07 * PowerSply = 0x0a * PowerCage = 0x15 * DIMM = 0x20 * HotSwapCt = 0x0f * ME = 0x2e * SysInfo = 0x40 * Component = * * (all others) */ #ifdef METACOMMAND extern int verbose; extern int sdr_get_reservation(uchar *res_id, int fdev); #else static int verbose; static int sdr_get_reservation(uchar *res_id, int fdev) { return(-1); } #endif #define ERR_LENMAX -7 /*same as LAN_ERR_BADLENGTH */ #define ERR_LENMIN -10 /*same as LAN_ERR_TOO_SHORT */ #define ERR_OTHER -13 /*same as LAN_ERR_OTHER */ #define STRING_DATA_TYPE_BINARY 0x00 #define STRING_DATA_TYPE_BCD_PLUS 0x01 #define STRING_DATA_TYPE_SIX_BIT_ASCII 0x02 #define STRING_DATA_TYPE_LANG_DEPENDENT 0x03 #define FRUCHUNK_SZ 16 /* optimal chunk = 16 bytes */ #define FRU_END 0xC1 #define FRU_EMPTY_FIELD 0xC0 #define FRU_TYPE_MASK 0xC0 #define FRU_LEN_MASK 0x3F #define NUM_BOARD_FIELDS 6 #define NUM_PRODUCT_FIELDS 8 #define NUM_CHASSIS_FIELDS 3 #define MAX_CTYPE 26 char *ctypes[MAX_CTYPE] = { "", "Other", "Unknown", "Desktop", "Low Profile Desktop", "Pizza Box", "Mini-Tower", "Tower", "Portable", "Laptop", "Notebook", "Handheld", "Docking Station", "All-in-One", "Sub-Notebook", "Space-saving", "Lunch Box", "Main Server Chassis", "Expansion Chassis", "SubChassis", "Bus Expansion Chassis", "Peripheral Chassis", "RAID Chassis", /*0x17=23.*/ "Rack-Mount Chassis", "New24" , "New25"}; /* what about bladed chassies? */ char *ctype_hdr = "Chassis Type "; char *chassis[NUM_CHASSIS_FIELDS] = { "Chassis Part Number ", "Chassis Serial Num ", "Chassis OEM Field " }; char *board[NUM_BOARD_FIELDS] = { "Board Manufacturer ", "Board Product Name ", "Board Serial Number ", "Board Part Number ", "Board FRU File ID ", "Board OEM Field " }; char *product[NUM_PRODUCT_FIELDS] = { "Product Manufacturer", "Product Name ", "Product Part Number ", "Product Version ", "Product Serial Num ", "Product Asset Tag ", "Product FRU File ID ", "Product OEM Field " }; char *asset_hdr = " Asset Tag Length "; #if 0 typedef struct { uchar len :6; uchar type:2; } TYPE_LEN; /*old, assumes lo-hi byte order*/ #else typedef struct { uchar len; uchar type; } TYPE_LEN; #endif void free_fru(uchar *pfrubuf) { if (pfrubuf != NULL) { if (frubuf != NULL) free(frubuf); frubuf = NULL; } return; } int load_fru(uchar sa, uchar frudev, uchar frutype, uchar **pfrubuf) { int ret = 0; uchar indata[FRUCHUNK_SZ+9]; uchar resp[18]; int sresp; uchar cc; int sz; char fwords; ushort fruoff = 0; int i, rv; int chunk; if (pfrubuf == NULL) return(ERR_BAD_PARAM); *pfrubuf = NULL; memset(indata, 0, sizeof(indata)); indata[0] = frudev; sresp = sizeof(resp); if (fdebug) printf("load_fru: sa=%02x, frudev=%02x, addrtype=%d\n", sa,frudev,g_addrtype); ret = ipmi_cmd_mc(GET_FRU_INV_AREA,indata,1,resp,&sresp,&cc,fdebug); if (fdebug) printf("load_fru: inv ret=%d, cc=%x, resp=%02x %02x %02x\n", ret,cc, resp[0], resp[1], resp[2]); if (ret != 0) return(ret); if (cc != 0) { ret = (cc & 0x00ff); return(ret); } sz = resp[0] + (resp[1] << 8); if (resp[2] & 0x01) { fwords = 1; sz = sz * 2; } else fwords = 0; frubuf = malloc(sz); if (frubuf == NULL) return(get_errno()); *pfrubuf = frubuf; sfru = sz; /* Loop on READ_FRU_DATA */ for (i = 0, chunk=FRUCHUNK_SZ; i < sz; i+=chunk) { if ((i+chunk) >= sz) chunk = sz - i; indata[0] = frudev; /* FRU Device ID */ if (fwords) { indata[3] = chunk / 2; fruoff = (i/2); } else { indata[3] = (uchar)chunk; fruoff = (ushort)i; } indata[1] = fruoff & 0x00FF; indata[2] = (fruoff & 0xFF00) >> 8; sresp = sizeof(resp); ret = ipmi_cmd_mc(READ_FRU_DATA,indata,4,resp,&sresp,&cc,fdebug); if (ret != 0) break; else if (cc != 0) { if (i == 0) ret = cc & 0x00ff; if (fdebug) printf("read_fru[%d]: ret = %d cc = %x\n",i,ret,cc); break; } memcpy(&frubuf[i],&resp[1],chunk); } if ((frudev == 0) && (sa == bmc_sa) && do_guid) { /*main system fru, so get GUID*/ sresp = sizeof(resp); rv = ipmi_cmd_mc(GET_SYSTEM_GUID,indata,0,resp,&sresp,&cc,fdebug); if (fdebug) printf("system_guid: ret = %d, cc = %x\n",rv,cc); if (rv == 0) rv = cc; if ((rv != 0) && !is_remote()) { /* get UUID from SMBIOS */ cc = 0; sresp = 16; rv = get_SystemGuid(resp); if (fdebug) printf("get_SystemGuid: ret = %d\n",rv); } if (rv == 0 && cc == 0) { if (fdebug) { printf("system guid (%d): ",sresp); for (i=0; i<16; i++) printf("%02x ",resp[i]); printf("\n"); } memcpy(&guid,&resp,16); guid[16] = 0; } else { printf("WARNING: GetSystemGuid error %d, %s\n",rv,decode_rv(rv)); /*do not pass this error upstream*/ } } /*endif*/ return(ret); } static void decode_string(unsigned char type, unsigned char language_code, unsigned char *source, int slen, char *target, int tsize) { static const char bcd_plus[] = "0123456789 -.:,_"; unsigned char *s = &source[0]; int len, i, j, k; union { uint32_t bits; char chars[4]; } u; if (slen == 0 || slen == 1) return; switch(type) { case STRING_DATA_TYPE_BINARY: /* 00: binary/unspecified */ len = (slen*2); break; /* hex dump -> 2x length */ case STRING_DATA_TYPE_SIX_BIT_ASCII: /*type 2 6-bit ASCII*/ /* 4 chars per group of 1-3 bytes */ len = ((((slen+2)*4)/3) & ~3); break; case STRING_DATA_TYPE_LANG_DEPENDENT: /* 03 language dependent */ case STRING_DATA_TYPE_BCD_PLUS: /* 01b: BCD plus */ default: len = slen; break; } if (len >= tsize) len = tsize - 1; memset(target, 0, len); if (type == STRING_DATA_TYPE_BCD_PLUS) { /*type 1: BCD plus*/ for (k=0; k 1 ? s[i+1] : 0); u.chars[1] = (k > 2 ? s[i+2] : 0); #define CHAR_IDX 3 #else memcpy((void *)&u.bits, &s[i], k); #define CHAR_IDX 0 #endif for (k=0; k<4; k++) { target[j++] = ((u.chars[CHAR_IDX] & 0x3f) + 0x20); u.bits >>= 6; } } target[j] = '\0'; } else if (type == STRING_DATA_TYPE_LANG_DEPENDENT) { /*type 3*/ if ((language_code == 0x00) || (language_code == 0x25) || (language_code == 0x19)) { memcpy(target, source, len); target[len] = 0; } else { printf("Language 0x%x dependent decode not supported\n",language_code); } } else if (type == STRING_DATA_TYPE_BINARY) { /* 00: binary/unspecified */ strncpy(target, buf2str(s, slen), len); target[len] = '\0'; /* add end-of-string char */ } else { /* other */ printf("Unable to decode type 0x%.2x\n",type); } return; } uchar calc_cksum(uchar *pbuf,int len) { int i; uchar cksum; uchar sum = 0; for (i = 0; i < len; i++) sum += pbuf[i]; cksum = 0 - sum; return(cksum); } static void dumpbuf(uchar *pbuf,int sz) { uchar line[17]; uchar a; int i, j; line[0] = 0; line[16] = 0; j = 0; for (i = 0; i < sz; i++) { if (i % 16 == 0) { j = 0; printf("%s\n %04d: ",line,i); } a = pbuf[i]; if (a < 0x20 || a > 0x7f) a = '.'; line[j++] = a; printf("%02x ",pbuf[i]); } line[j] = 0; printf("%s\n",line); return; } #define NSPDMFG 10 static struct { uchar id; char *str; } spd_mfg[NSPDMFG] = { /* see JEDEC JEP106 doc */ { 0x02, "AMI" }, { 0x04, "Fujitsu" }, { 0x15, "Philips Semi" }, { 0x1c, "Mitsubishi" }, { 0x2c, "Micron" }, { 0x89, "Intel" }, { 0x98, "Kingston" }, { 0xA8, "US Modular" }, { 0xc1, "Infineon" }, { 0xce, "Samsung" } }; int ValidTL(uchar typelen) { if (vend_id != VENDOR_INTEL) return 1; if ((typelen & 0xC0) == 0xC0) return 1; /* validate C type */ if ((typelen & 0x00) == 0x00) return 1; /* validate 0 type too */ else return 0; } #define SYS_FRUTYPE 0x40 char * FruTypeString(uchar frutype, uchar dev) { char *pstr; switch (frutype) { case 0x07: /*IPMB*/ case 0x0c: /*FRU*/ if (dev == 0) pstr = "Baseboard"; else pstr = "Board "; break; case 0x0a: pstr = "PowerSply"; break; /*FRU*/ case 0x15: pstr = "PowerCage"; break; /*FRU*/ case 0x20: pstr = "DIMM "; break; /*FRU*/ case 0x0f: pstr = "HotSwapCt"; break; /*IPMB*/ case 0x2e: pstr = "ME "; break; /*IPMB*/ case SYS_FRUTYPE: pstr = "SysInfo "; break; /*SysInfo*/ default: pstr = "Component"; break; } return(pstr); } static int ChkOverflow(int idx, int sz, uchar len) { if (idx >= sz) { printf(" ERROR - FRU Buffer Overflow (%d >= %d), last len=%d\n", idx,sz,len); return 1; /*overflow error*/ } return 0; } static void show_spd(uchar *spd, int lenspd, uchar frudev, uchar frutype) { int sz; char *pstr; int sdcap, ranks, busw, sdw, totcap; uchar srev, mfgid, mrev1, mrev2, yr, wk; uchar isdcap, iranks, ibusw, isdw; uchar iparity, iser, ipart, irev; int i; char devstr[24]; /* Sample SPD Headers: 80 08 07 0c 0a 01 48 00 (DDR SDRAM DIMM) 92 10 0b 01 03 1a 02 00 (DDR3 SDRAM DIMMs) */ sz = spd[0]; /* sz should == lenspd */ srev = spd[1]; /* SPD Rev: 8 for DDR, 10 for DDR3 SPD spec */ if (fcanonical) devstr[0] = 0; /*default is empty string*/ else sprintf(devstr,"[%s, %02x] ",FruTypeString(frutype,frudev),frudev); printf("%sMemory SPD Size %c %d\n", devstr,bdelim,lenspd); switch (spd[2]) { case 0x02: pstr = "EDO"; break; case 0x04: pstr = "SDRAM"; break; case 0x05: pstr = "ROM"; break; case 0x06: pstr = "DDR SGRAM"; break; case 0x07: pstr = "DDR SDRAM"; break; case 0x08: pstr = "DDR2 SDRAM"; break; case 0x09: pstr = "DDR2 SDRAM FB"; break; case 0x0A: pstr = "DDR2 SDRAM FB PROBE"; break; case 0x0B: pstr = "DDR3 SDRAM"; break; default: pstr = "DRAM"; break; /*FPM DRAM or other*/ } printf("%sMemory Type %c %s\n", devstr,bdelim,pstr); if (srev < 0x10) { /*used rev 0.8 of SPD spec*/ printf("%sModule Density %c %d MB per bank\n", devstr,bdelim, (spd[31] * 4)); printf("%sModule Banks %c %d banks\n", devstr,bdelim,spd[5]); printf("%sModule Rows, Cols %c %d rows, %d cols\n", devstr,bdelim, spd[3], spd[4]); iparity = spd[11]; mfgid = spd[64]; } else { /* use 1.0 SPD spec with DDR3 */ /* SDRAM CAPACITY = SPD byte 4 bits 3~0 */ /* PRIMARY BUS WIDTH = SPD byte 8 bits 2~0 */ /* SDRAM WIDTH = SPD byte 7 bits 2~0 */ /* RANKS = SPD byte 7 bits 5~3 */ isdcap = (spd[4] & 0x0f); iranks = (spd[7] & 0x38) >> 3; isdw = (spd[7] & 0x07); ibusw = (spd[8] & 0x07); iparity = (spd[8] & 0x38) >> 3; mfgid = spd[118]; switch(isdcap) { case 0: sdcap = 256; /*MB*/ break; case 1: sdcap = 512; /*MB*/ break; case 2: sdcap = 1024; /*MB*/ break; case 3: sdcap = 2048; /*MB*/ break; case 4: sdcap = 4096; /*MB*/ break; case 5: sdcap = 8192; /*MB*/ break; case 6: sdcap = 16384; /*MB*/ break; default: sdcap = 32768; /*MB*/ break; } switch(iranks) { case 0: ranks = 1; break; case 1: ranks = 2; break; case 2: ranks = 3; break; case 3: default: ranks = 4; break; } switch(isdw) { case 0: sdw = 4; break; case 1: sdw = 8; break; case 2: sdw = 16; break; case 3: default: sdw = 32; break; } switch(ibusw) { case 0: busw = 8; break; case 1: busw = 16; break; case 2: busw = 32; break; case 3: default: busw = 64; break; } totcap = sdcap / 8 * busw / sdw * ranks; printf("%sModule Density %c %d Mbits\n",devstr,bdelim,sdcap); printf("%sModule Ranks %c %d ranks\n",devstr,bdelim,ranks); printf("%sModule Capacity %c %d MB\n",devstr,bdelim,totcap); } if (iparity == 0x00) pstr = "Non-parity"; else /* usu 0x02 */ pstr = "ECC"; printf("%sDIMM Config Type %c %s\n", devstr,bdelim,pstr); for (i = 0; i < NSPDMFG; i++) if (spd_mfg[i].id == mfgid) break; if (i == NSPDMFG) pstr = ""; /* not found, use null string */ else pstr = spd_mfg[i].str; printf("%sManufacturer ID %c %s (0x%02x)\n", devstr,bdelim,pstr,mfgid); if (srev < 0x10) { yr = spd[93]; wk = spd[94]; iser = 95; ipart = 73; irev = 91; } else { /* 1.0 SPD spec with DDR3 */ yr = spd[120]; wk = spd[121]; iser = 122; ipart = 128; irev = 146; } mrev1 = spd[irev]; /* save this byte for later */ mrev2 = spd[irev+1]; spd[irev] = 0; /*stringify part number */ printf("%sManufacturer Part# %c %s\n", devstr,bdelim,&spd[ipart]); printf("%sManufacturer Rev %c %02x %02x\n", devstr,bdelim,mrev1,mrev2); printf("%sManufacturer Date %c year=%02x week=%02x\n", devstr,bdelim, yr,wk); printf("%sAssembly Serial Num %c %02x%02x%02x%02x\n", devstr,bdelim,spd[iser],spd[iser+1],spd[iser+2],spd[iser+3]); spd[irev] = mrev1; /* restore byte, so ok to repeat later */ return; } void show_guid(uchar *pguid) { char *s; int i; for (i=0; i<16; i++) { if ((i == 4) || (i == 6) || (i == 8) || (i == 10)) s = "-"; else s = ""; printf("%s%02x",s,pguid[i]); } } static char *volt_desc(uchar b) { char *s; switch(b) { case 0x03: s = "5V"; break; case 0x02: s = "3.3V"; break; case 0x01: s = "-12V"; break; case 0x00: default: s = "12V"; break; } return(s); } static char *mgt_type(uchar b) { char *s; switch(b) { case 0x01: s = "SysMgt_URL"; break; case 0x02: s = "SystemName"; break; case 0x03: s = "SysPingAddr"; break; case 0x04: s = "Compon_URL"; break; case 0x05: s = "ComponName"; break; case 0x06: s = "ComponPing"; break; case 0x07: default: s = "SysGUID"; break; } return(s); } static void show_fru_multi(char *tag, int midx, uchar mtype, uchar *pdata, int dlen) { int vend; char mystr[256]; char *s1; int v1, v2, v3, v4, v5, v6, v7; uchar b1, b2; if (fdebug) dumpbuf(pdata,dlen); /*multi-record area dump*/ sprintf(mystr,"%sMulti[%d] ",tag,midx); switch(mtype) { case 0x00: /*Power Supply*/ printf("%sPower Supply Record %c \n",mystr,bdelim); v1 = pdata[0] + ((pdata[1] & 0x0f) << 8); printf("\t Capacity \t%c %d W\n",bdelim, v1); v2 = pdata[2] + (pdata[3] << 8); printf("\t Peak VA \t%c %d VA\n",bdelim, v2); printf("\t Inrush Current\t%c %d A\n",bdelim, pdata[4]); printf("\t Inrush Interval\t%c %d ms\n",bdelim, pdata[5]); v3 = pdata[6] + (pdata[7] << 8); v4 = pdata[8] + (pdata[9] << 8); printf("\t Input Voltage Range1\t%c %d-%d V\n", bdelim,v3/100,v4/100); v3 = pdata[10] + (pdata[11] << 8); v4 = pdata[12] + (pdata[13] << 8); printf("\t Input Voltage Range2\t%c %d-%d V\n", bdelim,v3/100,v4/100); printf("\t Input Frequency Range\t%c %d-%d Hz\n", bdelim,pdata[14],pdata[15]); printf("\t AC Dropout Tolerance\t%c %d ms\n",bdelim, pdata[16]); b1 = pdata[17]; b2 = (b1 & 0x01); if (b2) { /*predictive fail*/ if ((b1 & 0x10) != 0) s1 = "DeassertFail "; else s1 = "AssertFail "; } else { if ((b1 & 0x10) != 0) s1 = "2pulses/rot "; else s1 = "1pulse/rot "; } printf("\t Flags \t%c %s%s%s%s%s\n",bdelim, b2 ? "PredictFail " : "", ((b1 & 0x02) == 0) ? "" : "PowerFactorCorrect ", ((b1 & 0x04) == 0) ? "" : "AutoswitchVolt ", ((b1 & 0x08) == 0) ? "" : "Hotswap ", s1); v5 = pdata[18] + ((pdata[19] & 0x0f) << 8); v6 = (pdata[19] & 0xf0) >> 4; printf("\t Peak Capacity \t%c %d W for %d s\n",bdelim, v5,v6); if (pdata[20] == 0) { printf("\t Combined Capacity\t%c not specified\n",bdelim); } else { b1 = pdata[20] & 0x0f; b2 = (pdata[20] & 0xf0) >> 4; v7 = pdata[21] + (pdata[22] << 8); printf("\t Combined Capacity\t%c %d W (%s and %s)\n", bdelim, v7,volt_desc(b1),volt_desc(b2)); } if (b2) /*predictive fail*/ printf("\t Fan low threshold\t%c %d RPS\n",bdelim,pdata[23]); break; case 0x01: /*DC Output*/ b1 = pdata[0] & 0x0f; b2 = ((pdata[0] & 0x80) != 0); printf("%sDC Output %c number %d\n",mystr,bdelim,b1); printf("\t Standby power \t%c %s\n", bdelim, (b2 ? "Yes" : "No")); v1 = pdata[1] + (pdata[2] << 8); printf("\t Nominal voltage \t%c %.2f V\n", bdelim, (double)v1 / 100); v2 = pdata[3] + (pdata[4] << 8); v3 = pdata[5] + (pdata[6] << 8); printf("\t Voltage deviation \t%c + %.2f V / - %.2f V\n", bdelim, (double)v3/100, (double)v2/100); v4 = pdata[7] + (pdata[8] << 8); printf("\t Ripple and noise pk-pk \t%c %d mV\n", bdelim, v4); v5 = pdata[9] + (pdata[10] << 8); printf("\t Min current draw \t%c %.3f A\n", bdelim, (double)v5/1000); v6 = pdata[11] + (pdata[12] << 8); printf("\t Max current draw \t%c %.3f A\n", bdelim, (double)v6/1000); break; case 0x02: /*DC Load*/ b1 = pdata[0] & 0x0f; printf("%sDC Load %c number %d\n",mystr,bdelim,b1); v1 = pdata[1] + (pdata[2] << 8); printf("\t Nominal voltage \t%c %.2f V\n", bdelim, (double)v1 / 100); v2 = pdata[3] + (pdata[4] << 8); v3 = pdata[5] + (pdata[6] << 8); printf("\t Min voltage allowed \t%c %.2f A\n", bdelim, (double)v2); printf("\t Max voltage allowed \t%c %.2f A\n", bdelim, (double)v3); v4 = pdata[7] + (pdata[8] << 8); printf("\t Ripple and noise pk-pk \t%c %d mV\n", bdelim, v4); v5 = pdata[9] + (pdata[10] << 8); printf("\t Min current load \t%c %.3f A\n", bdelim, (double)v5/1000); v6 = pdata[11] + (pdata[12] << 8); printf("\t Max current load \t%c %.3f A\n", bdelim, (double)v6/1000); break; case 0x03: /*Management Access*/ b1 = pdata[0]; printf("%sManagemt Access %c %s ",mystr,bdelim,mgt_type(b1)); memcpy(mystr,&pdata[1],dlen-1); mystr[dlen-1] = 0; printf("%s\n",mystr); break; case 0x04: /*Base Compatibility*/ vend = pdata[0] + (pdata[1] << 8) + (pdata[2] << 16); printf("%sBasic Compat %c %06x\n",mystr,bdelim,vend); break; case 0x05: /*Extended Compatibility*/ vend = pdata[0] + (pdata[1] << 8) + (pdata[2] << 16); printf("%sExtended Compat %c %06x\n",mystr,bdelim,vend); break; case 0xC0: /*OEM Extension*/ vend = pdata[0] + (pdata[1] << 8) + (pdata[2] << 16); if (vend == OEM_PICMG) { printf("%sOEM PICMG %c \n", mystr,bdelim); show_fru_picmg(pdata,dlen); } else printf("%sOEM Ext %c %06x %02x\n", mystr,bdelim, vend, pdata[3]); break; default: printf("%s %02x %c %02x\n", mystr,mtype,bdelim, pdata[0]); break; } } int show_fru(uchar sa, uchar frudev, uchar frutype, uchar *pfrubuf) { int ret = 0; int i, j, n, sz; uchar *pfru0; uchar *pfru; uchar lang; TYPE_LEN tl; char newstr[64]; int iaoff, ialen, bdoff, bdlen; int proff, prlen, choff, chlen; int moff, mlen; char devstr[24]; char *pstr; if ((pfrubuf[0] & 0x80) == 0x80) { /* 0x80 = type for DIMMs (SPD) */ /* FRU Header: 80 08 07 0c 0a 01 48 00 (DIMM) */ /* FRU Header: 92 10 0b 01 03 1a 02 00 (DDR3 DIMMs) */ sz = pfrubuf[0]; if (fdebug) { printf("DIMM SPD Body (size=%d/%d): ",sz,sfru); dumpbuf(pfrubuf,sfru); } show_spd(pfrubuf,sfru, frudev,frutype); return(ret); } pstr = FruTypeString(frutype,frudev); if (fcanonical) devstr[0] = 0; /*default is empty string*/ else sprintf(devstr,"[%s,%02x,%02x] ",pstr,sa,frudev); printf("%s%s FRU Size %c %d\n",devstr,pstr,bdelim,sfru); /* * FRU header: * 0 = format_ver (01 is std, usu 0x80 if DIMM) * 1 = internal_use offset * 2 = chassis_info offset * 3 = board_info offset (usu 6 fields) * 4 = product_info offset (usu 8 fields) * 5 = multirecord offset * 6 = pad (00) * 7 = header checksum (zero checksum) * FRU Header: 01 01 02 09 13 00 00 e0 (BMC) * FRU Header: 01 00 00 00 01 07 00 f7 (Power Cage) */ pfru0 = &pfrubuf[0]; /*pointer to fru start*/ pfru = &pfrubuf[0]; sz = 8; /*minimum for common header*/ for (i = 1; i < 6; i++) { /* walk thru offsets */ if (pfrubuf[i] != 0) sz = pfrubuf[i] * 8; } if (sz > 8) { /* if have at least one section */ if (pfrubuf[5] != 0) j = 5 + pfrubuf[sz+2]; /*if multi-record area*/ else j = pfrubuf[sz+1] * 8; /* else add length of last section */ sz += j; } /* Now, sz = size used, sfru = total available size */ if (sz > sfru) { if (fdebug) { uchar hsum; printf("FRU Header: "); for (i = 0; i < 8; i++) printf("%02x ",pfrubuf[i]); printf("\n"); hsum = calc_cksum(&pfrubuf[0],7); if (pfrubuf[7] != hsum) printf("FRU Header checksum mismatch (%x != %x)\n",pfrubuf[7],hsum); } printf("FRU size used=%d > available=%d\n",sz,sfru); if (fpicmg || fdoanyway) sz = sfru; /*do it anyway*/ else { printf("Please apply the correct FRU/SDR diskette\n"); return(ERR_OTHER); } } /* internal area offset, length */ iaoff = pfrubuf[1] * 8; ialen = pfrubuf[iaoff + 1] * 8; /* chassis area offset, length */ choff = pfrubuf[2] * 8; chlen = pfrubuf[choff + 1] * 8; /* board area offset, length */ bdoff = pfrubuf[3] * 8; bdlen = pfrubuf[bdoff + 1] * 8; /* product area offset, length */ proff = pfrubuf[4] * 8; prlen = pfrubuf[proff + 1] * 8; /* multi-record area offset, length */ moff = pfrubuf[5] * 8; mlen = 0; if (moff > 0) { for (i = moff; i < sfru; ) { if (pfrubuf[i] == 0 && pfrubuf[i+2] == 0) break; /*type/len invalid*/ j = 5 + pfrubuf[i+2]; mlen += j; if (pfrubuf[i+1] & 0x80) break; i += j; } } if (fdebug) { printf("FRU Header: "); for (i = 0; i < 8; i++) printf("%02x ",pfrubuf[i]); printf("\n"); printf("FRU Body (size=%d/%d): ",sz,sfru); dumpbuf(pfrubuf,sfru); printf("header, len=%d, cksum0 = %02x, cksum1 = %02x\n", 8,pfrubuf[7],calc_cksum(&pfrubuf[0],7)); printf("internal off=%d, len=%d, cksum = %02x\n", iaoff,ialen,calc_cksum(&pfrubuf[iaoff],ialen-1)); printf("chassis off=%d, len=%d, cksum = %02x\n", choff,chlen,calc_cksum(&pfrubuf[choff],chlen-1)); printf("board off=%d, len=%d, cksum = %02x\n", bdoff,bdlen,calc_cksum(&pfrubuf[bdoff],bdlen-1)); printf("prod off=%d, len=%d, cksum = %02x\n", proff,prlen,calc_cksum(&pfrubuf[proff],prlen-1)); /* Multi-record area */ printf("multi off=%d, len=%d, fru sz=%d\n", moff,mlen,sz); } /*endif fdebug, show header*/ if (choff != 0) { /* show Chassis area fields */ pfru = &pfrubuf[choff]; lang = 25; /* English */ ctype = pfru[2]; /*chassis type*/ if (fdebug) printf("ctype=%x\n",ctype); if (ctype >= MAX_CTYPE) ctype = MAX_CTYPE - 1; printf("%s%s%c %s\n",devstr, ctype_hdr,bdelim,ctypes[ctype]); pfru += 3; /* skip chassis header */ tl.len = 0; for (i = 0; i < NUM_CHASSIS_FIELDS; i++) { if (ChkOverflow((int)(pfru - pfru0),sfru,tl.len)) break; if (pfru[0] == FRU_END) break; /*0xC1 = end of FRU area*/ if (!ValidTL(pfru[0])) printf(" ERROR - Invalid Type/Length %02x for %s\n", pfru[0],chassis[i]); tl.type = (pfru[0] & FRU_TYPE_MASK) >> 6; tl.len = pfru[0] & FRU_LEN_MASK; if (i == 2) { /* OEM field for chassis_name */ chassis_offset = (int)(pfru - pfrubuf); chassis_len = tl.len; if (fdebug) printf("chassis oem dtype=%d lang=%d len=%d\n", tl.type,lang,tl.len); } pfru++; { newstr[0] = 0; decode_string(tl.type,lang,pfru,tl.len,newstr,sizeof(newstr)); printf("%s%s%c %s\n",devstr, chassis[i],bdelim,newstr); } pfru += tl.len; } if (fdebug) printf("num Chassis fields = %d\n",i); } if (bdoff != 0) { long nMin, nSec; time_t tsec; /* show Board area fields */ pfru = &pfrubuf[bdoff]; lang = pfru[2]; /* Decode board mfg date-time (num minutes since 1/1/96) */ nMin = pfru[3] + (pfru[4] << 8) + (pfru[5] << 16); /* 820,454,400 sec from 1/1/70 to 1/1/96 */ nSec = (nMin * 60) + 820454400; tsec = (time_t)(nSec & 0x0ffffffff); // fmt_time(tsec,newstr,sizeof(newstr)); printf("%sBoard Mfg DateTime %c %s",devstr,bdelim,ctime(&tsec)); pfru += 6; /* skip board header */ tl.len = 0; for (i = 0; i < NUM_BOARD_FIELDS; i++) { if (ChkOverflow((int)(pfru - pfru0),sfru,tl.len)) break; if (pfru[0] == FRU_END) break; /*0xC1 = end*/ if (!ValidTL(pfru[0])) printf(" ERROR - Invalid Type/Length %02x for %s\n", pfru[0],board[i]); tl.type = (pfru[0] & FRU_TYPE_MASK) >> 6; tl.len = pfru[0] & FRU_LEN_MASK; pfru++; { newstr[0] = 0; decode_string(tl.type,lang,pfru,tl.len,newstr,sizeof(newstr)); printf("%s%s%c %s\n",devstr, board[i],bdelim,newstr); } pfru += tl.len; } if (fdebug) printf("num Board fields = %d\n",i); } if (proff != 0) { /* show Product area fields */ pfru = &pfrubuf[proff]; maxprod = pfru[1] * 8; lang = pfru[2]; pfru += 3; /* skip product header */ tl.len = 0; for (i = 0; i < NUM_PRODUCT_FIELDS; i++) { if (ChkOverflow((int)(pfru - pfru0),sfru,tl.len)) break; if (*pfru == FRU_END) { /*0xC1 = end*/ /* Wart for known Kontron 1-byte Product Version anomaly. */ if (vend_id == VENDOR_KONTRON && i == 3) ; else break; } if (*pfru == 0) *pfru = FRU_EMPTY_FIELD; /* fix a broken table */ if (!ValidTL(pfru[0])) printf(" ERROR - Invalid Type/Length %02x for %s\n", pfru[0],product[i]); tl.type = (pfru[0] & FRU_TYPE_MASK) >> 6; tl.len = pfru[0] & FRU_LEN_MASK; if ((frudev == 0) && (sa == bmc_sa)) { /*baseboard FRU*/ if (i == 5) { /* asset tag */ asset_offset = (int)(pfru - pfrubuf); asset_len = tl.len; if (fdebug) printf("asset off=%d dtype=%d lang=%d len=%d\n", asset_offset,tl.type,lang,tl.len); if (fshowlen) /* show asset tag length for main board */ printf("%s%c %d\n",asset_hdr,bdelim,asset_len); } else if (i == 4) { /* serial number */ sernum_offset = (int)(pfru - pfrubuf); sernum_len = tl.len; if (fdebug) printf("sernum dtype=%d lang=%d len=%d\n", tl.type, lang, tl.len); } else if (i == 3) { /* product version number */ prodver_offset = (int)(pfru - pfrubuf); prodver_len = tl.len; if (fdebug) printf("prodver dtype=%d lang=%d len=%d\n", tl.type, lang, tl.len); } } /*if baseboard sa*/ pfru++; { newstr[0] = 0; decode_string(tl.type,lang,pfru,tl.len,newstr,sizeof(newstr)); printf("%s%s%c %s\n",devstr, product[i],bdelim,newstr); } pfru += tl.len; } if (fdebug) printf("num Product fields = %d, last=%x, max = %d\n", i,*pfru,maxprod ); if (*pfru == 0x00) *pfru = FRU_END; /* insert end char if broken */ } if (moff != 0) { /* multi-record area may contain several record headers * 0 = record type id * 1 = 0x02 or 0x82 if End-of-List * 2 = record len * 3 = record chksum * 4 = header chksum */ pfru = &pfrubuf[moff]; j = moff; for (i = 0; j < sz ; i++) { if (pfru[0] == 0 && pfru[2] == 0) break; /*type/len invalid*/ n = pfru[2]; /* len of this record */ show_fru_multi(devstr,i,pfru[0],&pfru[5],n); j += (5 + n); if (pfru[1] & 0x80) j = sz; /*0x80 = last in list, break*/ pfru += (5 + n); } } if ((frudev == 0) && (sa == bmc_sa) && do_guid) { printf("%sSystem GUID %c ",devstr,bdelim); show_guid(guid); printf("\n"); } return(ret); } int write_fru_data(uchar id, ushort offset, uchar *data, int dlen, char fdebug) { int ret = -1; int chunk; ushort fruoff; uchar req[FRUCHUNK_SZ+9]; uchar resp[FRUCHUNK_SZ]; int sresp; uchar cc; int i, j; /* Write the buffer in small 16-byte (FRUCHUNK_SZ) chunks */ req[0] = 0x00; /* override FRU Device ID (fruid) */ fruoff = offset; chunk = FRUCHUNK_SZ; for (i = 0; i < dlen; i += chunk) { req[1] = fruoff & 0x00ff; req[2] = (fruoff & 0xff00) >> 8; if ((i + chunk) > dlen) chunk = dlen - i; memcpy(&req[3],&data[i],chunk); if (fdebug) { printf("write_fru_data[%d] (len=%d): ",i,chunk+3); for (j = 0; j < chunk+3; j++) printf("%02x ",req[j]); printf("\n"); } sresp = sizeof(resp); ret = ipmi_cmd_mc(WRITE_FRU_DATA,req,(uchar)(chunk+3),resp,&sresp, &cc,fdebug); if ((ret == 0) && (cc != 0)) ret = cc & 0x00ff; if (fdebug && ret == 0) printf("write_fru_data[%d]: %d bytes written\n",i,resp[0]); if (ret != 0) break; fruoff += (ushort)chunk; } return(ret); } /* write_asset updates the FRU Product area only. */ int write_asset(char *tag, char *sernum, char *prodver, int flag, uchar *pfrubuf) { int ret = -1; uchar newdata[SZ_PRODAREA]; int alen, clen; int snlen, verlen; uchar *pfru0; uchar *pfru; uchar *pnew; int i, j, m, n, newlen, max; int chas_offset; int prod_offset, prod_len; int mult_offset, mult_len; uchar chksum; char fdoasset = 0; char fdosernum = 0; char fdoprodver = 0; char fdochassis = 0; if (flag == 0) return ERR_OTHER; if (pfrubuf == NULL) pfrubuf = frubuf; if (pfrubuf == NULL) return ERR_OTHER; if ((flag & 0x01) != 0) { fdoasset = 1; alen = strlen_(tag); /*new*/ } else { alen = asset_len; /*old*/ } if ((flag & 0x02) != 0) { fdosernum = 1; snlen = strlen_(sernum); /*new*/ } else { snlen = sernum_len; /*old*/ } if ((flag & 0x200) != 0) { fdochassis = 1; // clen = strlen(chassis_nm); /*new, ignore*/ // if (clen <= 1) return ERR_LENMIN; clen = chassis_len; } else { clen = chassis_len; /*old*/ } if ((flag & 0x08) != 0) { fdoprodver = 1; verlen = strlen_(prodver); /*new*/ } else verlen = prodver_len; /*old*/ /* * Abort if offset is negative or if it would clobber * fru header (8 bytes). * Abort if asset tag is too big for fru buffer. */ if (fdebug) { printf("write_asset: asset_off=%d asset_len=%d alen=%d sFRU=%d\n", asset_offset,asset_len,alen,sfru); printf(" sernum_off=%d sernm_len=%d snlen=%d maxprod=%d\n", sernum_offset,sernum_len,snlen,maxprod); printf(" prodver=%d prodver_len=%d verlen=%d maxprod=%d\n", prodver_offset,prodver_len,verlen,maxprod); } if (fdoasset && (alen <= 1)) return ERR_LENMIN; if (fdosernum && (snlen <= 1)) return ERR_LENMIN; if (asset_offset < 8) return ERR_LENMIN; if (asset_offset + alen > sfru) return ERR_LENMAX; if (sernum_offset < 8) return ERR_LENMIN; if (sernum_offset + snlen > sfru) return ERR_LENMAX; if (prodver_offset < 8) return ERR_LENMIN; if (prodver_offset + verlen > sfru) return ERR_LENMAX; pfru0 = &pfrubuf[0]; chas_offset = pfrubuf[2] * 8; // offset of chassis data prod_offset = pfrubuf[4] * 8; // offset of product data prod_len = pfrubuf[prod_offset+1] * 8; // length of product data mult_offset = pfrubuf[5] * 8; mult_len = 0; if (mult_offset > 0) { for (i = mult_offset; i < sfru; ) { mult_len += (5 + pfrubuf[i+2]); if (pfrubuf[i+1] & 0x80) break; i = mult_len; } } /* Check if asset tag will fit in product data area of FRU. */ if (fdebug) printf("write_asset: fru[4,p]=[%02x,%02x] prod_off=%d plen=%d veroff=%d\n", pfrubuf[4],pfrubuf[prod_offset+1],prod_offset,prod_len, prodver_offset); /* asset comes after sernum, so this check works for both */ if (prod_offset > prodver_offset) return ERR_LENMAX; // offsets wrong if (prod_len > sizeof(newdata)) return ERR_LENMAX; // product > buffer memset(newdata,0,prod_len); pnew = &newdata[0]; /* Copy fru data from start to chassis OEM */ pfru = &pfrubuf[chas_offset]; /* Copy fru data before serial number */ pfru = &pfrubuf[prod_offset]; j = prodver_offset - prod_offset; memcpy(pnew,pfru,j); pfru += j; pnew += j; if (fdebug) { printf("write_asset: fru[4,p]=[%02x,%02x] sernum_off=%d snlen=%d plen=%d\n", pfrubuf[4],pfrubuf[sernum_offset+1],sernum_offset,snlen,prod_len); } if (fdoprodver) { pnew[0] = (verlen | FRU_TYPE_MASK); /*add type=3 to snlen*/ memcpy(++pnew,prodver,verlen); } else { pnew[0] = (verlen | FRU_TYPE_MASK); /*type/len byte*/ memcpy(++pnew,&pfrubuf[prodver_offset+1],verlen); } j += prodver_len + 1; pfru += prodver_len + 1; pnew += verlen; /*already ++pnew above*/ /* Copy new or old serial number */ if (fdebug) printf("pfrubuf[%ld]: %02x %02x %02x, j=%d, snlen=%d/%d\n", (pfru-pfrubuf),pfru[0],pfru[1],pfru[2],j,snlen,sernum_len); if (fdosernum) { pnew[0] = (snlen | FRU_TYPE_MASK); /*add type=3 to snlen*/ memcpy(++pnew,sernum,snlen); } else { pnew[0] = (snlen | FRU_TYPE_MASK); /*type/len byte*/ memcpy(++pnew,&pfrubuf[sernum_offset+1],snlen); } /* increment past serial number, to asset tag */ j += sernum_len + 1; pfru += sernum_len + 1; pnew += snlen; /*already ++pnew above*/ /* Copy new or old asset tag */ if (fdebug) printf("pfrubuf[%ld]: %02x %02x %02x, j=%d, alen=%d/%d\n", (pfru-pfrubuf),pfru[0],pfru[1],pfru[2],j,alen,asset_len); if (fdoasset) { pnew[0] = (alen | FRU_TYPE_MASK); /*add type=3 to len*/ memcpy(++pnew,tag,alen); } else { pnew[0] = (alen | FRU_TYPE_MASK); /*type/len byte*/ memcpy(++pnew,&pfrubuf[asset_offset+1],alen); } j += asset_len + 1; pfru += asset_len + 1; pnew += alen; /* copy trailing fru data from saved copy */ n = (int)(pnew - newdata); /* new num bytes used */ m = (int)(pfru - pfru0); /* old num bytes used */ if (fdebug) printf("pfrubuf[%d]: %02x %02x %02x, j=%d, n=%d, plen=%d\n", m,pfru[0],pfru[1],pfru[2],j,n,prod_len); if (mult_offset > 0) { /* do not expand if multi-record area there */ max = prod_len - j; } else /* nothing else, can expand product area, up to sfru */ max = sfru - (j + prod_offset); if (fdebug) printf("pfrubuf[%ld]: %02x %02x %02x, j=%d n=%d remainder=%d\n", (pfru-pfrubuf),pfru[0],pfru[1],pfru[2],j,n,max); if (max < 0) max = 0; for (i = 0; i < max; i++) { pnew[i] = pfru[i]; if (pfru[i] == FRU_END) { i++; break; } } if (i == max) { /*never found 0xC1 FRU_END*/ pnew[0] = FRU_END; i = 1; } newlen = n + i; if (fdebug) printf("newbuf[%d]: %02x %02x %02x, j=%d, newlen=%d\n", n,pnew[0],pnew[1],pnew[2],j,newlen); /* round up to next 8-byte boundary */ /* need one more byte for checksum, so if mod=0, adds 8 anyway */ j = 8 - (newlen % 8); for (i = 0; i < j; i++) newdata[newlen++] = 0; if (newlen < prod_len) newlen = prod_len; /* don't shrink product area */ newdata[1] = newlen / 8; // set length of product data /* include new checksum (calc over Product area) */ chksum = calc_cksum(&newdata[0],newlen-1); newdata[newlen-1] = chksum; #ifdef NEEDED /* This caused a problem on Radisys systems, and is not needed, so skip it.*/ if (mult_offset > 0) { /* add on any more data from multi-record area */ pnew = &newdata[newlen]; pfru = &pfrubuf[mult_offset]; memcpy(pnew,pfru,mult_len); newlen += mult_len; } #endif if (fdebug) { printf("old buffer (%d):",prod_len); dumpbuf(&pfrubuf[prod_offset],prod_len); printf("new buffer (%d):",newlen); dumpbuf(newdata,newlen); } if (prod_offset + newlen >= sfru) return ERR_LENMAX; if ((mult_offset > 0) && (newlen > prod_len)) return ERR_LENMAX; #ifdef TEST newlen = 0; #endif ret = write_fru_data(0, (ushort)prod_offset, newdata, newlen, fdebug); return(ret); } #define SDR_CHUNKSZ 16 #define LAST_REC 0xffff #define SDR_STR_OFF 16 int get_sdr(ushort recid, ushort resid, ushort *recnext, uchar *sdr, int *slen, uchar *pcc) { uchar idata[6]; uchar rdata[64]; int sresp; ushort cmd; uchar cc = 0; int len = 0; int szsdr, thislen; int rc; memset(sdr,0,*slen); /*clear sdr */ idata[0] = resid & 0x00ff; idata[1] = (resid & 0xff00) >> 8; idata[2] = recid & 0x00ff; idata[3] = (recid & 0xff00) >> 8; idata[4] = 0; /*offset*/ idata[5] = SDR_CHUNKSZ; /*bytes to read*/ if (fdevsdrs) cmd = GET_DEVICE_SDR; else cmd = GET_SDR; sresp = sizeof(rdata); rc = ipmi_cmd_mc(cmd, idata, 6, rdata, &sresp,&cc, fdebug); if (fdebug) printf("get_sdr[%x] ret = %d cc = %x sresp = %d\n", recid,rc,cc,sresp); if (rc == 0 && cc == 0xCA) { /*cannot read SDR_CHUNKSZ bytes*/ idata[5] = 8; /*bytes to read*/ sresp = sizeof(rdata); rc = ipmi_cmd_mc(cmd, idata, 6, rdata, &sresp,&cc, fdebug); if (fdebug) printf("get_sdr[%x] ret = %d cc = %x sresp = %d\n", recid,rc,cc,sresp); } *pcc = cc; if (rc == 0 && cc == 0) { *recnext = rdata[0] + (rdata[1] << 8); if (sresp < 2) len = 0; else len = sresp-2; if (len > *slen) len = *slen; memcpy(sdr,&rdata[2],len); szsdr = sdr[4] + 5; /*get actual SDR size*/ if (szsdr > *slen) szsdr = *slen; /* if an SDR locator record, get the rest of it. */ if (sdr[3] == 0x11 || sdr[3] == 0x12) if (szsdr > SDR_CHUNKSZ) { ushort resid2; rc = sdr_get_reservation((uchar *)&resid2,fdevsdrs); if (fdebug) printf("2nd sdr_get_reservation ret=%d\n",rc); thislen = szsdr - SDR_CHUNKSZ; if (thislen > SDR_CHUNKSZ) thislen = SDR_CHUNKSZ; idata[0] = resid2 & 0x00ff; idata[1] = (resid2 & 0xff00) >> 8; idata[2] = recid & 0x00ff; idata[3] = (recid & 0xff00) >> 8; idata[4] = SDR_CHUNKSZ; /*offset*/ idata[5] = (uchar)thislen; /*bytes to read*/ sresp = sizeof(rdata); rc = ipmi_cmd_mc(cmd, idata, 6, rdata, &sresp,&cc, fdebug); if (fdebug) printf("get_sdr[%x] 2nd ret=%d cc=%x sresp=%d\n", recid,rc,cc,sresp); if (rc == 0 && cc == 0) { if (sresp < 2) sresp = 0; else sresp -= 2; if (sresp > thislen) sresp = thislen; memcpy(&sdr[len],&rdata[2],sresp); len += sresp; } else rc = 0; /*ok because got first part*/ } /*endif got first chunk, need more*/ *slen = len; } else *slen = 0; return(rc); } void show_loadfru_error(uchar sa, uchar fruid, int ret) { if (ret == 0) return; switch(ret) { case 0x081: printf("\tFRU(%x,%x) device busy\n",sa,fruid); break; case 0x0C3: printf("\tFRU(%x,%x) timeout, not found\n",sa,fruid); break; case 0x0CB: printf("\tFRU(%x,%x) not present\n",sa,fruid); break; default: printf("load_fru(%x,%x) error = %d (0x%x)\n", sa,fruid,ret,ret); break; } return; } int get_show_fru(ushort recid, uchar *sdr, int sdrlen) { int ret = 0; int ilen; char idstr[32]; uchar sa, fruid =0; uchar frutype = 0; char fgetfru = 0; char fisbase = 0; uchar *pfru; if (sdrlen > SDR_STR_OFF) { ilen = sdrlen - SDR_STR_OFF; if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; memcpy(idstr,&sdr[SDR_STR_OFF],ilen); idstr[ilen] = 0; } else idstr[0] = 0; sa = sdr[5]; /* usu 0x20 for bmc_sa */ if (fbasefru) fisbase = 1; /* Get its FRU data */ if ((sdr[3] == 0x11) && (sdr[7] & 0x80)) { /* FRU SDRs */ /* It is a logical FRU device */ if (fcanonical) printf("SDR[%04x] FRU %c %s\n", recid, bdelim, idstr); else printf("SDR[%04x] FRU %02x %02x %02x %02x %s\n", recid, sdr[5],sdr[6],sdr[12],sdr[13],idstr); fruid = sdr[6]; if (sdrlen > 12) frutype = sdr[12]; if (sa == bmc_sa && fruid == 0) { /*dont repeat base fru */ frutype = 0x0c; fisbase = 1; if (fbasefru) fgetfru = 1; } else switch(frutype) /*FRU entity id*/ { case 0x0a: /*Power Supply*/ case 0x20: /*DIMM*/ case 0x15: /*Power Cage*/ default: fgetfru = 1; break; } } else if (sdr[3] == 0x12) { /* IPMB SDRs (DLRs for MCs) */ if (fcanonical) printf("SDR[%04x] IPMB %c %s\n", recid, bdelim, idstr); else printf("SDR[%04x] IPMB %02x %02x %02x %02x %s\n", recid, sdr[5],sdr[6],sdr[12],sdr[13],idstr); fruid = 0; /*every MC must have fruid 0*/ if (sdrlen > 12) frutype = sdr[12]; if (sa == bmc_sa && fruid == 0) { /*dont repeat base fru */ fisbase = 1; frutype = 0x07; if (fdebug) printf("do bmc_sa %02x once\n",sa); g_frutype = frutype; if (fbasefru) fgetfru = 1; } else if (frutype == 0x2e) { /*skip ME*/ if (fdebug) printf("skipping ME sa %02x, %02x\n",sa,fruid); } else if (sa == 0x28) { /*do nothing for Bridge Ctlr sa=0x28*/ if (fdebug) printf("skipping IPMB sa %02x, %02x\n",sa,fruid); } else if (sa == 0xC0) { /* HotSwap Backplane (sa=0xC0) */ /* Note: Loading sa 0xC0 over ipmi lan gives a timeout * error, but it works locally. */ fgetfru = 1; } else { /* other misc sa,fruid */ fgetfru = 1; } } /* Check if matches previous FRU, if so don't repeat */ if ((sa == lastfru[0]) && (fruid == lastfru[1]) ) fgetfru = 0; if (fgetfru) { uchar adrtype; adrtype = g_addrtype; if (fdebug) printf("set_mc %02x:%02x:%02x type=%d fruid=%02x\n", g_bus,sa,g_lun,adrtype,fruid); ipmi_set_mc(g_bus, sa, g_lun,adrtype); ret = load_fru(sa,fruid,frutype,&pfru); if (ret != 0) { show_loadfru_error(sa,fruid,ret); } else { ret = show_fru(sa,fruid,frutype,pfru); if (ret != 0) printf("show_fru error = %d\n",ret); if (sa == bmc_sa && fruid == 0) fbasefru = 0; } free_fru(pfru); pfru = NULL; ipmi_restore_mc(); lastfru[0] = sa; lastfru[1] = fruid; lastfru[2] = frutype; } return(ret); } /* * test_show_fru * * Reads the FRU buffer dump from a file to test decoding the FRU. * This file uses the format output from 'ipmiutil fru -x'. * [Component,20,00] Component FRU Size : 4096 FRU Header: 01 0a 00 01 20 00 00 d4 FRU Body (size=256/4096): 0000: 01 0a 00 01 20 00 00 d4 01 09 00 c0 3b 7e 83 64 .... .......;~.d * */ static int test_show_fru(char *infile) { int rv = -1; FILE *fp; int len, i, idx, sz, off; char buff[256]; uchar sa = 0x20; uchar fruid =0; uchar frutype = 0; uchar *pfru = NULL; char *p1; char *p2; fp = fopen(infile,"r"); if (fp == NULL) { printf("Cannot open file %s\n",infile); return(ERR_FILE_OPEN); } else { if (fdebug) printf("decoding text file with FRU buffer bytes\n"); idx = 0; off = 0; sz = sizeof(buff); while (fgets(buff, 255, fp)) { len = strlen_(buff); if (fdebug) printf("fgets[%d]: %s",idx,buff); /*has '\n'*/ if (idx == 0) { /* the FRU Size line*/ p1 = strstr(buff,"FRU Size"); if (p1 == NULL) continue; p1 = strchr(buff,','); if (p1 == NULL) continue; p1++; p2 = strchr(p1,','); if (p2 == NULL) p2 = &buff[len]; *p2 = 0; /*stringify*/ sa = htoi(p1); p1 = p2 + 1; p2 = strchr(p1,']'); if (p2 == NULL) p2 = &buff[len]; *p2 = 0; /*stringify*/ fruid = htoi(p1); frutype = 0; if (fdebug) printf("read[%d] sa=%x fruid=%x\n",idx,sa,fruid); idx++; } else if (idx == 1) { /* the FRU Header line*/ p1 = strstr(buff,"FRU Header"); // if (p1 == NULL) continue; if (fdebug) printf("read[%d] p1=%p\n",idx,p1); idx++; } else if (idx == 2) { /* the FRU Bodu line*/ p1 = strstr(buff,"FRU Body"); if (p1 == NULL) continue; p1 = strchr(buff,'='); if (p1 == NULL) continue; ++p1; p2 = strchr(p1,'/'); if (p2 == NULL) p2 = &buff[len]; *p2 = 0; /*stringify*/ sz = atoi(p1); p1 = p2 + 1; p2 = strchr(p1,')'); if (p2 == NULL) p2 = &buff[len]; *p2 = 0; /*stringify*/ sfru = atoi(p1); /*global sfru*/ pfru = malloc(sfru); if (fdebug) printf("read[%d] sz=%d/%d pfru=%p\n",idx,sz,sfru,pfru); idx++; } else { /*idx==3, this has the FRU buffer data */ p1 = strchr(buff,':'); if (p1 == NULL) continue; p1 += 2; for (i = 0; i < 16; i++) { pfru[off+i] = htoi(&p1[i*3]); } off += 16; if (fdebug) printf("read[%d] offset=%d\n",idx,off); } /*endif */ if (off >= sz) { rv = 0; break; } } /*end while*/ fclose(fp); if (rv == 0) { if (pfru == NULL) { printf("Invalid input file format (mode %d)\n",idx); return(ERR_BAD_FORMAT); } rv = show_fru(sa,fruid,frutype,pfru); if (rv != 0) printf("show_fru error = %d\n",rv); } free_fru(pfru); } return(rv); } #ifdef ALONE #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #else /* METACOMMAND */ int i_fru(int argc, char **argv) #endif { int ret, rv; int c; uchar DevRecord[16]; ushort recid; ushort nextid; ushort rsvid; uchar sdr[48]; char biosver[80]; uchar cc; uchar sa; //uchar fruid = 0; //uchar frutype = 0; int len, i, j; char *s1; uchar *pfru = NULL; FILE *fp; int ipass, npass, nsdrs; char *tag; char do_reserve = 1; char devstr[32]; printf("%s version %s\n",progname,progver); parse_lan_options('V',"4",0); /*default to admin privilege*/ while ( (c = getopt( argc, argv,"a:bcd:efhkl:m:n:i:p:r:s:t:v:xyzT:V:J:EYF:P:N:R:U:Z:?")) != EOF ) switch(c) { case 'x': fdebug = 1; break; case 'z': fdebug = 3; break; /*do more LAN debug detail*/ case 'b': fonlybase = 1; g_frutype = 0x07; break; case 'c': fcanonical = 1; bdelim = BDELIM; break; case 'd': fdump = 1; /*dump fru to a file*/ binfile = optarg; break; case 'e': fchild = 1; break; /*extra child MCs if bladed*/ case 'f': fchild = 1; break; /*follow child MCs if bladed*/ case 'h': fonlyhsc = 1; /* show HSC FRU, same as -m00c000s */ g_frutype = 0x0f; break; case 'k': foemkontron = 1; break; case 'n': fwritefru |= 0x200; if (optarg) { len = strlen_(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; strncpy(chassis_name,optarg,len); if (len == 1) { /* add a space */ chassis_name[1] = ' '; chassis_name[2] = 0; } } break; case 'p': /*Power Supply Product */ // fwritefru |= 0x10; if (optarg) { len = strlen_(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; strncpy(ps_prod,optarg,len); if (len == 1) { /* add a space */ ps_prod[1] = ' '; ps_prod[2] = 0; } } break; case 'r': frestore = 1; /*restore fru from a file*/ fwritefru = 0x100; binfile = optarg; break; case 't': ftestshow = 1; /*test show_fru from a file*/ binfile = optarg; break; case 'a': fwritefru |= 0x01; if (optarg) { len = strlen_(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; strncpy(asset_tag,optarg,len); if (len == 1) { /* add a space */ asset_tag[1] = ' '; asset_tag[2] = 0; } } break; case 's': fwritefru |= 0x02; if (optarg) { len = strlen_(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; strncpy(serial_num,optarg,len); if (len == 1) { /* add a space */ serial_num[1] = ' '; serial_num[2] = 0; } } break; case 'v': fwritefru |= 0x08; if (optarg) { len = strlen_(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; strncpy(prod_ver,optarg,len); if (len == 1) { /* add a space */ prod_ver[1] = ' '; prod_ver[2] = 0; } } break; case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } fset_mc = 1; printf("set MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'l': /* set local IPMB MC sa (same as -Z but sets bmc_sa) */ sa = htoi(&optarg[0]); /*device slave address*/ ipmi_set_mymc(g_bus, sa, g_lun,ADDR_IPMB); bmc_sa = sa; break; case 'i': fonlybase = 1; /*specify a fru id*/ if (strncmp(optarg,"0x",2) == 0) g_fruid = htoi(&optarg[2]); else g_fruid = htoi(optarg); printf("Using FRU ID 0x%02x\n",g_fruid); break; case 'y': fdoanyway = 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: printf("Usage: %s [-bceikmtvx -a asset_tag -s ser_num -NUPREFTVYZ]\n", progname); printf(" -a tag Sets the Product Asset Tag\n"); printf(" -b Only show Baseboard FRU data\n"); printf(" -c show canonical, delimited output\n"); printf(" -d file Dump the binary FRU data to a file\n"); printf(" -e walk Every child FRU, for blade MCs\n"); printf(" -i 00 Get a specific FRU ID\n"); printf(" -k Kontron setsn, setmfgdate\n"); printf(" -m002000 specific MC (bus 00,sa 20,lun 00)\n"); printf(" -s snum Sets the Product Serial Number\n"); printf(" -v pver Sets the Product Version Number\n"); printf(" -x Display extra debug messages\n"); print_lan_opt_usage(0); ret = ERR_USAGE; goto do_exit; } if (ftestshow) { ret = test_show_fru(binfile); goto do_exit; } if (is_remote() && (!fprivset)) { /* If priv not specified, not writing, and only targetted FRU, can default to request user privilege. */ if (!fwritefru && fonlybase) parse_lan_options('V',"2",0); } ret = ipmi_getdeviceid( DevRecord, sizeof(DevRecord),fdebug); if (ret == 0) { uchar ipmi_maj, ipmi_min; ipmi_maj = DevRecord[4] & 0x0f; ipmi_min = DevRecord[4] >> 4; vend_id = DevRecord[6] + (DevRecord[7] << 8) + (DevRecord[8] << 16); prod_id = DevRecord[9] + (DevRecord[10] << 8); show_devid( DevRecord[2], DevRecord[3], ipmi_maj, ipmi_min); if (ipmi_maj < 2) do_systeminfo = 0; if ((DevRecord[1] & 0x80) == 0x80) fdevsdrs = 1; if (vend_id == VENDOR_NEC) fdevsdrs = 0; else if (vend_id == VENDOR_SUN) { do_guid = 0; /*Sun doesn't support GUID*/ do_systeminfo = 0; /*Sun doesn't support system info*/ } else if (vend_id == VENDOR_INTEL) { if (is_thurley(vend_id,prod_id) || is_romley(vend_id,prod_id)) set_max_kcs_loops(URNLOOPS); /*longer for cmds (default 300)*/ } } else { goto do_exit; } ret = ipmi_getpicmg( DevRecord, sizeof(DevRecord),fdebug); if (ret == 0) fpicmg = 1; if (!fpicmg) fdevsdrs = 0; /* override, use SDR repository for FRU */ if (fdebug) printf("bmc_sa = %02x, fdevsdrs = %d\n",bmc_sa,fdevsdrs); if (fset_mc) { /* target a specific MC via IPMB (usu a picmg blade) */ if (fdebug) printf("set_mc: %02x:%02x:%02x type=%d\n", g_bus,g_sa,g_lun,g_addrtype); ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); fonlybase = 1; /*only show this MC*/ } else { g_sa = bmc_sa; /* BMC_SA = 0x20 */ } if (g_frutype == 0) { g_frutype = 0x01; /* other = "Component" */ } if (foemkontron) { #ifdef METACOMMAND for (i = 0; i < optind; i++) { argv++; argc--; } if (fdebug) verbose = 1; ret = ipmi_kontronoem_main(NULL,argc,argv); #else ret = LAN_ERR_NOTSUPPORT; #endif goto do_exit; } npass = 1; if (fonlybase || fonlyhsc) fbasefru = 1; else { /* find FRU devices from SDRs */ if (fpicmg && fdevsdrs) { /* npass = 2 will get both SdrRep & DevSdr passes on CMM */ npass = 2; g_addrtype = ADDR_IPMB; } nsdrs = 0; for (ipass = 0; ipass < npass; ipass++) { ret = GetSDRRepositoryInfo(&j,&fdevsdrs); if (fdebug) printf("GetSDRRepositoryInfo: ret=%x nSDRs=%d fdevsdrs=%d\n", ret,j,fdevsdrs); if (j == 0) { /* this is an error, probably because fdevsdrs is wrong.*/ fdevsdrs = (fdevsdrs ^ 1); if (fdebug) printf("nsdrs=0, retrying with fdevsdrs=%d\n",fdevsdrs); j = 60; /*try some default num SDRs*/ } nsdrs = j; if (fdevsdrs) tag="Device SDRs"; else tag="SDR Repository"; printf("--- Scanning %s for %d SDRs ---\n",tag,nsdrs); /* loop thru SDRs to find FRU devices */ recid = 0; while (recid != LAST_REC) { if (do_reserve) { /* reserve the SDR repository */ ret = sdr_get_reservation((uchar *)&rsvid,fdevsdrs); if (fdebug) printf("sdr_get_reservation ret=%d\n",ret); if (ret == 0) do_reserve = 0; } len = sizeof(sdr); /*sizeof(sdr); get 32 sdr bytes*/ ret = get_sdr(recid,rsvid,&nextid,sdr,&len,&cc); if ((ret != 0) || (cc != 0)) { printf("SDR[%04x] error %d ccode = %x\n",recid,ret,cc); if (cc == 0xC5) do_reserve = 1; /*retry w reserve*/ if (cc == 0x83) os_usleep(0,100); /*busy, retry*/ else break; /*stop if errors*/ } if (len >= MIN_SDR_SZ) { if ((sdr[3] == 0x11) || (sdr[3] == 0x12)) /*SDR FRU or IPMB type*/ ret = get_show_fru(recid, sdr,len); do_reserve = 1; } /*endif get_show_fru */ #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 && (sdr[3] == 0x12)) { /* PICMG MC DLR */ ushort _recid, _recnext; int _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", sdr[5],sdr[8],sdr[12],fdevsdrs); ipmi_set_mc(PICMG_SLAVE_BUS,sdr[5],sdr[6],g_addrtype); _sz = 16; ret = ipmi_cmd_mc(GET_DEVICE_ID,NULL,0,_sdrdata,&_sz,&cc,fdebug); if (ret == 0 && cc == 0) { /* get a new SDR Reservation ID */ ret = sdr_get_reservation((uchar *)&rsvid,fdevsdrs); if (fdebug) printf("sdr_get_reservation ret=%d\n",ret); /* Get the SDRs from the IPMB MC */ _recid = 0; while (_recid != 0xffff) { _sz = sizeof(_sdrdata); ret = get_sdr(_recid,rsvid,&_recnext,_sdrdata,&_sz,&cc); if (fdebug) printf("get_sdr(%x) rv=%d cc=%x rlen=%d\n", _recid,ret,cc,_sz); if (ret != 0) { printf("%04x get_sdr error %d, rlen=%d\n",_recid,ret,_sz); break; } else if (_sz >= MIN_SDR_SZ) { if ((_sdrdata[3] == 0x11) || (_sdrdata[3] == 0x12)) ret = get_show_fru(_recid, _sdrdata, _sz); } if (_recnext == _recid) _recid = 0xffff; else _recid = _recnext; } /*end while*/ } /*endif ret==0*/ /* restore BMC globals */ fdevsdrs = devsdrs_save; ipmi_restore_mc(); do_reserve = 1; /* get a new SDR Reservation ID */ } /*endif fpicmg && fchild*/ #endif recid = nextid; } /*end while sdrs*/ if (npass > 1) { /*npass==2 for PICMG child*/ /* Switch fdevsdrs from Device to Repository (or vice-versa) */ if (fdevsdrs == 0) fdevsdrs = 1; else fdevsdrs = 0; } } /*end ipass loop*/ } /*endif not fonlybase*/ /* load the FRU data for Baseboard (address 0x20) */ printf("\n"); sa = g_sa; /* bmc_sa = BMC_SA = 0x20 */ if (fonlyhsc) { sa = 0xC0; g_addrtype = ADDR_SMI; ipmi_set_mc(g_bus,sa,g_lun,g_addrtype); } if (g_addrtype == ADDR_IPMB) ipmi_set_mc(g_bus,sa,g_lun,g_addrtype); if (fbasefru) { /* get and display the Baseboard FRU data */ ret = load_fru(sa,g_fruid,g_frutype,&pfru); if (ret != 0) { show_loadfru_error(sa,g_fruid,ret); free_fru(pfru); pfru = NULL; goto do_exit; } ret = show_fru(sa,g_fruid,g_frutype,pfru); if (ret != 0) printf("show_fru error = %d\n",ret); } if (fcanonical) devstr[0] = 0; /*default is empty string*/ else sprintf(devstr,"[%s,%02x,%02x] ", /*was by g_frutype*/ FruTypeString(SYS_FRUTYPE,g_fruid),sa,g_fruid); if (!is_remote()) { i = get_BiosVersion(biosver); if (i == 0) printf("%sBIOS Version %c %s\n",devstr,bdelim,biosver); } if (do_systeminfo) { char infostr[64]; int len; len = sizeof(infostr); rv = get_system_info(1,infostr,&len); /*Firmware Version*/ if (rv == 0) { len = sizeof(infostr); rv = get_system_info(2,infostr,&len); if (rv == 0) printf("%sSystem Name %c %s\n",devstr,bdelim,infostr); len = sizeof(infostr); rv = get_system_info(3,infostr,&len); if (rv == 0) printf("%sPri Operating System%c %s\n",devstr,bdelim,infostr); len = sizeof(infostr); rv = get_system_info(4,infostr,&len); if (rv == 0) printf("%sSec Operating System%c %s\n",devstr,bdelim,infostr); } else { if (fdebug && (rv == 0xC1)) /*only supported on later IPMI 2.0 fw */ printf("GetSystemInfo not supported on this platform\n"); } } if (fdump && ret == 0) { /* Dump FRU to a binary file */ #ifdef WIN32 fp = fopen(binfile,"wb"); #else fp = fopen(binfile,"w"); #endif if (fp == NULL) { ret = get_LastError(); printf("Cannot open file %s, error %d\n",binfile,ret); } else { printf("Writing FRU size %d to %s ...\n",sfru,binfile); len = (int)fwrite(frubuf, 1, sfru, fp); fclose(fp); if (len <= 0) { ret = get_LastError(); printf("Error %d writing file %s\n",ret,binfile); } else ret = 0; } goto do_exit; } else if (frestore) { uchar cksum; /* Restore FRU from a binary file */ #ifdef WIN32 fp = fopen(binfile,"rb"); #else fp = fopen(binfile,"r"); #endif if (fp == NULL) { ret = get_LastError(); printf("Cannot open file %s, error %d\n",binfile,ret); } else { ret = 0; /* sfru and frubuf were set from load_fru above. */ len = (int)fread(frubuf, 1, sfru, fp); if (len <= 0) { ret = get_LastError(); printf("Error %d reading file %s\n",ret,binfile); sfru = 0; /*for safety*/ } fclose(fp); if (fdebug) { printf("FRU buffer from file (%d):",sfru); dumpbuf(frubuf,sfru); } /* Do some validation of the FRU buffer header */ cksum = calc_cksum(&frubuf[0],7); if (fdebug) printf("header, len=8, cksum0 = %02x, cksum1 = %02x\n", frubuf[7],cksum); if (frubuf[7] != cksum) { printf("Not a valid FRU file\n"); ret = ERR_BAD_FORMAT; free_fru(frubuf); } if (ret == 0) { /*successfully read data*/ printf("Writing FRU size %d from %s ...\n",sfru,binfile); ret = write_fru_data(g_fruid, 0, frubuf, sfru, fdebug); free_fru(frubuf); if (ret != 0) printf("write_fru error %d (0x%02x)\n",ret,ret); else { /* successful, show new data */ ret = load_fru(sa,g_fruid,g_frutype,&pfru); if (ret != 0) show_loadfru_error(sa,g_fruid,ret); else ret = show_fru(sa,g_fruid,g_frutype,pfru); free_fru(pfru); pfru = NULL; } } } } /*end-else frestore */ else if ((fwritefru != 0) && ret == 0) { if (fbasefru == 0) { /* if not fbasefru, must reload fru because freed in get_show_fru */ ret = load_fru(sa,g_fruid,g_frutype,&pfru); if (ret != 0) { show_loadfru_error(sa,g_fruid,ret); free_fru(pfru); pfru = NULL; goto do_exit; } if (fdebug) printf("Baseboard FRU buffer reloaded (%d):",sfru); } printf("\nWriting new product data (%s,%s,%s) ...\n", prod_ver,serial_num,asset_tag); ret = write_asset(asset_tag,serial_num,prod_ver,fwritefru,pfru); free_fru(pfru); if (ret != 0) printf("write_asset error %d (0x%02x)\n",ret,ret); else { /* successful, show new data */ ret = load_fru(sa,g_fruid,g_frutype,&pfru); if (ret != 0) show_loadfru_error(sa,g_fruid,ret); else ret = show_fru(sa,g_fruid,g_frutype,pfru); free_fru(pfru); } pfru = NULL; } else free_fru(pfru); do_exit: ipmi_close_(); // show_outcome(progname,ret); return(ret); } /* end ifru.c */ ipmiutil-3.1.5/util/ipmidir.c0000644000076400007640000014263613566765324016250 0ustar mgportalloggers/************************************************ * * ipmidir.c * * Supports direct raw KCS and SMBus user-space I/Os. * Use this if no other IPMI driver is present. * This interface would not be sufficient if more * than one application is using IPMI at a time. * This code is currently included for Linux, not for * Windows. Windows requires imbdrv.sys or ipmidrv.sys. * * 08/21/06 Andy Cress - added as a new module * 09/22/06 Andy Cress - improved SMBus base address detection * 09/27/06 Andy Cress - fixed passing slave addrs other than BMC (0x20) * 01/16/08 Andy Cress - more DBG messages * ************************************************/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 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 Corporation 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. *----------------------------------------------------------------------*/ #if defined(__IA64__) #define STUB_IO 1 #endif #if defined(STUB_IO) /* May stub out direct io. For instance, PPC does not support */ #define UCHAR unsigned char #define UINT16 unsigned short int ipmi_open_direct(int fdebugcmd) { return(-1); } int ipmi_close_direct(void) { return(-1); } int ipmi_cmdraw_direct(UCHAR cmd, UCHAR netfn, UCHAR lun, UCHAR sa, UCHAR bus, UCHAR *pdata, int sdata, UCHAR *presp, int *sresp, UCHAR *pcc, char fdebugcmd) { return(-1); } int ipmi_cmd_direct(UINT16 icmd, UCHAR *pdata, int sdata, UCHAR *presp, int *sresp, UCHAR *pcc, char fdebugcmd) { return(-1); } int ipmi_set_max_kcs_loops(int ms) { return(0); } #elif defined(LINUX) || defined(BSD) || defined(DOS) || defined(MACOS) || defined(HPUX) #include #include #include #include #include // for ProcessSendMessage timeout #include #include #ifdef DOS #include #else #include #endif #include "imb_api.h" #include "ipmicmd.h" #include "ipmidir.h" /* No special includes for 64-bit are needed. */ #if defined(LINUX) #include #elif defined(BSD) || defined(MACOS) || defined(HPUX) // #include int iofd = -1; static __inline uchar inbc(ushort port) { uchar data; /* from Linux sys/io.h: * __asm__ __volatile__ ("inb %w1,%0":"=a" (data):"Nd" (port)); * from BSD machine/cpufunc.h: * __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((ushort)(port))); */ __asm __volatile("inb %1,%0" : "=a" (data) : "d" (port)); return (data); } static __inline void outbc(ushort port, uchar data) { /* from Linux sys/io.h: * __asm__ __volatile__ ("outb %b0,%w1": :"a" (data), "Nd" (port)); * from BSD machine/cpufunc.h: * __asm __volatile("outb %0,%1" : : "a" (data), "id" ((ushort)(port))); */ __asm __volatile("outb %0,%1" : : "a" (data), "d" (port)); } static __inline uint inl(ushort port) { uint data; __asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port)); return (data); } static __inline void outl(ushort port, uint data) { __asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port)); } #endif /* Linux & BSD define usleep() in unistd.h, but DOS has delay() instead. */ #if defined(DOS) void usleep(ulong usec) /*missing from DOS*/ { delay(usec); } #endif /* DBGP() is enabled with -x, DBGP2 is enabled if LINUX_DEBUG & -x */ #define DBGP(fmt, args...) if (fdebugdir) fprintf(stdout,fmt, ##args) #if defined(DOS) #define DBGP2() ; /*no extra debug output*/ #elif defined(LINUX_DEBUG) #define DBGP2(fmt, args...) if (fdebugdir) fprintf(stderr,fmt, ##args) #else #define DBGP2(fmt, args...) ; /*no extra debug output*/ #endif #ifdef ALONE static int fjustpass = 0; #else // DRV_KCS, DRV_SMB types defined in ipmicmd.h // extern int fDriverTyp; // use set_driver_type() instead extern ipmi_cmd_t ipmi_cmds[NCMDS]; extern int fjustpass; #endif /*****************************************************************************/ /* * GLOBAL DATA */ /* KCS base addr: use 0xca2 for ia32, 0x8a2 for ia64 * some use 0xca8/0xcac w register spacing */ #if defined(__ia64__) /* gcc defines __ia64__, or Makefile.am defines __IA64__ */ static UINT16 kcsBaseAddress = 0x8a2; /* for Itanium2 KCS */ static UINT8 kcs_inc = 1; /*register spacing*/ #else static UINT16 kcsBaseAddress = 0xca2; /* for ia32 KCS */ static UINT8 kcs_inc = 1; /*register spacing*/ #endif /* * SMBus/SSIF: see dmidecode for I2C Slave Address & Base Addr. * Slave Addr is constant for all Intel SSIF platforms (=0x84). * 0x0540 base <= PCI ID 24D38086 at 00:1f.3 is JR (ICH5) * 0x0400 base <= PCI ID 25A48086 at 00:1f.3 is TP (Hance_Rapids) */ UINT8 mBMCADDR = 0x84; /* SMBus I2C slave address = (0x42 << 1) */ UINT16 mBMC_baseAddr = 0x540; /* usu. 0x0540 (JR), or 0x0400 if TP */ UINT16 BMC_base = 0; /* resulting BMC base address (KCS or SMBus)*/ static char lock_dir_file[] = "/var/tmp/ipmiutil_dir_lock"; /* SSIF/SMBus defines */ #define STATUS_REQ 0x60 #define WR_START 0x61 #define WR_END 0x62 #define READ_BYTE 0x68 #define COMMAND_REG (kcsBaseAddress+kcs_inc) #define STATUS_REG (kcsBaseAddress+kcs_inc) #define DATA_IN_REG (kcsBaseAddress) #define DATA_OUT_REG (kcsBaseAddress) #if defined(DOS) extern unsigned inp(unsigned _port); extern unsigned outp(unsigned _port, unsigned _value); #pragma intrinsic(inp, outp) #define _INB(addr) inp((addr)) #define _OUTB(data, addr) outp((addr),(data)) #define _IOPL(data) 0 #define ReadPortUchar( addr, valp ) (*valp) = inp((addr)) #define WritePortUchar( addr, val ) outp((addr),(val)) #define WritePortUlong( addr, val ) ( outp((addr),(val)) ) #define ReadPortUlong( addr, valp ) (*(valp) = inp((addr)) ) #elif defined(BSD) || defined(MACOS) || defined(HPUX) #define _INB(addr) inbc((addr)) #define _OUTB(data, addr) outbc((addr),(data)) #define _IOPL(data) 0 #define ReadPortUchar( addr, valp ) (*valp) = inbc((addr)) #define WritePortUchar( addr, val ) outbc((addr),(val)) #define WritePortUlong( addr, val ) ( outl((addr),(val)) ) #define ReadPortUlong( addr, valp ) (*(valp) = inl((addr)) ) #else #define _INB(addr) inb((addr)) #define _OUTB(data, addr) outb((data),(addr)) #define _IOPL(data) iopl((data)) #define ReadPortUchar( addr, valp ) (*valp) = inb((addr)) #define WritePortUchar( addr, val ) outb((val),(addr)) #define WritePortUlong( addr, val ) ( outl((val), (addr)) ) #define ReadPortUlong( addr, valp ) (*(valp) = inl((addr)) ) #endif /* Static data for Driver type, BMC type, etc. */ static int g_DriverType = DRV_KCS; static UINT16 g_ipmiVersion = IPMI_VERSION_UNKNOWN; static UINT16 g_bmcType = BMC_UNKNOWN; struct SMBCharStruct SMBChar; static int fdebugdir = 0; static char fDetectedIF = 0; /*****************************************************************************/ /* Subroutine prototypes */ #ifdef ALONE int set_driver_type(char * typ) { return; } int get_IpmiStruct(UCHAR *iftype, UCHAR *ver, UCHAR *sa, int *base, UCHAR *inc) { return(-1); } #else /* extern int set_driver_type(char * typ); in ipmicmd.h */ extern char fsm_debug; /*in mem_if.c*/ extern int get_IpmiStruct(UCHAR *iftype, UCHAR *ver, UCHAR *sa, int *base, UCHAR *inc); #endif int SendTimedImbpRequest_kcs( IMBPREQUESTDATA *requestData, unsigned int timeout, UINT8 *resp_data, int *respDataLen, UINT8 *compCode); int SendTimedImbpRequest_ssif( IMBPREQUESTDATA *requestData, unsigned int timeout, UINT8 *resp_data, int *respDataLen, UINT8 *compCode); int ImbInit_dir(void); static int SendmBmcRequest( unsigned char* request, UINT32 reqLength, unsigned char* response, UINT32* respLength, UINT32 ipmiOldFlag); static int ReadResponse( unsigned char* resp, struct SMBCharStruct* smbChar); static int SendRequest( unsigned char* req, int length, struct SMBCharStruct* smbChar ); static int GetDeviceId(UINT16 *bmcType, UINT16 *ipmiVersion); static int send_raw_kcs(UINT8 *rqData, int rqLen, UINT8 *rsData, int *rsLen ); static int ProcessTimedMessage(BMC_MESSAGE *p_reqMsg, BMC_MESSAGE *p_respMsg, const UINT32 timeout); static int wait_for_SMS_flag(void); /*****************************************************************************/ /* Subroutines */ static int ProcessMessage(BMC_MESSAGE *p_reqMsg, BMC_MESSAGE *p_respMsg) { int status = STATUS_OK; UINT32 timeout = 1000 * GETMSGTIMEOUT; // value is in milliseconds status = ProcessTimedMessage(p_reqMsg, p_respMsg, timeout); return status; } static char *BmcDesc(unsigned char drvtype) { /* return BMC Driver type description string */ char *msg; switch(drvtype) { case DRV_KCS: msg = "KCS"; break; /*BMC Sahalee KCS*/ case DRV_SMB: msg = "SMBus"; break; /*mBMC SMBus (SSIF)*/ default: msg = ""; } return(msg); } int get_ipmi_if(void) { /* Only care about Linux since ipmidir is not used for Windows. */ char *if_file = "/var/lib/ipmiutil/ipmi_if.txt"; char *if_file2 = "/usr/share/ipmiutil/ipmi_if.txt"; FILE *fp; char line[80]; char *p; char *r; int rv = ERR_NO_DRV; int i, j; ulong mybase = 0; int myinc = 1; // uchar *rgbase; fp = fopen(if_file,"r"); if (fp == NULL) fp = fopen(if_file2,"r"); if (fp == NULL) { /*error opening ipmi_if file*/ return -1; } else { /*read the data from the ipmi_if file*/ while ( (p = fgets(line,sizeof(line),fp)) != NULL) { if (strstr(line,"Interface type:") != NULL) { if (strstr(line,"KCS") != NULL) { g_DriverType = DRV_KCS; } else { g_DriverType = DRV_SMB; } } else if (strstr(line,"Base Address:") != NULL) { r = strchr(line,':'); i = strspn(++r," \t"); /* skip leading spaces */ r += i; j = strcspn(r," \t\r\n"); /* end at next whitespace */ r[j] = 0; /*stringify*/ /* convert the "0x0000000000000401" string to an int */ if (strncmp(r,"0x",2) == 0) { r += 2; j -= 2; } DBGP2("base addr 0x: %s, mybase=%x j=%d\n",r,mybase,j); mybase = strtol(r, NULL, 16); /*hex string is base 16*/ DBGP2("base addr 0x: %s, mybase=%x \n",r,mybase); } else if (strstr(line,"Register Spacing:") != NULL) { r = strchr(line,':'); i = strspn(++r," \t"); /* skip leading spaces */ r += i; j = strcspn(r," \t"); /* end at next whitespace */ r[j] = 0; /*stringify*/ myinc = atoi(r); } } fclose(fp); DBGP("ipmi_if: Driver = %d (%s), Base = 0x%04lx, Spacing = %d\n", g_DriverType,BmcDesc(g_DriverType),mybase,myinc); if (g_DriverType == DRV_SMB) { if (mybase & 0x0001) mybase -= 1; /* 0x0401 -> 0x0400 */ if (mybase != 0 && (mybase & 0x0F) == 0) { /* valid base address */ mBMC_baseAddr = mybase; BMC_base = mBMC_baseAddr; rv = 0; } } else { /*KCS*/ if (mybase != 0) { /* valid base address */ kcsBaseAddress = (mybase & 0x0000ffff); BMC_base = kcsBaseAddress; if (myinc > 1) kcs_inc = myinc; rv = 0; } } DBGP2("ipmi_if: BMC_base = 0x%04x, kcs_inc = %d, ret = %d\n", BMC_base, kcs_inc,rv); } return(rv); } static int set_lock_dir(void) { int rv = 0; FILE *fp; fp = fopen(lock_dir_file,"w"); if (fp == NULL) rv = -1; else { fclose(fp); rv = 0; } return(rv); } static int clear_lock_dir(void) { int rv = 0; rv = remove(lock_dir_file); /*same as unlink() */ if (fdebugdir) printf("clear_lock rv = %d\n",rv); return(rv); } static int check_lock_dir(void) { int rv = 0; #ifdef LOCK_OK FILE *fp; fp = fopen(lock_dir_file,"r"); if (fp == NULL) rv = 0; else { fclose(fp); rv = -1; /*error, lock file exists*/ } #endif return(rv); } int ipmi_open_direct(int fdebugcmd) { int status = 0; //char *dmsg = ""; int i; DBGP2("open_direct(%d) called\n",fdebugcmd); if (fdebugcmd) { fdebugdir = fdebugcmd; #if defined(LINUX_DEBUG) && !defined(ALONE) fsm_debug = fdebugcmd; #endif } /* Read ipmi_if config file data, if present. */ status = get_ipmi_if(); if (status == -1) { uchar iftype, iver, sa, inc; int mybase; /* Read SMBIOS to get IPMI struct */ status = get_IpmiStruct(&iftype,&iver,&sa,&mybase,&inc); if (status == 0) { if (iftype == 0x04) { g_DriverType = DRV_SMB; mBMC_baseAddr = mybase; } else { /*0x01==KCS*/ g_DriverType = DRV_KCS; BMC_base = mybase; if (sa == 0x20 && mybase != 0) { /*valid*/ kcsBaseAddress = mybase; kcs_inc = inc; } } DBGP("smbios: Driver=%d(%s), sa=%02x, Base=0x%04x, Spacing=%d\n", g_DriverType,BmcDesc(g_DriverType),sa,mybase,inc); } else { return ERR_NO_DRV; /*no SMBIOS IPMI record*/ } } #ifndef DOS /* superuser/root priv is required for direct I/Os */ i = geteuid(); /*direct is Linux only anyway*/ if (i > 1) { fprintf(stdout,"Not superuser (%d)\n", i); return ERR_NO_DRV; } #endif /* check lock for driverless interface */ i = check_lock_dir(); if (i != 0) { fprintf(stdout,"open_direct interface locked, %s in use\n", lock_dir_file); return ERR_NO_DRV; } /* Find the SMBIOS IPMI driver type, data */ status = ImbInit_dir(); DBGP2("open_direct Init status = %d\n",status); DBGP2("open_direct base=%x spacing=%d\n",BMC_base,kcs_inc); if (status == 0) { fDetectedIF = 1; /*Successfully detected interface */ /* Send a command to the IPMI interface */ if (!fjustpass) status = GetDeviceId(&g_bmcType,&g_ipmiVersion); if (status == 0) { char *typ; if (g_DriverType == DRV_SMB) typ = "smb"; else typ = "kcs"; set_driver_type(typ); } /* set lock for driverless interface */ i = set_lock_dir(); } DBGP("open_direct: status=%d, %s drv, ipmi=%d\n", status,BmcDesc(g_DriverType),g_ipmiVersion); return status; } int ipmi_close_direct(void) { int status = 0; #if defined(BSD) || defined(MACOS) || defined(HPUX) if (iofd >= 0) { close(iofd); iofd = -1; } #endif /* clear lock for driverless interface */ status = clear_lock_dir(); return status; } int ipmi_cmdraw_direct(UCHAR cmd, UCHAR netfn, UCHAR lun, UCHAR sa, UCHAR bus, UCHAR *pdata, int sdata, UCHAR *presp, int *sresp, UCHAR *pcc, char fdebugcmd) { BMC_MESSAGE sendMsg; BMC_MESSAGE respMsg; int status; int len = 0; if (g_bmcType == BMC_UNKNOWN) { /* User-specified a driver type, but need open */ status = ipmi_open_direct(fdebugcmd); } fdebugdir = fdebugcmd; if (sdata > IPMI_REQBUF_SIZE) return(LAN_ERR_BADLENGTH); if (fjustpass) { status = send_raw_kcs(pdata, sdata, presp, sresp); *pcc = 0; return(status); } sendMsg.Bus = bus; sendMsg.DevAdd = sa; sendMsg.NetFn = netfn; sendMsg.LUN = lun; sendMsg.Cmd = cmd; sendMsg.Len = sdata; if (sdata > 0) memcpy(sendMsg.Data,pdata,sdata); status = ProcessMessage(&sendMsg, &respMsg); if (status == STATUS_OK) { *pcc = respMsg.CompCode; if (respMsg.Len > 0) { len = respMsg.Len; if (len > *sresp) len = *sresp; } else len = 0; if (len > 0) memcpy(presp,respMsg.Data,len); *sresp = len; } return(status); } #ifndef ALONE int ipmi_cmd_direct(UINT16 icmd, UCHAR *pdata, int sdata, UCHAR *presp, int *sresp, UCHAR *pcc, char fdebugcmd) { UINT8 cmd, netfn, sa, lun, bus; int status; int i; fdebugdir = fdebugcmd; for (i = 0; i < NCMDS; i++) { if (ipmi_cmds[i].cmdtyp == icmd) { cmd = (icmd & 0x00ff); sa = ipmi_cmds[i].sa; bus = ipmi_cmds[i].bus; netfn = ipmi_cmds[i].netfn; lun = ipmi_cmds[i].lun; break; } } if (i >= NCMDS) { DBGP("ipmidir: icmd %04x not found, defaults used\n",icmd); cmd = (icmd & 0xFF); netfn = (icmd & 0xFF00) >> 8; sa = BMC_ADDR; lun = BMC_LUN; bus = 0; } status = ipmi_cmdraw_direct(cmd, netfn, lun, sa, bus, pdata, sdata, presp, sresp, pcc, fdebugcmd); return(status); } #endif static UINT8 CalculateChecksum(UINT8* p_buff, int length) { UINT8 sum = 0; int i; for (i = 0; i < length; i++) sum+= p_buff[i]; return (~sum) + 1; } static int GetDeviceId(UINT16 *bmcType, UINT16 *ipmiVersion) { int status = STATUS_OK; UINT16 thisBmcType = BMC_UNKNOWN; BMC_MESSAGE sendMsg; BMC_MESSAGE respMsg; DBGP2("open_direct: detecting interface, bmc: %X ver: %X drv=%s\n", g_bmcType, g_ipmiVersion, BmcDesc(g_DriverType)); // if the BMC type has not yet been detected - detect it if( g_bmcType == BMC_UNKNOWN ) { // Try sending the GetDeviceId command to the default interface sendMsg.DevAdd = BMC_ADDR; sendMsg.NetFn = NETFN_APP; sendMsg.LUN = BMC_LUN; sendMsg.Cmd = CMD_GET_DEVICE_ID; sendMsg.Len = 0; DBGP2("open_direct: Try Get_Device_ID with %s driver\n", BmcDesc(g_DriverType)); status = ProcessMessage(&sendMsg, &respMsg); if (status == STATUS_OK) { if (g_DriverType == DRV_KCS) thisBmcType = BMC_SAHALEE; else thisBmcType = BMC_MBMC_87431M; } else { /*error, switch interfaces*/ DBGP("open_direct: ProcessMessage(%s) error = %d\n", BmcDesc(g_DriverType),status); if (!fDetectedIF) { /* if not yet detected, try other IF type */ if (g_DriverType == DRV_KCS) { DBGP2("open_direct: Not KCS, try SSIF/SMBus\n"); g_DriverType = DRV_SMB; } else { DBGP2("open_direct: Not SSIF, try KCS\n"); g_DriverType = DRV_KCS; } } } /*end-else error*/ // If error, try again with the other interface if (thisBmcType == BMC_UNKNOWN) { // send the command via KCS/SMBus to get the IPMI version. status = ProcessMessage(&sendMsg, &respMsg); if (status == STATUS_OK) { if (g_DriverType == DRV_KCS) thisBmcType = BMC_SAHALEE; else thisBmcType = BMC_MBMC_87431M; } else { // If sending message fails status = ER_NO_BMC_IF; } } g_bmcType = thisBmcType; // if we contacted the BMC, decode its version if( status == STATUS_OK ) { if( g_bmcType == BMC_MBMC_87431M ) { // Decode the miniBMC productID } if( respMsg.Data[4] == 0x51 ) g_ipmiVersion = (UINT16)IPMI_VERSION_1_5; else if( respMsg.Data[4] == 0x02 ) g_ipmiVersion = IPMI_VERSION_2_0; } } /* endif unknown BMC */ // set the version info and leave *ipmiVersion = g_ipmiVersion; *bmcType = g_bmcType; DBGP2("open_direct: AFTER bmc: %X ver: %X\n", g_bmcType, g_ipmiVersion); return status; } //***************************************************************************** #if defined (WIN64) // Do Nothing for WIN64 as we are not using these functions here #else static int ProcessSendMessage(BMC_MESSAGE *p_reqMsg, BMC_MESSAGE *p_respMsg, const UINT8 bus, const UINT8 slave, const UINT32 timeout) { int status = STATUS_OK; BMC_MESSAGE sendReq; static UINT8 sendSeq = 1; static UINT8 incTestCount=0; BMC_MESSAGE reqMsg,respMsg; int retryCount; UINT32 i; UINT nRetryCount = 0; int testCount; // Windows will be using Async Imb request interface to poll for // messages in the BMC SMS message queue // format the send message packet sendReq.Cmd = SENDMESSAGE_CMD; sendReq.DevAdd = BMC_ADDR; sendReq.LUN = 0; sendReq.NetFn = NETFN_APP; sendReq.Data[0] = bus; sendReq.Data[1] = slave; // NetFn is the upper 6 bits of the data byte, the LUN is the lower two sendReq.Data[2] = ((p_reqMsg->NetFn << 2) | (p_reqMsg->LUN & 0x03)); sendReq.Data[3] = CalculateChecksum(&sendReq.Data[1], 2); sendReq.Data[4] = BMC_ADDR; // NetFn is the upper 6 bits of the data byte, the LUN is the lower two sendReq.Data[5] = ((sendSeq << 2) | (SMS_MSG_LUN & 0x03)); // sequence number = 1 << 2 and BMC message response lun = 0x02 sendReq.Data[6] = p_reqMsg->Cmd; // loop to copy the command data to the send message data format i = 0; for(i=0; i < p_reqMsg->Len; i++) sendReq.Data[7+i] = p_reqMsg->Data[i]; // create a checksum sendReq.Data[7+i] = CalculateChecksum(&sendReq.Data[4], p_reqMsg->Len + 3); // send data length plus the values from index 3 - 6 // send length plus 0 - 7 and checksum byte sendReq.Len = p_reqMsg->Len + 8; /* * Send the message with retries * For get Device ID & Read FRU data, retry less, in case * HSC/LCP is not present, */ if (p_reqMsg->NetFn != 0x08 ) retryCount = BMC_MAX_RETRIES+2; else retryCount = BMC_MAX_RETRIES+20; do { // send the message if( (status = ProcessMessage(&sendReq, p_respMsg)) == STATUS_OK ) { // some error, maybe because the controller was not ready yet. if( p_respMsg->CompCode == 0x83 ) { // Sleep for 1 second and try again sleep(1); incTestCount = 1; // true continue; // try again } else if( p_respMsg->CompCode == 0x82 ) { DBGP("ProcessSendMessage(sa=%02x,%02x,%02x) " "ccode=82 bus error\n", slave,p_reqMsg->NetFn,p_reqMsg->Cmd); status = ERGETTINGIPMIMESSAGE; break; // exit with error } else if( p_respMsg->CompCode != 0x00 ) continue; //break; // exit with error status = wait_for_SMS_flag(); /* new, added */ if (status == -1) DBGP("wait_for_SMS_flag timeout\n"); // Only for windows we use Imb Asyn interface for polling // For Unix we issue GetMessage command // issue a getmessage command reqMsg.DevAdd = BMC_ADDR; reqMsg.NetFn = NETFN_APP; reqMsg.LUN = BMC_LUN; reqMsg.Cmd = GETMESSAGE_CMD; reqMsg.Len = 0; nRetryCount = 0; testCount = 100; /* For HSC */ if (slave == 0x22 || incTestCount == 1) // true testCount=1000; /*added for LCP */ do { /* Loop here for the response with the correct * sequence number. */ if( (status = ProcessMessage( &reqMsg, &respMsg )) != 0 ) { DBGP("Breaking after Getmsg, Status is %d\n",status); break; } if( slave == 0x22 && p_reqMsg->Cmd == 0x04 ) { /* give debug if LCP ever gets here. */ DBGP("LCP get: cnt[%d,%d] seq[%02x,%02x] cc=%02x status=%u\n", testCount,retryCount, sendSeq, ((respMsg.Data[4] & 0xFC)>>2), respMsg.CompCode,status) ; return STATUS_OK; } if (respMsg.CompCode != 0) { DBGP2("get, cnt[test=%d] slave=%02x, cc==%02x\n", testCount,slave,respMsg.CompCode); /* Used to wait 1 ms via usleep(1000), but not needed. */ // usleep(1000); } } while(((respMsg.CompCode == 0x83 ||(respMsg.CompCode == 0x80)) && --testCount > (int) 0) || (respMsg.CompCode == 0x0 && ((respMsg.Data[4] & 0xFC) >> 2) != sendSeq) ); DBGP("get cnt[test=%d,retry=%d] seq[Send=0x%02x Recv=0x%02x] " "CompCode=0x%x status=%u\n", testCount,retryCount, sendSeq,((respMsg.Data[4] & 0xFC)>>2), respMsg.CompCode,status); if( (respMsg.CompCode == 0x00) && (status == STATUS_OK) && ((respMsg.Data[4] & 0xFC) >> 2 == sendSeq) ) { // format the GetMessage response (*p_respMsg) = (*p_reqMsg); // The first data byte is the channel number the message // was sent on p_respMsg->DevAdd = respMsg.Data[3]; p_respMsg->NetFn = respMsg.Data[1] >> 2; p_respMsg->LUN = respMsg.Data[4] & 0x03; p_respMsg->Cmd = respMsg.Data[5]; p_respMsg->CompCode = respMsg.Data[6]; // comp code p_respMsg->Len = respMsg.Len - 8; // the last data byte is the checksum if ( p_respMsg->CompCode == 0xCC) { DBGP2(" Cmd=%d Len=%d ccode=CC ", p_respMsg->Cmd, p_respMsg->Len); } for(i=0; i < p_respMsg->Len; i++) p_respMsg->Data[i] = respMsg.Data[7+i]; break; } } // this will retry the read the number of times in retryCount } while( --retryCount > 0 ); if( retryCount <= 0 ) status = ERGETTINGIPMIMESSAGE; /* Increment the sequence number * sequence number can't be greater 63 (6bit number), * so wrap the counter if it is */ ++sendSeq; if( sendSeq >= 64 ) sendSeq = 1; return status; } #endif /* All other than WIN64 */ /* #define MAX_KCS_LOOP 30000 *was 7000*/ /* Set a failsafe MAX KCS Loops to prevent infinite loop on status reg */ /* max was 7000, but need longer for ClearSEL cmd */ static int max_kcs_loop = 30000; /*means 300ms*/ static int max_sms_loop = 500; /*means 500ms*/ static int peak_loops = 0; int ipmi_set_max_kcs_loops(int ms) { max_kcs_loop = ms * 100; /*300 ms * 100 = 30000 loops*/ max_sms_loop = ms; return 0; } static int wait_for_SMS_flag(void) { int i = 0; while((_INB(STATUS_REG) & 0x04) == 0) { usleep(2 * 1000); /*sleep for 2 msec*/ i += 2; if ( i > max_sms_loop ) return -1; } return 0; } static int wait_for_IBF_clear(void) { int i = 0; while ((_INB(STATUS_REG) & 0x02) == 0x02) { if (i > 0 && (i % 100) == 0) usleep(1000); /*sleep for 1 msec*/ if (i > max_kcs_loop) { DBGP("wait_for_IBF_clear: max loop %d\n",i); return -1; // break; } i++; } if (i > peak_loops) peak_loops = i; return 0; } static int wait_for_OBF_set(void) { int i = 0; while ((_INB(STATUS_REG) & 0x01) == 0x00) { if (i > 0 && (i % 100) == 0) usleep(1000); /*sleep for 1 msec*/ if (i > max_kcs_loop) { DBGP("wait_for_OBF_set: max loop %d\n",i); return -1; // break; } i++; } if (i > peak_loops) peak_loops = i; return 0; } static inline int get_write_state(void) { if ((_INB(STATUS_REG) >> 6) != 0x02) return -1; return 0; } static inline int get_read_state(void) { if ((_INB(STATUS_REG) >> 6) != 0x01) return -1; return 0; } static inline int get_idle_state(void) { if ((_INB(STATUS_REG) >> 6) != 0x00) return -1; return 0; } UINT8 dummy2; static inline void clear_OBF(void) { dummy2 = _INB(DATA_IN_REG); } static int send_raw_kcs (UINT8 *rqData, int rqLen, UINT8 *rsData, int *rsLen ) { int length; unsigned char dummy; unsigned char rx_data[64]; int rxbuf_len; int rv; if (fdebugdir) { int cnt; DBGP("send_raw_kcs: "); for ( cnt=0; cnt < rqLen ; cnt++) DBGP(" %02x",rqData[cnt]); DBGP("\n"); } wait_for_IBF_clear(); clear_OBF(); _OUTB(WR_START,COMMAND_REG); rv = wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); if (rv != 0) return LAN_ERR_SEND_FAIL; for(length = 0;length < rqLen-1;length++) { _OUTB(rqData[length],DATA_OUT_REG); wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); } _OUTB(WR_END,COMMAND_REG); wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); _OUTB(rqData[length],DATA_OUT_REG); /* write phase complete, start read phase */ rxbuf_len = *rsLen; *rsLen = 0; while(*rsLen <= IPMI_RSPBUF_SIZE) { wait_for_IBF_clear(); if (get_read_state() != 0) { if (get_idle_state() != 0) { DBGP2("not idle in rx_data (%02x)\n",_INB(STATUS_REG)); // clear_lock_dir(); return LAN_ERR_RECV_FAIL; } else { rv = wait_for_OBF_set(); if (rv != 0) return LAN_ERR_RECV_FAIL; dummy = _INB(DATA_IN_REG); /* done, copy the data */ for (length=0;length < *rsLen;length++) rsData[length] = rx_data[length]; return ACCESS_OK; } } else { rv = wait_for_OBF_set(); if (rv != 0) return LAN_ERR_RECV_FAIL; rx_data[*rsLen] = _INB(DATA_IN_REG); DBGP2("rx_data[%d] is 0x%x\n",*rsLen,rx_data[*rsLen]); _OUTB(READ_BYTE,DATA_IN_REG); (*rsLen)++; } if (*rsLen > rxbuf_len) { DBGP("ipmidir: rx buffer overrun, size = %d\n",rxbuf_len); break; /*stop if user buffer max*/ } } /*end while*/ return ACCESS_OK; } /* * SendTimedImbpRequest_kcs - write bytes to KCS interface, read response * The bytes are written in this order: * 1 netfn * 2 cmdType * 3-N data, if any */ int SendTimedImbpRequest_kcs (IMBPREQUESTDATA *requestData, unsigned int timeout, UINT8 *resp_data, int *respDataLen, unsigned char *compCode) { /*SendTimedImb for KCS*/ int length; unsigned char dummy; unsigned char rx_data[64]; int rxbuf_len, rv; if (fdebugdir) { int cnt; DBGP("Send Netfn=%02x Cmd=%02x, raw: %02x %02x %02x %02x", requestData->netFn, requestData->cmdType, requestData->busType, requestData->rsSa, (requestData->netFn<<2), requestData->cmdType); for ( cnt=0; cnt < requestData->dataLength ; cnt++) DBGP(" %02x",requestData->data[cnt]); DBGP("\n"); } rv = wait_for_IBF_clear(); clear_OBF(); if (rv != 0) return LAN_ERR_SEND_FAIL; _OUTB(WR_START,COMMAND_REG); rv = wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); if (rv != 0) return LAN_ERR_SEND_FAIL; _OUTB((requestData->netFn << 2),DATA_OUT_REG); rv = wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); if (requestData->dataLength == 0) { _OUTB(WR_END,COMMAND_REG); wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); _OUTB(requestData->cmdType,DATA_OUT_REG); } else { _OUTB(requestData->cmdType,DATA_OUT_REG); wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); for(length = 0;length < requestData->dataLength-1;length++) { _OUTB(requestData->data[length],DATA_OUT_REG); wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); } _OUTB(WR_END,COMMAND_REG); wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); _OUTB(requestData->data[length],DATA_OUT_REG); } /********************************** WRITE PHASE OVER ***********************/ #ifdef TEST_ERROR if (fdebugdir == 5) { /*introduce an error test case*/ printf("Aborting after KCS write, before read\n"); return(rv); } #endif // length = 0; // usleep(100000); /********************************** READ PHASE START ***********************/ rxbuf_len = *respDataLen; *respDataLen = 0; while(*respDataLen <= IPMI_RSPBUF_SIZE) { wait_for_IBF_clear(); if (get_read_state() != 0) { if (get_idle_state() != 0) { DBGP2("not idle in rx_data (%02x)\n",_INB(STATUS_REG)); // clear_lock_dir(); return LAN_ERR_RECV_FAIL; } else { rv = wait_for_OBF_set(); if (rv != 0) { return LAN_ERR_RECV_FAIL; } dummy = _INB(DATA_IN_REG); /* done, copy the data, if valid */ if (*respDataLen < 3) { /* data not valid, no cc */ (*respDataLen) = 0; *compCode = 0xCA; /*cannot return #bytes*/ // clear_lock_dir(); return LAN_ERR_TIMEOUT; } else { /*valid*/ requestData->netFn = rx_data[0]; requestData->cmdType = rx_data[1]; *compCode = rx_data[2]; (*respDataLen) -= 3; for (length=0;length < *respDataLen;length++) resp_data[length] = rx_data[length+3]; } DBGP2("ipmidir: peak_loops = %d\n",peak_loops); return ACCESS_OK; } } else { rv = wait_for_OBF_set(); if (rv != 0) { return LAN_ERR_RECV_FAIL; } rx_data[*respDataLen] = _INB(DATA_IN_REG); DBGP2("rx_data[%d] is 0x%x\n",*respDataLen,rx_data[*respDataLen]); _OUTB(READ_BYTE,DATA_IN_REG); (*respDataLen)++; } if (*respDataLen > rxbuf_len) { DBGP("ipmidir: rx buffer overrun, size = %d\n",rxbuf_len); break; /*stop if user buffer max*/ } } /*end while*/ return ACCESS_OK; } /* end SendTimedImbpRequest_kcs */ static int ProcessTimedMessage(BMC_MESSAGE *p_reqMsg, BMC_MESSAGE *p_respMsg, const UINT32 timeout) { int status = STATUS_OK; IMBPREQUESTDATA requestData = {0}; int respDataLen = IPMI_RSPBUF_SIZE; UINT8 compCode = 0; // static UINT8 sendSeq = 1; // UINT8 buff[DATA_BUF_SIZE] = {0}; ACCESN_STATUS accessn; int i, j; j = p_reqMsg->Len; if (j > IPMI_REQBUF_SIZE) return(LAN_ERR_BADLENGTH); // Initialize Response Message Data for(i = 0; i < IPMI_RSPBUF_SIZE; i++) { p_respMsg->Data[i] = 0; } /* show the request */ DBGP("ipmidir Cmd=%02x NetFn=%02x Lun=%02x Sa=%02x Data(%d): ", p_reqMsg->Cmd, p_reqMsg->NetFn, p_reqMsg->LUN, p_reqMsg->DevAdd, j); for (i=0; iData[i]); DBGP("\n"); j = _IOPL(3); if (j != 0) { DBGP("ipmi_direct: iopl errno = %d\n",errno); return(errno); } // Initializes Request Message // Call into IPMI if (p_reqMsg->DevAdd == 0x20) { requestData.cmdType = p_reqMsg->Cmd; requestData.rsSa = 0x20; requestData.busType = 0; requestData.netFn = p_reqMsg->NetFn; requestData.rsLun = p_reqMsg->LUN; requestData.data = p_reqMsg->Data; requestData.dataLength = (int)p_reqMsg->Len; if (g_DriverType == DRV_KCS) /*KCS*/ accessn = SendTimedImbpRequest_kcs(&requestData, timeout, p_respMsg->Data, &respDataLen, &compCode); else if (g_DriverType == DRV_SMB) /*SMBus*/ accessn = SendTimedImbpRequest_ssif(&requestData, timeout, p_respMsg->Data, &respDataLen, &compCode); else { /* should never happen */ printf("ipmi_direct: g_DriverType invalid [%d]\n",g_DriverType); return(ERR_NO_DRV); } status = accessn; // Return Response Message p_respMsg->DevAdd = p_reqMsg->DevAdd; p_respMsg->NetFn = requestData.netFn; p_respMsg->LUN = p_reqMsg->LUN; p_respMsg->Cmd = requestData.cmdType; p_respMsg->CompCode = compCode; p_respMsg->Len = respDataLen; } else { /*DevAdd != 0x20*/ status = ProcessSendMessage(p_reqMsg, p_respMsg, p_reqMsg->Bus, p_reqMsg->DevAdd,10000); DBGP2("ProcessSendMessage(cmd=%02x,rs,sa=%02x,10000) = %d\n", p_reqMsg->Cmd,p_reqMsg->DevAdd,status); } /* validate the response data length */ if (p_respMsg->Len > IPMI_RSPBUF_SIZE) p_respMsg->Len = IPMI_RSPBUF_SIZE; /* show the response */ j = p_respMsg->Len; DBGP("ipmidir Resp(%x,%x): status=%d cc=%02x, Data(%d): ", (p_respMsg->NetFn >> 2), p_respMsg->Cmd, status,p_respMsg->CompCode, j); if (status == 0) for (i=0; iData[i]); DBGP("\n"); return status; } /* * ImbInit_dir * Uses SMBIOS to determine the driver type and base address. * It also checks the status register if KCS. */ int ImbInit_dir(void) { uchar v = 0xff; /* Read SMBIOS to get IPMI struct */ DBGP2("ImbInit: BMC_base = 0x%04x\n",BMC_base); if (BMC_base == 0) { /*use get_IpmiStruct routine from mem_if.c */ uchar iftype, iver, sa, inc; int mybase, status; char *ifstr; status = get_IpmiStruct(&iftype,&iver,&sa,&mybase,&inc); if (status == 0) { if (iftype == 0x04) { g_DriverType = DRV_SMB; ifstr = "SSIF"; mBMC_baseAddr = mybase; } else /*0x01==KCS*/ { g_DriverType = DRV_KCS; BMC_base = mybase; ifstr = "KCS"; if (sa == BMC_SA && mybase != 0) { /*valid*/ kcsBaseAddress = mybase; kcs_inc = inc; } } DBGP("SMBIOS IPMI Record found: type=%s sa=%02x base=0x%04x spacing=%d\n", ifstr, sa, mybase, inc); } } /* Use KCS here. There are no known SMBus implementations on 64-bit */ if (BMC_base == 0) { DBGP("No IPMI Data Structure Found in SMBIOS Table,\n"); #ifdef TRY_KCS g_DriverType = DRV_KCS; BMC_base = kcsBaseAddress; DBGP("Continuing with KCS on Default Port 0x%04x\n",kcsBaseAddress); #else printf("No IPMI interface detected...Exiting\n"); return ERR_NO_DRV; #endif } #if defined(BSD) || defined(MACOS) || defined(HPUX) iofd = open("/dev/io",O_RDWR); if (iofd < 0) { printf("Cannot open /dev/io...Exiting\n"); return ERR_NO_DRV; } #endif if (g_DriverType == DRV_SMB) { /* Perhaps add controller type in ipmi_if.txt (?)*/ /* Intel SSIF: 0x0540=SJR, 0x0400=STP */ if (mBMC_baseAddr == 0x540 || mBMC_baseAddr == 0x400) SMBChar.Controller = INTEL_SMBC; else /*else try ServerWorks*/ SMBChar.Controller = SW_SMBC; SMBChar.baseAddr = mBMC_baseAddr; DBGP("BMC SSIF/SMBus Interface at i2c=%02x base=0x%04x\n", mBMCADDR,mBMC_baseAddr); } if (g_DriverType == DRV_KCS) { v = _IOPL(3); v = _INB(STATUS_REG); DBGP2("inb(%x) returned %02x\n",STATUS_REG,v); if (v == 0xff) { printf("No Response from BMC...Exiting\n"); return ERR_NO_DRV; } DBGP("BMC KCS Initialized at 0x%04x\n",kcsBaseAddress); } return STATUS_OK; } int SendTimedImbpRequest_ssif ( IMBPREQUESTDATA *requestData, unsigned int timeout, UINT8 *resp_data, int *respDataLen, unsigned char *compCode) { /* SendTimedImb for SMBus */ unsigned char rq[IPMI_REQBUF_SIZE+35] = {0,}; /*SIZE + MAX_ISA_LENGTH=35*/ unsigned char rp[IPMI_RSPBUF_SIZE+35] = {0,}; /*SIZE + MAX_ISA_LENGTH=35*/ unsigned int i, rpl=0; int status; int respMax, rlen; i = _IOPL(3); rq[0] = ((requestData->netFn << 2) | (requestData->rsLun & 0x03)); rq[1] = requestData->cmdType; if (sizeof(rq) < (requestData->dataLength + 2)) return(LAN_ERR_BADLENGTH); for (i=0;i<=(unsigned int)requestData->dataLength;i++) rq[i+2] = requestData->data[i]; respMax = *respDataLen; if (respMax == 0) respMax = IPMI_RSPBUF_SIZE; status = SendmBmcRequest(rq,requestData->dataLength+2,rp,&rpl,0); if (status == IMB_SEND_ERROR) { *respDataLen = 0; return LAN_ERR_SEND_FAIL; } if (rpl < 3) { *respDataLen = 0; *compCode = 0xCA; /*cannot return #bytes*/ return LAN_ERR_TIMEOUT; } else { rlen = rpl-3; /* Chop off netfn/LUN , compcode, command */ if (rlen > respMax) rlen = respMax; *respDataLen = rlen; *compCode = rp[2]; for (i = 0; i < rlen; i++) resp_data[i] = rp[i+3]; } return ACCESS_OK; } int SendmBmcRequest ( unsigned char* request, UINT32 reqLength, unsigned char* response, UINT32 * respLength, UINT32 ipmiOldFlag ) { int retries = 5; /* Send Request - Retry 5 times at most */ do{ if (SendRequest(request, reqLength, &SMBChar) == 0) break; } while (0 < retries--); if (retries <= 0) { return IMB_SEND_ERROR; } /* Read Response - Retry 5 times at most */ retries = 5; do{ if ((*respLength = ReadResponse(response, &SMBChar))!=(-1)) { break; // Success } }while (0 < retries--); if (retries <= 0) { return IMB_SEND_ERROR; } return IMB_SUCCESS; } static int SendRequest(unsigned char* req, int length, struct SMBCharStruct* smbChar) { UINT8 data = 0; // unsigned char* msgBuf = req; int i; UINT8 status = 0; // Delay of 50 ms before request is sent usleep(100000); // Handle Intel & ServerWorks Chipsets // Clear all status bits, Host Status Register switch (smbChar->Controller) { // Intel Status Register case INTEL_SMBC: status = ICH_HST_STA_ALL_ERRS|ICH_HST_STA_INTR|ICH_HST_STA_BYTE_DONE_STS; break; // ServerWorks Status Register case SW_SMBC: status = ICH_HST_STA_ALL_ERRS|ICH_HST_STA_INTR; break; }// End of Switch // Status Register WritePortUchar( (((smbChar->baseAddr))+ICH_HST_STA), status); // Block protocol, Host Control Register WritePortUchar(((smbChar->baseAddr)+ICH_HST_CNT), (UINT8)(ICH_HST_CNT_SMB_CMD_BLOCK)); // IPMI command, Host Command Register WritePortUchar(((smbChar->baseAddr)+ICH_HST_CMD), (UINT8)(0x02)); // Slave address, Host Address Register WritePortUchar(((smbChar->baseAddr)+ICH_XMIT_SLVA), (UINT8)(mBMCADDR)); // Block length, Host DATA0 Register WritePortUchar(((smbChar->baseAddr)+ICH_D0), (UINT8)(length)); // Initialize timer switch (smbChar->Controller) { // Handle Intel Chipset case INTEL_SMBC: // the first byte WritePortUchar(((smbChar->baseAddr)+ICH_BLOCK_DB), *(UINT8 *)((UINT8 *)req )); // Block protocol and Start, Host Control Register WritePortUchar(((smbChar->baseAddr)+ICH_HST_CNT), ICH_HST_CNT_START | ICH_HST_CNT_SMB_CMD_BLOCK); // Send byte by byte for ( i = 1; i < length; i++ ) { // OsSetTimer(&SendReqTimer); * Start timer * do { // Read host status register ReadPortUchar((smbChar->baseAddr+ICH_HST_STA), &data); // if (OsTimerTimedout(&SendReqTimer)) return -1; // Any error or Interrupt bit or byte done bit set ? } while ((data & status) == 0); // OsCancelTimer(&SendReqTimer); * End Timer * // Check for byte completion in block transfer if ((data & ICH_HST_STA_BYTE_DONE_STS) != ICH_HST_STA_BYTE_DONE_STS) break; // Write next byte WritePortUchar(((smbChar->baseAddr)+ICH_BLOCK_DB), *(UINT8 *)((UINT8 *)req + i)); // Clear status bits, Host Status Register WritePortUchar((smbChar->baseAddr), (UINT8)(data & status)); } // End of for - Send byte by byte break; // End of Intel Chipset Handling // Handle ServerWorks Chipset case SW_SMBC: // Block length, Host DATA1 Register WritePortUchar(((smbChar->baseAddr)+ICH_D1), (UINT8)(length)); // Reset block inex ReadPortUchar(((smbChar->baseAddr)+ICH_HST_CNT), &data); // Put all bytes of the message to Block Data Register for ( i = 0; i < length; i++ ) WritePortUchar(((smbChar->baseAddr)+ICH_BLOCK_DB), *(UINT8 *)((UINT8 *)req + i)); // Block protocol and Start, Host Control Register WritePortUchar(((smbChar->baseAddr)+ICH_HST_CNT), ICH_HST_CNT_START | ICH_HST_CNT_SMB_CMD_BLOCK); // OsSetTimer(&SendReqTimer); * Start timer * do { // Read host status register ReadPortUchar((smbChar->baseAddr+ICH_HST_STA), &data); // if (OsTimerTimedout(&SendReqTimer)) return -1; } while ((data & status) == 0); // Any error or Interrupt bit set ? // OsCancelTimer(&SendReqTimer); * End Timer * break; // End of ServerWorks Chipset Handling } // End of Switch Controller // Clear status bits, Host Status Register WritePortUchar((smbChar->baseAddr), (UINT8)(data & status)); if (data & ICH_HST_STA_ALL_ERRS) return -1; // Success return 0; } static int ReadResponse( unsigned char* resp, struct SMBCharStruct * smbChar) { UINT8 data, dummy, length, status = 0; UINT8 * msgBuf = (UINT8 *) resp; int i; //, timeout =0; // os_timer_t SendReqTimer; // Delay current thread - time to delay in uSecs // 100 msec = 100000 microsec usleep(100000); // Handle Intel & ServerWorks Chipsets switch (smbChar->Controller) { case INTEL_SMBC: status = ICH_HST_STA_ALL_ERRS|ICH_HST_STA_INTR|ICH_HST_STA_BYTE_DONE_STS; break; case SW_SMBC: status = ICH_HST_STA_ALL_ERRS|ICH_HST_STA_INTR; break; } // End of Switch WritePortUchar(((smbChar->baseAddr)+ICH_HST_STA), status); // Block protocol, Host Control Register WritePortUchar(((smbChar->baseAddr)+ICH_HST_CNT), ICH_HST_CNT_SMB_CMD_BLOCK); // Slave address, Host Address Register WritePortUchar(((smbChar->baseAddr)+ICH_XMIT_SLVA), (UINT8)(mBMCADDR |ICH_XMIT_SLVA_READ)); // IPMI command, Host Command Register WritePortUchar(((smbChar->baseAddr)+ICH_HST_CMD), 0x03); // Reset block index ReadPortUchar(((smbChar->baseAddr)+ICH_HST_CNT), &data); // Block protocol and Start, Host Control Register WritePortUchar(((smbChar->baseAddr)+ICH_HST_CNT), ICH_HST_CNT_START | ICH_HST_CNT_SMB_CMD_BLOCK); // Initialize timer do { // Read host status register ReadPortUchar((smbChar->baseAddr+ICH_HST_STA), &data); } while ((data & status) == 0); // Any error or Interrupt bit set ? // End Timer // Clear status bits, Host Status Register WritePortUchar((smbChar->baseAddr), (UINT8)(data & status)); if (data & ICH_HST_STA_ALL_ERRS) return -1; // Block length, Host DATA0 Register ReadPortUchar(((smbChar->baseAddr)+ICH_D0), &length); /* check recv length > MAX (35) */ if (length > MAX_ISA_LENGTH) length = MAX_ISA_LENGTH; switch (smbChar->Controller) { case INTEL_SMBC: // Read the first byte ReadPortUchar((smbChar->baseAddr+ICH_BLOCK_DB), &(msgBuf[0])); // Put all bytes of the message to Block Data Register for ( i = 1; i < length; i++ ) { if (i == (length-1)) { // Set Last Byte bit ReadPortUchar(((smbChar->baseAddr)+ICH_HST_CNT),&dummy); WritePortUchar(((smbChar->baseAddr)+ICH_HST_CNT), (UINT8)(dummy | ICH_HST_CNT_LAST_BYTE)); } // Clear status bits, Host Status Register WritePortUchar((smbChar->baseAddr), (UINT8)(data & status)); do { // Read host status register ReadPortUchar((smbChar->baseAddr+ICH_HST_STA), &data); } while ((data & status) == 0); // Any error or Interrupt bit set ? if (data & ICH_HST_STA_ALL_ERRS) return -1; ReadPortUchar((smbChar->baseAddr+ICH_BLOCK_DB), &(msgBuf[i])); } break; case SW_SMBC: // Put all bytes of the message to Block Data Register for ( i = 0; i < length; i++ ) { ReadPortUchar((smbChar->baseAddr+ICH_BLOCK_DB), &(msgBuf[i])); } break; } /* end of switch */ if (data & ICH_HST_STA_ALL_ERRS) return -1; return length; } #endif /* end ipmidir.c */ ipmiutil-3.1.5/util/icmd.c0000644000076400007640000003017013566765324015514 0ustar mgportalloggers/* * icmd.c * * This tool takes command line input as an IPMI command. * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2003-2006 Intel Corporation. * Copyright (c) 2009 Kontron America, Inc. * * 03/30/04 Andy Cress - created * 04/08/04 Andy Cress - display response data, changed usage order * 05/05/04 Andy Cress - call ipmi_close before exit * 11/01/04 Andy Cress - add -N / -R for remote nodes * 12/08/04 Andy Cress v1.5 changed usage order, moved bus to first byte, * gives better compatibility with ipmicmd.exe. * 04/13/06 Andy Cress v1.6 fixed istart for -U -R */ /*M* Copyright (c) 2006, Intel Corporation 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 Corporation 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*/ #if defined(EFI) #ifndef NULL #define NULL 0 #endif #include #include #include #include #else /* Linux, Solaris, BSD, Windows */ #include #include #include #include #include #include #ifdef WIN32 #include "getopt.h" #elif defined(DOS) #include #include "getopt.h" #elif defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include "ipmicmd.h" extern void ipmi_lan_set_timeout(int ipmito, int tries, int pingto); /* * Global variables */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil cmd"; #else static char * progver = "3.08"; static char * progname = "icmd"; #endif static char fdebug = 0; static char fquiet = 0; static char fset_mc = 0; static char ftest = 0; static int vend_id; static int prod_id; static char fmBMC = 0; static char fdecimal = 0; extern int fjustpass; /*see ipmicmd.c*/ #define PRIVATE_BUS_ID 0x03 // w Sahalee, the 8574 is on Private Bus 1 #define PERIPHERAL_BUS_ID 0x24 // w mBMC, the 8574 is on the Peripheral Bus #define MAXRQLEN 64 #define MAXRSLEN 200 static char usagemsg[] = "Usage: %s [-kqmsxEFNPRTUV] bus rsSa netFn/lun cmd [data bytes]\n"; static uchar busid = PRIVATE_BUS_ID; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = 0; /*0x20*/ static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static int send_icmd(uchar *cmd, int len) { uchar responseData[MAXRSLEN]; int responseLength; uchar completionCode; int ret, i; uchar netfn, lun; ushort icmd; /* icmd format: 0=bus, 1=rsSa, 2=netFn/lun, 3=cmd, 4-n=data */ netfn = cmd[2] >> 2; lun = cmd[2] & 0x03; icmd = cmd[3] + (netfn << 8); if (fjustpass) { ret = ipmi_cmdraw(IPMB_SEND_MESSAGE,NETFN_APP,BMC_SA,0,0, &cmd[0],(uchar)(len), responseData, &responseLength, &completionCode, fdebug); } else { responseLength = sizeof(responseData); if (g_addrtype == ADDR_IPMB) { /* && (g_sa != 0) */ /* if -m used, do ipmi_cmd_mc for IPMB commands */ ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); ret = ipmi_cmd_mc(icmd, &cmd[4], (uchar)(len-4), responseData, &responseLength, &completionCode, fdebug); ipmi_restore_mc(); } else { /* ipmi_cmdraw: bus, cmd, netfn, sa, lun, pdata, ... */ ret = ipmi_cmdraw(cmd[3], netfn, cmd[1], cmd[0], lun, &cmd[4], (uchar)(len-4), responseData, &responseLength, &completionCode, fdebug); } } if (ret < 0) { printf("ipmi_cmd: ret = %d %s\n",ret,decode_rv(ret)); return(ret); } else if ((ret != 0) || (completionCode != 0)) { printf("ipmi_cmd: ret = %d, ccode %02x %s\n", ret, completionCode, decode_cc(icmd,completionCode)); return(ret); } else if (responseLength > 0) { /* show the response data */ printf("respData[len=%d]: ",responseLength); for (i = 0; i < responseLength; i++) printf("%02x ",responseData[i]); printf("\n"); } return(ret); } /*end send_icmd()*/ #ifdef METACOMMAND int i_cmd(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int ret = 0; int c; uchar devrec[17]; uchar cmdbuf[MAXRQLEN]; int maxlen = MAXRQLEN; int i, j, istart, cmdlen; int fskipdevid = 0; int fprivset = 0; int cmdmin; char *s1; istart = 1; while ( (c = getopt( argc, argv,"djkm:qst:xp:N:P:R:U:EF:J:T:V:YZ:?")) != EOF ) switch(c) { case 'j': /* just pass the bytes to KCS */ fjustpass = 1; break; case 'd': /* decimal command bytes, skipping bus and sa, which matches 'ipmitool raw' format. */ fdecimal = 1; break; 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 'q': fquiet = 1; fskipdevid = 1; break; /* minimal output */ case 's': fskipdevid = 1; break; /* skip devid */ case 't': /* set IPMI timeout for ipmilan, usu 2 * 4 = 8 sec */ i = atoi(optarg); if (i >= 2) { j = i / 2; i = j; } else { i = 1; j = 1; } ipmi_lan_set_timeout(i,j,1); break; case 'k': /* check for IPMI access */ ftest = 1; break; case 'x': fdebug = 1; break; /* debug messages */ case 'V': /* priv level */ fprivset = 1; case 'p': /* port */ 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: printf("%s ver %s\n", progname,progver); printf(usagemsg, progname); printf(" where -x shows eXtra debug messages\n"); printf(" -d decimal input, matching ipmitool syntax\n"); printf(" -k check for IPMI access\n"); printf(" -m002000 specific MC (bus 00,sa 20,lun 00)\n"); printf(" -q quiet mode, with minimal headers\n"); printf(" -s skips the GetDeviceID command\n"); print_lan_opt_usage(1); ret = ERR_USAGE; goto do_exit; } if (ftest) { ret = ipmi_getdeviceid(devrec,16,fdebug); if (ret == 0) { /*check if a driver is loaded, or direct*/ i = get_driver_type(); printf("IPMI access is ok, driver type = %s\n",show_driver_type(i)); if ((i == DRV_KCS) || (i == DRV_SMB)) printf("Using driverless method\n"); } else printf("IPMI access error %d\n",ret); goto do_exit; } if (!fquiet) { printf("%s ver %s\n", progname,progver); printf("This is a test tool to compose IPMI commands.\n"); printf("Do not use without knowledge of the IPMI specification.\n"); } istart = optind; if (fdebug) printf("icmd: argc=%d istart=%d\n",argc,istart); if (fset_mc == 1) { /* target a specific MC via IPMB (usu a picmg blade) */ ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); } else g_sa = BMC_SA; for (i = 0; i < istart; i++) { argv++; argc--; } if (argc < maxlen) maxlen = argc; if (fdebug) printf("icmd: len=%d, cmd byte0=%s\n",maxlen,argv[0]); if (fdecimal) { uchar b; cmdbuf[0] = g_bus; cmdbuf[1] = g_sa; for (i = 0; i < maxlen; i++) { if (argv[i][0] == '0' && argv[i][1] == 'x') /*0x00*/ b = htoi(&argv[i][2]); else b = atob(argv[i]); /*decimal default, or 0x00*/ if (i == 0) { /*special handling for netfn */ cmdbuf[i+2] = (b << 2) | (g_lun & 0x03); } else cmdbuf[i+2] = b; } cmdlen = i + 2; } else { for (i = 0; i < maxlen; i++) { cmdbuf[i] = htoi(argv[i]); } cmdlen = i; } if (fdebug) { printf("ipmi_cmd: "); for (i = 0; i < cmdlen; i++) printf("%02x ",cmdbuf[i]); printf("\n"); } if (is_remote() && fprivset == 0) { /*IPMI LAN, privilege not set by user*/ /* commands to other MCs require admin privilege */ // if ((g_sa != BMC_SA) || (cmdbuf[1] != BMC_SA)) parse_lan_options('V',"4",0); } if (!fskipdevid) { /* * Check the Device ID to determine which bus id to use. */ ret = ipmi_getdeviceid(devrec,16,fdebug); if (ret != 0) { goto do_exit; } else { uchar b, j; char *pstr; if (fdebug) { printf("devid: "); for (j = 0; j < 16; j++) printf("%02x ",devrec[j]); printf("\n"); } b = devrec[4] & 0x0f; j = devrec[4] >> 4; prod_id = devrec[9] + (devrec[10] << 8); vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16); if (vend_id == VENDOR_NSC) { /* NSC = 0x000322 */ fmBMC = 1; /*NSC miniBMC*/ } else if (vend_id == VENDOR_INTEL) { /* Intel = 0x000157 */ switch(prod_id) { case 0x4311: /* Intel NSI2U*/ fmBMC = 1; /* Intel miniBMC*/ break; case 0x003E: /* NSN2U or CG2100*/ set_max_kcs_loops(URNLOOPS); /*longer for cmds (default 300)*/ break; default: break; } } if (fmBMC) { /*NSC mini-BMC*/ pstr = "mBMC"; busid = PERIPHERAL_BUS_ID; /*used by alarms MWR*/ } else { /* treat like Intel Sahalee = 57 01 */ pstr = "BMC"; busid = PRIVATE_BUS_ID; /*used by alarms MWR*/ } printf("-- %s version %x.%x, IPMI version %d.%d \n", pstr, devrec[2], devrec[3], b, j); } // ret = ipmi_getpicmg( devrec, sizeof(devrec),fdebug); // if (ret == 0) fpicmg = 1; } /*endif skip devid*/ if (fjustpass) cmdmin = 2; else cmdmin = 4; if (cmdlen < cmdmin) { printf("command length (%d) is too short\n",cmdlen); printf(usagemsg, progname); } else { ret = send_icmd(cmdbuf,cmdlen); if (!fquiet) printf("send_icmd ret = %d\n",ret); } do_exit: ipmi_close_(); // if (!fquiet) show_outcome(progname,ret); return (ret); } /* end main()*/ /* end icmd.c */ ipmiutil-3.1.5/util/oem_supermicro.h0000644000076400007640000000514213566765324017636 0ustar mgportalloggers/* * oem_supermicro.h * SuperMicro OEM command functions * *--------------------------------------------------------------------- */ /*M* Copyright (c) 2013 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 Kontron 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*/ #define SUPER_NETFN_OEM 0x30 #define SUPER_CMD_BMCSTATUS 0x70 #define SUPER_CMD_RESET_INTRUSION 0x03 #define SUPER_NETFN_OEMFW 0x3C /*for SuperMicro/Peppercon*/ #define SUPER_CMD_OEMFWINFO 0x20 int oem_supermicro_get_bmc_status(uchar *sts); int oem_supermicro_set_bmc_status(uchar sts); int oem_supermicro_get_health(char *pstr, int sz); int oem_supermicro_get_firmware_info(uchar *info); int oem_supermicro_get_firmware_str(char *pstr, int sz); int oem_supermicro_reset_intrusion(void); int oem_supermicro_get_lan_port(uchar *val); int oem_supermicro_set_lan_port(uchar val); char *oem_supermicro_lan_port_string(uchar val); int decode_sensor_supermicro(uchar *sdr,uchar *reading,char *pstring, int slen, int fsimple, char fdbg); int decode_mem_supermicro(int prod, uchar b2, uchar b3, char *desc, int *psz); int decode_sel_supermicro(uchar *evt, char *outbuf, int outsz, char fdesc, char fdebug); /* end oem_supermicro.h */ ipmiutil-3.1.5/util/ipmiutil2.mak0000644000076400007640000003364613566765324017057 0ustar mgportalloggers# This makefile will build the ipmiutil util directory (without lanplus) # # First download getopt.c getopt.h # Then download and build openssl for Windows # LIBC_RT=libcmt.lib /NODEFAULTLIB:"msvcirt.lib" # LIBC_RT=msvcrt.lib /NODEFAULTLIB:"msvcirt.lib" MARCH=IX86 #MARCH=IX86 # The ipmiutil directory SRC_D=. LIB_D=..\lib L2_D=$(LIB_D)\lanplus L3_D=$(LIB_D)\lanplus\inc INSTALLTOP=install TMP_D=tmp INC=/I$(SRC_D) /I$(L2_D) /I$(L3_D) CMD_OBJ = getopt.obj ipmicmd.obj imbapi.obj md5.obj md2.obj \ ipmilan.obj ipmims.obj subs.obj CMD_OBJ = $(CMD_OBJ) ipmilanplus.obj # To remove lanplus support use the empty LANPLUS variables L2_OBJ= L2_LIB= LF_LANPLUS= CF_LANPLUS= #L2_OBJ = $(L2_D)\helper.obj $(L2_D)\ipmi_strings.obj $(L2_D)\lanplus.obj \ # $(L2_D)\lanplus_crypt_impl.obj $(L2_D)\lanplus_dump.obj \ # $(L2_D)\lanplus_strings.obj $(L2_D)\lanplus_crypt.obj #L2_LIB=lanplus.lib #LF_LANPLUS=/LIBPATH:$(LIB_D) $(L2_OBJ) ssleay32.lib libeay32.lib #CF_LANPLUS=/D HAVE_LANPLUS # Set your compiler options # To remove any GPL dependencies, use the CF_EX line with NON_GPL # CFLAGS_O=/W3 /O2 /Zi /MD /GF /Gy /nologo # CFLAGS_O=/W3 /O2 /Zi /MD /nologo # CFLAGS_O=/W3 /O2 /Zi /MT /nologo CFLAGS_O=/W3 /O2 /Zi /MT /nologo CF_EX=/DWIN32 $(CF_LANPLUS) $(INC) /D_CONSOLE /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DHAVE_STRING_H CF_SAM=/DWIN32 $(INC) /D_CONSOLE /D_CRT_SECURE_NO_DEPRECATE /DHAVE_STRING_H CFLAGS=$(CFLAGS_O) $(CF_EX) /DSKIP_MD2 CFLAGS_M=$(CFLAGS_O) $(CF_EX) /DSKIP_MD2 /DMETACOMMAND CFLAGS_SAM=$(CFLAGS_O) $(CF_SAM) LFLAGS=/nologo /subsystem:console /machine:$(MARCH) /opt:ref #LFLAGS=/nologo /subsystem:console /machine:IX86 /opt:ref #LFLAGS=/nologo /subsystem:console /machine:IX86 /opt:ref /debug # LFLAGS_D=/nologo /subsystem:console /machine:I386 /opt:ref /dll # CFLAGS_W=/O2 /D_CONSOLE /D_MBCS /EHsc /ML /W3 /Zi /TP CFLAGS_W=/TP /EHsc $(CFLAGS) LFLAGS_W=/nologo /subsystem:console /machine:$(MARCH) /opt:ref LIBS_W=comsuppw.lib wbemuuid.lib # gdi32.lib comdlg32.lib shell32.lib uuid.lib CC=cl LINK=link MKDIR=-mkdir MKLIB=lib RM=del CP=copy LIBS_EX = advapi32.lib kernel32.lib wsock32.lib ws2_32.lib $(LIBS_W) $(LIBC_RT) LIBS_PEF = /LIBPATH:$(LIB_D) iphlpapi.lib # LIBS_EX+=wsock32.lib user32.lib gdi32.lib HEADER=ipmicmd.h imb_api.h ipmilan.h ipmidir.h ipmilanplus.h \ ipmiutil.h SHOWSEL = showsel TARG_EXE=ievents.exe $(SHOWSEL)msg.dll ipmi_sample.exe ipmi_sample_evt.exe $(SAMP_DLL) # alarms.exe ihealth.exe $(SHOWSEL).exe $(SHOWSEL)msg.dll \ # ireset.exe ifru.exe ilan.exe iserial.exe wdt.exe \ # getevent.exe sensor.exe icmd.exe isolconsole.exe idiscover.exe \ # ievents.exe SAMP_LIB = ipmiutil.lib SAMP_DLL = ipmiutillib.dll E_EXE=ipmiutil.exe E_OBJ=$(TMP_D)\ipmiutil.obj \ $(TMP_D)\ialarms.obj $(TMP_D)\ihealth.obj $(TMP_D)\iwdt.obj \ $(TMP_D)\ireset.obj $(TMP_D)\ifru.obj $(TMP_D)\ilan.obj \ $(TMP_D)\iserial.obj $(TMP_D)\icmd.obj $(TMP_D)\isol.obj \ $(TMP_D)\isolwin.obj $(TMP_D)\AnsiTerm.obj $(TMP_D)\idiscover.obj \ $(TMP_D)\iconfig.obj $(TMP_D)\igetevent.obj $(TMP_D)\isensor.obj \ $(TMP_D)\isel.obj $(TMP_D)\ievents.obj \ $(TMP_D)\ipicmg.obj $(TMP_D)\ifirewall.obj \ $(TMP_D)\iekanalyzer.obj $(TMP_D)\ifru_picmg.obj \ $(TMP_D)\oem_kontron.obj $(TMP_D)\ihpm.obj $(TMP_D)\ifwum.obj \ $(TMP_D)\oem_fujitsu.obj $(TMP_D)\oem_intel.obj $(TMP_D)\oem_lenovo.obj \ $(TMP_D)\oem_asus.obj $(TMP_D)\iuser.obj \ $(TMP_D)\oem_sun.obj $(TMP_D)\oem_dell.obj $(TMP_D)\oem_hp.obj \ $(TMP_D)\oem_supermicro.obj $(TMP_D)\itsol.obj $(TMP_D)\idcmi.obj \ $(TMP_D)\oem_quanta.obj $(TMP_D)\oem_newisys.obj $(CMD_OBJ) mem_if.obj ################################################################### all: banner $(TMP_D) exe banner: @echo Building ipmiutil $(TMP_D): $(MKDIR) $(TMP_D) @echo created $(TMP_D) lib: $(L2_OBJ) cd $(LIB_D) nmake /nologo -f ipmilib.mak cd ../util exe: $(E_EXE) $(TARG_EXE) install: $(MKDIR) $(INSTALLTOP) $(MKDIR) $(INSTALLTOP)\bin $(CP) $(E_EXE) $(INSTALLTOP)\bin xcopy $(TARG_EXE) $(INSTALLTOP)\bin xcopy *.dll $(INSTALLTOP)\bin clean: $(RM) *.obj 2>NUL $(RM) $(TARG_EXE) 2>NUL $(RM) *.exe 2>NUL -$(RM) $(TMP_D)\*.obj 2>NUL -$(RM) *.manifest 2>NUL distclean: $(RM) *.obj 2>NUL $(RM) $(TARG_EXE) 2>NUL $(RM) *.exe 2>NUL $(RM) $(TMP_D)\*.* 2>NUL rmdir $(TMP_D) 2>NUL $(RM) *.rc 2>NUL $(RM) *.bin 2>NUL $(RM) *.RES 2>NUL $(RM) getopt.* 2>NUL getopt.obj: getopt.c $(CC) /c $(CFLAGS) getopt.c imbapi.obj: imbapi.c $(CC) /c $(CFLAGS_M) imbapi.c ipmicmd.obj: ipmicmd.c $(CC) /c $(CFLAGS) ipmicmd.c ipmilan.obj: ipmilan.c $(CC) /c $(CFLAGS) ipmilan.c ipmilanplus.obj: ipmilanplus.c $(CC) /c $(CFLAGS_M) ipmilanplus.c md5.obj: md5.c $(CC) /c $(CFLAGS) md5.c md2.obj: md2.c $(CC) /c $(CFLAGS) md2.c ievents.obj: ievents.c $(CC) /c $(CFLAGS) ievents.c ialarms.obj: ialarms.c $(CC) /c $(CFLAGS) ialarms.c ihealth.obj: ihealth.c $(CC) /c $(CFLAGS) ihealth.c igetevent.obj: igetevent.c $(CC) /c $(CFLAGS) igetevent.c mem_if.obj: mem_if.c $(CC) /c $(CFLAGS_W) mem_if.c ipmims.obj: ipmims.cpp $(CC) /c $(CFLAGS_W) ipmims.cpp isel.obj: isel.c $(CC) /c $(CFLAGS) isel.c ireset.obj: ireset.c $(CC) /c $(CFLAGS) ireset.c ireset.exe: ireset.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ireset.exe ireset.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) ifru.obj: ifru.c $(CC) /c $(CFLAGS) ifru.c ifru.exe: ifru.obj mem_if.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ifru.exe ifru.obj mem_if.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) ilan.obj: ilan.c $(CC) /c $(CFLAGS) ilan.c ilan.exe: ilan.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ilan.exe ilan.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_PEF) $(LIBS_EX) iserial.obj: iserial.c $(CC) /c $(CFLAGS) iserial.c iserial.exe: iserial.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:iserial.exe iserial.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) isensor.obj: isensor.c $(CC) /c $(CFLAGS) isensor.c isensor.exe: isensor.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:isensor.exe isensor.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) iwdt.obj: iwdt.c $(CC) /c $(CFLAGS) iwdt.c iwdt.exe: iwdt.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:iwdt.exe iwdt.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) isol.obj: isol.c $(CC) /c $(CFLAGS) isol.c isolwin.obj: isolwin.c $(CC) /c $(CFLAGS) isolwin.c isol.exe: isol.obj isolwin.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:isol.exe isol.obj isolwin.obj \ $(CMD_OBJ) $(LF_LANPLUS) $(LIBS_EX) icmd.obj: icmd.c $(CC) /c $(CFLAGS) icmd.c icmd.exe: icmd.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:icmd.exe icmd.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) idiscover.obj: idiscover.c $(CC) /c $(CFLAGS) idiscover.c idiscover.exe: idiscover.obj getopt.obj $(LINK) $(LFLAGS) /OUT:idiscover.exe idiscover.obj getopt.obj \ $(LF_LANPLUS) $(LIBS_EX) ialarms.exe: ialarms.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ialarms.exe ialarms.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) ihealth.exe: ihealth.obj mem_if.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ihealth.exe ihealth.obj mem_if.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) igetevent.exe: igetevent.obj ievents.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:igetevent.exe igetevent.obj ievents.obj \ $(CMD_OBJ) $(LF_LANPLUS) $(LIBS_EX) isel.exe: isel.obj ievents.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:isel.exe isel.obj ievents.obj \ $(CMD_OBJ) $(LF_LANPLUS) $(LIBS_EX) $(SHOWSEL).mc: $(CP) ..\scripts\$(SHOWSEL).mc . $(SHOWSEL)msg.dll: $(SHOWSEL).mc mc -U $(SHOWSEL).mc rc -r $(SHOWSEL).rc $(LINK) /machine:$(MARCH) -dll -noentry -out:$(SHOWSEL)msg.dll $(SHOWSEL).res mem_if.exe: $(TMP_D)\mem_if.obj $(LINK) $(LFLAGS_W) /OUT:mem_if.exe $(TMP_D)\mem_if.obj $(LIBS_EX) $(TMP_D)\mem_if.obj: mem_if.c $(CC) /c $(CFLAGS_W) /DCOMP_BIN /Fo$(TMP_D)\mem_if.obj mem_if.c ievents.exe: ievents.c $(CC) /c $(CFLAGS) /DALONE ievents.c $(LINK) $(LFLAGS) /OUT:ievents.exe ievents.obj $(LIBS_EX) $(RM) ievents.obj ipmims.exe: ipmims.cpp $(CC) /c $(CFLAGS_W) /DALONE /DTEST_BIN ipmims.cpp $(LINK) $(LFLAGS_W) /OUT:ipmims.exe ipmims.obj $(LIBS_EX) $(RM) ipmims.obj $(TMP_D)\ievents.obj: ievents.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ievents.obj ievents.c $(TMP_D)\ipmiutil.obj: ipmiutil.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ipmiutil.obj ipmiutil.c $(TMP_D)\ialarms.obj: ialarms.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ialarms.obj ialarms.c $(TMP_D)\ihealth.obj: ihealth.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ihealth.obj ihealth.c $(TMP_D)\iconfig.obj: iconfig.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iconfig.obj iconfig.c $(TMP_D)\ipicmg.obj: ipicmg.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ipicmg.obj ipicmg.c $(TMP_D)\ifirewall.obj: ifirewall.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifirewall.obj ifirewall.c $(TMP_D)\ifwum.obj: ifwum.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifwum.obj ifwum.c $(TMP_D)\ihpm.obj: ihpm.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ihpm.obj ihpm.c $(TMP_D)\idcmi.obj: idcmi.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\idcmi.obj idcmi.c $(TMP_D)\iuser.obj: iuser.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iuser.obj iuser.c $(TMP_D)\oem_fujitsu.obj: oem_fujitsu.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_fujitsu.obj oem_fujitsu.c $(TMP_D)\oem_kontron.obj: oem_kontron.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_kontron.obj oem_kontron.c $(TMP_D)\oem_intel.obj: oem_intel.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_intel.obj oem_intel.c $(TMP_D)\oem_sun.obj: oem_sun.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_sun.obj oem_sun.c $(TMP_D)\oem_dell.obj: oem_dell.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_dell.obj oem_dell.c $(TMP_D)\oem_hp.obj: oem_hp.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_hp.obj oem_hp.c $(TMP_D)\oem_supermicro.obj: oem_supermicro.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_supermicro.obj oem_supermicro.c $(TMP_D)\oem_lenovo.obj: oem_lenovo.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_lenovo.obj oem_lenovo.c $(TMP_D)\oem_asus.obj: oem_asus.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_asus.obj oem_asus.c $(TMP_D)\oem_quanta.obj: oem_quanta.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_quanta.obj oem_quanta.c $(TMP_D)\oem_newisys.obj: oem_newisys.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_newisys.obj oem_newisys.c $(TMP_D)\iekanalyzer.obj: iekanalyzer.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iekanalyzer.obj iekanalyzer.c $(TMP_D)\ifru_picmg.obj: ifru_picmg.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifru_picmg.obj ifru_picmg.c $(TMP_D)\ifru.obj: ifru.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifru.obj ifru.c $(TMP_D)\ireset.obj: ireset.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ireset.obj ireset.c $(TMP_D)\ilan.obj: ilan.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ilan.obj ilan.c $(TMP_D)\iserial.obj: iserial.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iserial.obj iserial.c $(TMP_D)\isensor.obj: isensor.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isensor.obj isensor.c $(TMP_D)\icmd.obj: icmd.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\icmd.obj icmd.c $(TMP_D)\igetevent.obj: igetevent.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\igetevent.obj igetevent.c $(TMP_D)\isel.obj: isel.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isel.obj isel.c $(TMP_D)\isol.obj: isol.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isol.obj isol.c $(TMP_D)\isolwin.obj: isolwin.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isolwin.obj isolwin.c $(TMP_D)\itsol.obj: itsol.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\itsol.obj itsol.c $(TMP_D)\AnsiTerm.obj: AnsiTerm.cpp $(CC) /c $(CFLAGS_W) /Fo$(TMP_D)\AnsiTerm.obj AnsiTerm.cpp $(TMP_D)\idiscover.obj: idiscover.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\idiscover.obj idiscover.c $(TMP_D)\iwdt.obj: iwdt.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iwdt.obj iwdt.c $(E_EXE): $(E_OBJ) $(LINK) $(LFLAGS) /OUT:$(E_EXE) $(E_OBJ) $(LF_LANPLUS) $(LIBS_PEF) $(LIBS_EX) ipmi_sample.obj: ipmi_sample.c $(CC) /c $(CFLAGS_SAM) ipmi_sample.c $(SAMP_LIB): $(CMD_OBJ) mem_if.obj $(CC) /c $(CFLAGS_SAM) ipmilanplus.c $(MKLIB) /OUT:$(SAMP_LIB) /nologo $(CMD_OBJ) mem_if.obj del ipmilanplus.obj $(SAMP_DLL): $(CMD_OBJ) mem_if.obj $(CC) /D_WINDLL /D_USRDLL /c $(CFLAGS_SAM) ipmilanplus.c $(LINK) /DLL $(LFLAGS) /OUT:$(SAMP_DLL) /def:ipmiutillib.def $(CMD_OBJ) mem_if.obj $(LIBS_PEF) $(LIBS_EX) del ipmilanplus.obj ipmi_sample.exe: $(SAMP_LIB) ipmi_sample.obj $(LINK) $(LFLAGS) /OUT:ipmi_sample.exe ipmi_sample.obj $(SAMP_LIB) $(LIBS_PEF) $(LIBS_EX) ipmi_sample2.exe: $(SAMP_LIB) ipmi_sample.c isensor.c ievents.c $(CC) /c $(CFLAGS_SAM) /DGET_SENSORS ipmi_sample.c $(CC) /c $(CFLAGS_SAM) isensor.c $(CC) /c $(CFLAGS_SAM) ievents.c $(LINK) $(LFLAGS) /OUT:ipmi_sample2.exe ipmi_sample.obj isensor.obj ievents.obj $(SAMP_LIB) $(LIBS_PEF) $(LIBS_EX) del isensor.obj ievents.obj ipmi_sample_evt.obj: ipmi_sample_evt.c $(HEADER) $(CC) /c $(CFLAGS_SAM) ipmi_sample_evt.c isensor2.obj: isensor.c isensor.h $(HEADER) $(CC) /c /Foisensor2.obj $(CFLAGS_SAM) isensor.c ievents2.obj: ievents.c ievents.h $(HEADER) $(CC) /c /Foievents2.obj $(CFLAGS_SAM) /DSENSORS_OK ievents.c ipmi_sample_evt.exe: $(SAMP_LIB) ipmi_sample_evt.obj ievents2.obj isensor2.obj $(LINK) $(LFLAGS) /OUT:ipmi_sample_evt.exe ipmi_sample_evt.obj ievents2.obj isensor2.obj $(SAMP_LIB) $(LIBS_PEF) $(LIBS_EX) ipmiutil-3.1.5/util/mem_if_cpp.cpp0000644000076400007640000000025313566765324017235 0ustar mgportalloggers// mem_if_cpp.cpp // Include the actual mem_if source into this .cpp file. // This is a wrapper for build.exe to detect its type as C++. // #include "mem_if.c" ipmiutil-3.1.5/util/ipmidir.h0000644000076400007640000003101313566765324016237 0ustar mgportalloggers/*********************************************** * ipmidir.h * * Definitions and data structures for direct * user-space IPMI I/Os. * ***********************************************/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 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 Corporation 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. *----------------------------------------------------------------------*/ #ifndef IPMIDIR_H_ #define IPMIDIR_H_ #define SMB_DATA_ADDRESS = 0x000 // // State bits based on S1 & S0 below // #define ISA_STATE_MASK 0xC0 #define ISA_IDLE_STATE 0x00 #define ISA_READ_STATE 0x40 #define ISA_WRITE_STATE 0x80 #define ISA_ERROR_STATE 0xC0 // // Status Register Bits // #define ISA_S1_FLAG 0x80 #define ISA_S0_FLAG 0x40 // RESERVED 0x20 // RESERVED 0x10 #define ISA_CD_FLAG 0x08 #define ISA_SMS_MSG_FLAG 0x04 #define ISA_IBF_FLAG 0x02 #define ISA_OBF_FLAG 0x01 // // ISA interface register access defines // #define BMC_SLAVE_ADDR 0x20 #define MAX_ISA_LENGTH 35 #define ISA_SMS_TIMEOUT 5000 // in miliseconds - 1 second #define ISA_SMM_TIMEOUT 100 // in microseconds // // mBMC Address // #define IMB_SEND_ERROR 1 #define IMB_SUCCESS 0 // typedef unsigned int DWORD; // typedef unsigned char BYTE; // typedef unsigned char UCHAR; * defined in imb_api.h * // typedef unsigned long ULONG; * defined in imb_api.h * // typedef unsigned int UINT32; typedef unsigned short UINT16; typedef unsigned char UINT8; struct SMBCharStruct { unsigned int Controller; unsigned int baseAddr; }; /*---------------------------------------------------------* * PCI defines for SMBus *---------------------------------------------------------*/ // PCI related definitions #define PCI_CONFIG_ADDRESS 0xCF8 #define PCI_CONFIG_DATA 0xCFC // PCI unique identifiers #define ID_8111 0x746A1022 #define ID_81801 0x24128086 #define ID_81801AA 0x24138086 #define ID_81801AB 0x24238086 #define ID_82801BA 0x24438086 #define ID_82801CA 0x24838086 #define ID_ICH4 0x24C38086 #define ID_ICH5 0x24D38086 #define ID_ICH6 0x266A8086 //srini added ICH6 support #define ID_CSB5 0x02011166 #define ID_CSB6 0x02031166 #define ID_OSB4 0x02001166 #define Hance_Rapids 0x25A48086 //lester 0627 // PCI configuration registers #define ICH_SMB_BASE 0x20 // base address register #define ICH_HOSTC 0x40 // host config register #define ICH_HOSTC_I2C_EN 0x04 // enable i2c mode #define ICH_HOSTC_SMB_SMI_EN 0x02 // SMI# instead of irq #define ICH_HOSTC_HST_EN 0x01 // enable host cntrlr #define AMD_SMB_BASE_2 0x10 // base address register of SMBus 2.0 #define AMD_SMB_BASE_2_EN 0x04 // SMBus 2.0 space enable #define AMD_SMB_BASE_1 0x58 // base address register of SMBus 1.0 #define AMD_SMB_BASE_1_EN 0x41 // SMBus 1.0 space enable #define AMD_SMBUS_1 0xE0 // SMBus 1.0 registers // I/O registers #define ICH_HST_STA 0x00 // host status #define ICH_HST_STA_BYTE_DONE_STS 0x80 // byte send/rec'd #define ICH_HST_STA_INUSE_STS 0x40 // device access mutex #define ICH_HST_STA_SMBALERT_STS 0x20 // SMBALERT# signal #define ICH_HST_STA_FAILED 0x10 // failed bus transaction #define ICH_HST_STA_BUS_ERR 0x08 // transaction collision #define ICH_HST_STA_DEV_ERR 0x04 // misc. smb device error #define ICH_HST_STA_ALL_ERRS (ICH_HST_STA_FAILED|ICH_HST_STA_BUS_ERR|ICH_HST_STA_DEV_ERR) #define ICH_HST_STA_INTR 0x02 // command completed ok #define ICH_HST_STA_HOST_BUSY 0x01 // command is running #define ICH_HST_CNT 0x02 // host control #define ICH_HST_CNT_START 0x40 // start command #define ICH_HST_CNT_LAST_BYTE 0x20 // indicate last byte #define ICH_HST_CNT_SMB_CMD_QUICK 0x00 // command: quick #define ICH_HST_CNT_SMB_CMD_BYTE 0x04 // command: byte #define ICH_HST_CNT_SMB_CMD_BYTE_DATA 0x08 // command: byte data #define ICH_HST_CNT_SMB_CMD_WORD_DATA 0x0c // command: word data #define ICH_HST_CNT_SMB_CMD_PROC_CALL 0x10 // command: process call #define ICH_HST_CNT_SMB_CMD_BLOCK 0x14 // command: block #define ICH_HST_CNT_SMB_CMD_I2C_READ 0x18 // command: i2c read #define ICH_HST_CNT_KILL 0x02 // kill current transaction #define ICH_HST_CNT_INTREN 0x01 // enable interrupt #define ICH_HST_CMD 0x03 // host command #define ICH_XMIT_SLVA 0x04 // transmit slave address #define ICH_XMIT_SLVA_READ 0x01 // direction: read #define ICH_XMIT_SLVA_WRITE 0x00 // direction: write #define ICH_D0 0x05 // host data 0 #define ICH_D1 0x06 // host data 1 #define ICH_BLOCK_DB 0x07 // block data byte // SMBus 1.0 #define AMD_SMB_1_STATUS 0x00 // SMBus global status #define AMD_SMB_1_STATUS_SMBS_BSY (1<11) #define AMD_SMB_1_STATUS_SMBA_STS (1<10) #define AMD_SMB_1_STATUS_HSLV_STS (1<9) #define AMD_SMB_1_STATUS_SNP_STS (1<8) #define AMD_SMB_1_STATUS_TO_STS (1<5) #define AMD_SMB_1_STATUS_HCYC_STS (1<4) #define AMD_SMB_1_STATUS_HST_BSY (1<3) #define AMD_SMB_1_STATUS_PERR_STS (1<2) #define AMD_SMB_1_STATUS_COL_STS (1<1) #define AMD_SMB_1_STATUS_ABRT_STS (1<0) #define AMD_SMB_1_STATUS_ALL_ERRS AMD_SMB_1_STATUS_TO_STS|AMD_SMB_1_STATUS_HST_BSY|AMD_SMB_1_STATUS_PERR_STS|AMD_SMB_1_STATUS_COL_STS #define AMD_SMB_1_CTL 0x02 // SMBus global control #define AMD_SMB_1_CTL_SMBA_EN (1<<10) #define AMD_SMB_1_CTL_HSLV_EN (1<<9) #define AMD_SMB_1_CTL_SNP_EN (1<<8) #define AMD_SMB_1_CTL_ABORT (1<<5) #define AMD_SMB_HCYC_EN (1<<4) #define AMD_SMB_HOSTSTS (1<<3) #define AMD_SMB_CYCTYPE_QC 0x0 // quick command #define AMD_SMB_CYCTYPE_RSB 0x1 // receive/send byte #define AMD_SMB_CYCTYPE_RWB 0x2 // read/write byte #define AMD_SMB_CYCTYPE_RWW 0x3 // read/write word #define AMD_SMB_CYCTYPE_PC 0x4 // process call #define AMD_SMB_CYCTYPE_RWBL 0x5 // read/write block #define AMD_SMB_1_ADDR 0x04 // SMBus host address #define AMD_SMB_1_ADDR_READCYC (1<<0) #define AMD_SMB_1_DATA 0x06 // SMBus host data #define AMD_SMB_1_CMD 0x08 // SMBus host command #define AMD_SMB_1_BLOCK_DATA 0x09 // SMBus block data FIFO access port // For SMBus 2.0, see ACPI 2.0 chapter 13 PCI interface definitions #define AMD_SMB_BLOCK_WRITE 0xa #define AMD_SMB_BLOCK_READ 0xb // AMD PCI control registers definitions. #define AMD_PCI_MISC 0x48 #define AMD_PCI_MISC_SCI 0x04 #define AMD_PCI_MISC_INT 0x02 #define AMD_PCI_MISC_SPEEDUP 0x01 // SMBus Controllers #define INTEL_SMBC 1 // Intel #define SW_SMBC 2 // ServerWorks #define VIA_SMBC 3 // VIA #define AMD_SMBC 4 // AMD /************************************************ * bmc.h ************************************************/ #define STATUS_OK 0 #define BMC_MAX_RETRIES 3 // Max number of retries if BMC is busy #define DATA_BUF_SIZE 255 // Max data buffer, see IPMI_REQBUF_SIZE #define GETMSGTIMEOUT 5 // Time out in sec for send/get message command // Product IDs of systems with PC87431 chips (have both Sahalee and mBMC) #define ID_PC87431_M 0x4311 #define ID_PC87431_S 0x4312 #define ID_PC87431_C 0x4315 // Available BMC chips that are supported by this library. #define BMC_UNKNOWN 0 #define BMC_SAHALEE 1 // Intel Sahalee BMC #define BMC_MBMC_87431M 2 // mBMC, chip = PC87431M #define BMC_MBMC_87431S 3 // mBMC, chip = PC87431S #define BMC_MBMC_87431C 4 // mBMC, chip = PC87431C #define BMC_BOTH_SAHALEE_MBMC 5 #define BMC_DUAL_NW 6 // currently not detected // #define BMC_AMT10 7 // Available IPMI versions. There may be full and partial IPMI implementations. // To figure out what implementation is supported, look at the BMC_TYPE. #define IPMI_VERSION_UNKNOWN 0 #define IPMI_VERSION_1_5 1 #define IPMI_VERSION_2_0 2 #define IPMI_VERSION_1_0 3 //***************************************************************************** // Message struct for sending and receiving messages from the BMC. Requests // must have a DevAdd, NetFn, LUN, Cmd, Data, and Len. The response will have // all fields filled in. In both cases 'Len' is the length of the data buffer. typedef struct { UINT8 Bus; UINT8 DevAdd; UINT8 NetFn; UINT8 LUN; UINT8 Cmd; UINT8 Data[DATA_BUF_SIZE]; UINT32 Len; UINT8 CompCode; } BMC_MESSAGE; /* Internal error codes from BMC or IPMI driver: * ERR_NO_DRV is defined in ipmicmd.h, and the other * values below are not used. */ #define ER_NO_BMC_IF -400 // could not find the BMC interface #define ERCANTLOCATEIPMIHANDLE -500 // Unable to locate IPMI handle #define ERCANTALLOCMEMORYFORIPMI -501 // Unable to allocate memory for IPMI services #define ERCANTLOADIPMIDRIVER -502 // Unable to dynamically load IPMI driver #define ERSENDINGIPMIMESSAGE -503 // Error sending request to BMC #define ERGETTINGIPMIMESSAGE -504 // Error getting request from BMC #define ERCMDRETURNEDDONTMATCH -505 // Returned command # doesn't match what was sent #define ERLUNRETURNEDDONTMATCH -506 // Returned LUN # doesn't match what was sent #define ERCOMPCODEERR -507 // Comp code is not COMPCODE_NORMAL #define ERSEQNUMBER -508 // Sequence number error. #define ERCANTCLEARMSGFLAGS -509 // Can not clear message flags #define ERINVALIDRESPONSELEN -510 // Response length not as expected. #define ER_NO_PCI_BIOS -511 // No PCI BIOS record exist #define ER_SMBUSBUSERROR -512 #define ER_SMBUSTIMEOUT -513 #define ER_SMBUSOWNERSHIP -514 #define ER_SMBUSDEVERROR -515 #define ER_NOTKCS -516 // Not KCS, probably SMBus // Device Addresses #define BMC_ADDR 0x20 // Baseboard Management Controller #define HSC0_ADDR 0xC0 // Hot Swap Controller 0 #define HSC1_ADDR 0xC2 // Hot Swap Controller 1 #define PSC_ADDR 0xC8 // Power Supply Controller #define CBC_ADDR 0x28 // Chassis Bridge Controller #define LCP_ADDR 0x22 // LCP(Local Control Panel) Address #define MBMC_ADDR 0x84 // MINI BMC address #define SMBUS_SLAVE_ADDRESS 0x00 #define ID_VITESSE 0x01 // for HSC #define ID_GEM 0x02 // for HSC #define ISA_BUS 0xFF // ISA Bus address #define BMC_DEV_ADDR 0x20 // BMC Device Addr for Get Device ID // #define BMC_LUN 0x00 // BMC commands & event request messages #define OEM_LUN1 0x01 // OEM LUN 1 #define SMS_MSG_LUN 0x02 // SMS message LUN #define OEM_LUN2 0x03 // OEM LUN 2 #define NETFN_APP 0x06 #define GETMESSAGE_CMD 0x33 // IPMI Get Message command #define SENDMESSAGE_CMD 0x34 // IPMI Send Message command #endif // IPMIDIR_H_ ipmiutil-3.1.5/util/ipmild.c0000644000076400007640000001722013566765324016057 0ustar mgportalloggers/*M* // PVCS: // $Workfile: ipmild.c $ // $Revision: 1.0 $ // $Modtime: 23 Feb 2005 15:20:14 $ // $Author: arcress at users.sourceforge.net $ // // This implements support for the /dev/ldipmi native interface from // the LanDesk IPMI driver. // Requires linking with libldipmi.a, or equivalent. // // 02/23/05 ARC - created, but stubbed out, since the // LanDesk libipmiapi.a isn't clean yet. *M*/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2005, 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 Corporation 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. *----------------------------------------------------------------------*/ #ifdef LINUX #include #include #include #include #include #include #include #include #include "ipmicmd.h" /* for uchar, NCMDS */ // #define uchar unsigned char #define MAX_NO_OF_RETRIES 3 // Request structure provided to SendTimedImbpRequest() #pragma pack(1) typedef struct { uchar cmdType; // IMB command uchar rsSa; // command destination address uchar busType; // not used uchar netFn; // IMB command class (network function) uchar rsLun; // subsystem on destination uchar * data; // command body int dataLength; // body size } IMBPREQUESTDATA; #pragma pack() #ifdef LINK_LANDESK /* typedef enum { 0, 1, 2, 3, 4, 5, 6 } ACCESN_STATUS; */ /* Note that this routine name conflicts with ia_ imb routine. */ extern int SendTimedImbpRequest ( IMBPREQUESTDATA *reqPtr, int timeOut, uchar * respDataPtr, int * respDataLen, uchar * completionCode); extern int initIPMI(); extern int termIPMI(); static int ipmi_timeout_ld = 100000; /*100 * 1000 ms = 100 sec */ #endif extern FILE *fperr; /*defined in ipmicmd.c*/ extern FILE *fpdbg; /*defined in ipmicmd.c*/ extern ipmi_cmd_t ipmi_cmds[NCMDS]; #ifdef LINK_LANDESK static int ipmi_fd = -1; #endif int ipmi_open_ld(char fdebugcmd) { int rc = -1; #ifdef TEST char *pdev; if (ipmi_fd != -1) return(0); pdev = "/dev/ldipmi"; ipmi_fd = open(pdev, O_RDWR); if (ipmi_fd == -1) { if (fdebugcmd) printf("ipmi_open_ld: cannot open %s\n",pdev); pdev = "/dev/ldipmi/0"; ipmi_fd = open(pdev, O_RDWR); } #endif #ifdef LINK_LANDESK rc = initIPMI(); if (rc != 0) { if (fdebugcmd) printf("ipmi_open_ld: cannot open ldipmi, rc=%d errno=%d\n",rc,errno); return(-1); } ipmi_fd = 1; /*show that open was ok*/ if (fdebugcmd) printf("ipmi_open_ld: successfully opened ldipmi\n"); #endif return(rc); } int ipmi_close_ld(void) { int rc = 0; #ifdef LINK_LANDESK if (ipmi_fd != -1) { termIPMI(); ipmi_fd = -1; } #endif return(rc); } int ipmicmd_ld( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { #ifdef LINK_LANDESK IMBPREQUESTDATA requestData; int status = 0; uchar * pc; int sz, i; requestData.cmdType = cmd; requestData.rsSa = sa; requestData.busType = bus; requestData.netFn = netfn; requestData.rsLun = lun; requestData.dataLength = sdata; requestData.data = pdata; if (fdebugcmd) { sz = sizeof(IMBPREQUESTDATA); pc = (uchar *)&requestData.cmdType; fprintf(fpdbg,"ipmicmd_ld: request (len=%d): ",sz); for (i = 0; i < sz; i++) fprintf(fpdbg,"%02x ",pc[i]); fprintf(fpdbg,"\n"); pc = requestData.data; sz = requestData.dataLength; fprintf(fpdbg," req.data=%p, dlen=%d: ", pc, sz); for (i = 0; i < sz; i++) fprintf(fpdbg,"%02x ",pc[i]); fprintf(fpdbg,"\n"); } if (ipmi_fd == -1) { status = ipmi_open_ld(fdebugcmd); if (status != 0) return(status); } { sz = *sresp; /* note that sresp must be pre-set */ memset(presp, 0, sz); for ( i =0 ; i < MAX_NO_OF_RETRIES; i++) { *sresp = sz; /* retries may need to re-init *sresp */ if((status =SendTimedImbpRequest(&requestData, ipmi_timeout_ld, presp, sresp, pcc)) == 0 ) { break; } if (fdebugcmd) // only gets here if error fprintf(fpdbg,"ipmi_cmd_ld: sendImbRequest error status=%x, ccode=%x\n", (uint)status, *pcc); } } if (fdebugcmd) { /* if debug, show both good and bad statuses */ fprintf(fpdbg,"ipmi_cmd_ld: sendImbRequest status=%x, ccode=%x\n", (uint)status, *pcc); if (status == 0) { uchar * pc; int sz; sz = *sresp; pc = (uchar *)presp; fprintf(fpdbg,"ipmi_cmd_ld: response (len=%d): ",sz); for (i = 0; i < sz; i++) fprintf(fpdbg,"%02x ",pc[i]); fprintf(fpdbg,"\n"); } } return(status); #else return(-1); #endif } /* end ipmicmd_ld() */ int ipmi_cmdraw_ld( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rc; rc = ipmicmd_ld(cmd, netfn, lun, sa, bus, pdata,sdata,presp,sresp,pcc,fdebugcmd); return(rc); } int ipmi_cmd_ld(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rc, i; for (i = 0; i < NCMDS; i++) { if (ipmi_cmds[i].cmdtyp == cmd) break; } if (i >= NCMDS) { fprintf(fperr, "ipmi_cmd_ld: Unknown command %x\n",cmd); return(-1); } if (cmd >= CMDMASK) cmd = cmd & CMDMASK; /* unmask it */ rc = ipmicmd_ld(cmd, ipmi_cmds[i].netfn, ipmi_cmds[i].lun, ipmi_cmds[i].sa, ipmi_cmds[i].bus, pdata,sdata,presp,sresp,pcc,fdebugcmd); return(rc); } #ifdef LINK_LANDESK /* define extra stuff that the LanDesk library needs */ void * _Unwind_Resume(void *context) { printf("called Unwind_Resume\n"); return(NULL); } int __gxx_personality_v0(void *a) { return(0); } #endif #endif ipmiutil-3.1.5/util/ipmi_sample.mak0000644000076400007640000000327313566765324017431 0ustar mgportalloggers# ipmi_sample.mak # This makefile will build the ipmiutil ipmi_sample application # LIBC_RT=libcmt.lib /NODEFAULTLIB:"msvcirt.lib" # LIBC_RT=msvcrt.lib /NODEFAULTLIB:"msvcirt.lib" MARCH=IX86 # MARCH=X64 # The ipmiutil directory SRC_D=%CD% LIB_D=%CD% INC=/I$(SRC_D) # Set your compiler options # CFLAGS_O=/W3 /O2 /Zi /MT /nologo CFLAGS_O=/W3 /Zi /MT /nologo CF_SAM=/DWIN32 $(INC) /D_CONSOLE /D_CRT_SECURE_NO_DEPRECATE /DHAVE_STRING_H CFLAGS_SAM=$(CFLAGS_O) $(CF_SAM) LFLAGS=/nologo /subsystem:console /machine:$(MARCH) /opt:ref LIBS_W=comsuppw.lib wbemuuid.lib LIBS_EX=advapi32.lib kernel32.lib wsock32.lib ws2_32.lib $(LIBS_W) $(LIBC_RT) LIBS_PEF=/LIBPATH:$(LIB_D) iphlpapi.lib CC=cl LINK=link RM=del HEADER = ipmicmd.h SAMP_LIB = ipmiutil.lib TARG1_EXE = ipmi_sample.exe TARG2_EXE = ipmi_sample_evt.exe ################################################################### all: $(TARG1_EXE) clean: $(RM) *.obj 2>NUL $(RM) $(TARG1_EXE) 2>NUL ipmi_sample.obj: ipmi_sample.c $(HEADER) $(CC) /c $(CFLAGS_SAM) ipmi_sample.c $(TARG1_EXE): $(SAMP_LIB) ipmi_sample.obj $(LINK) $(LFLAGS) /OUT:$(TARG1_EXE) ipmi_sample.obj $(SAMP_LIB) $(LIBS_PEF) $(LIBS_EX) ipmi_sample_evt.obj: ipmi_sample_evt.c $(HEADER) $(CC) /c $(CFLAGS_SAM) ipmi_sample_evt.c isensor2.obj: isensor.c isensor.h $(HEADER) $(CC) /c /Foisensor2.obj $(CFLAGS_SAM) isensor.c ievents2.obj: ievents.c ievents.h $(HEADER) $(CC) /c /Foievents2.obj $(CFLAGS_SAM) /DSENSORS_OK ievents.c $(TARG2_EXE): $(SAMP_LIB) ipmi_sample_evt.obj ievents2.obj isensor2.obj $(LINK) $(LFLAGS) /OUT:$(TARG2_EXE) ipmi_sample_evt.obj ievents2.obj isensor2.obj $(SAMP_LIB) $(LIBS_PEF) $(LIBS_EX) ipmiutil-3.1.5/util/oem_lenovo.c0000644000076400007640000004057113566765324016750 0ustar mgportalloggers/* * oem_lenovo.c * Handle Lenovo OEM command functions * * Author: Andy Cress arcress at users.sourceforge.net * Change history: * 11/21/2016 ARCress - created * *--------------------------------------------------------------------- */ /*M* Copyright (c) 2016 Andy Cress All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of the copyright holder nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ #ifdef WIN32 #include #include "getopt.h" #else #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #include #else #include #endif #endif #include #include #include #include #include "ipmicmd.h" #include "ievents.h" #include "oem_lenovo.h" extern uchar bitnum(ushort value); /*isensor.c*/ extern char fdebug; /*ipmicmd.c*/ void set_loglevel(int level); /*prototype */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil lenovooem"; #else static char * progver = "3.08"; static char * progname = "ilenovooem"; #endif static int verbose = 0; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static int vend_id = 0; static int prod_id = 0; /* See oem_ibm_sel_map from ipmitool contrib, interpretation not verified yet */ #define NIBMEVT 16 struct { uchar stype; uchar snum; uchar etype; uchar data1; uchar data2; uchar data3; uchar sev; char *desc; } oem_ibm_events[NIBMEVT] = { 0xC1, 0xFF, 0xFF, 0xFF, 0x01, 0x00, SEV_MIN, "CPU shutdown - Potential cause 'triple fault' a software address problem", 0xC1, 0xFF, 0xFF, 0xFF, 0x02, 0x01, SEV_INFO, "Memory Mirrored Failover Occurred - System running from mirrored memory image", 0xC1, 0xFF, 0xFF, 0xFF, 0x02, 0x04, SEV_INFO, "Memory hot replace event", 0xC1, 0xFF, 0xFF, 0xFF, 0x02, 0x05, SEV_INFO, "Memory hot add event", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x00, SEV_INFO, "Scalability link down", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x01, SEV_INFO, "Scalability link up", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x02, SEV_INFO, "Scalability link double wide down", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x03, SEV_INFO, "Scalability link double wide up", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x80, SEV_INFO, "Scalability link PFA", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x81, SEV_INFO, "Scalability link invalid port", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x82, SEV_INFO, "Scalability link invalid node", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x83, SEV_INFO, "Scalability link kill", 0xE0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, SEV_INFO, "Device OK", 0xE0, 0x00, 0x01, 0xFF, 0xFF, 0xFF, SEV_MAJ, "Required ROM space not available", 0xE0, 0x00, 0x02, 0xFF, 0xFF, 0xFF, SEV_MAJ, "Required I/O Space not available", 0xE0, 0x00, 0x03, 0xFF, 0xFF, 0xFF, SEV_MAJ, "Required memory not available" }; /*------------------------------------------------------------------------ * get_ibm_desc * Uses the oem_ibm_events to decode IBM events not otherwise handled. * Called by decode_sel_lenovo *------------------------------------------------------------------------*/ char * get_ibm_desc(uchar type, uchar num, uchar trig, uchar data1, uchar data2, uchar data3, uchar *sev) { int i; char *pstr = NULL; /* Use oem_ibm_events array for other misc descriptions */ data1 &= 0x0f; /*ignore top half of sensor offset for matching */ for (i = 0; i < NIBMEVT; i++) { if ((oem_ibm_events[i].stype == 0xff) || (oem_ibm_events[i].stype == type)) { if (oem_ibm_events[i].snum != 0xff && oem_ibm_events[i].snum != num) continue; if (oem_ibm_events[i].etype != 0xff && oem_ibm_events[i].etype != trig) continue; if (oem_ibm_events[i].data1 != 0xff && (oem_ibm_events[i].data1 & 0x0f) != (data1 & 0x0f)) continue; if (oem_ibm_events[i].data2 != 0xff && oem_ibm_events[i].data2 != data2) continue; if (oem_ibm_events[i].data3 != 0xff && oem_ibm_events[i].data3 != data3) continue; /* have a match, use description */ pstr = (char *)oem_ibm_events[i].desc; if (sev != NULL) *sev = oem_ibm_events[i].sev; break; } } /*end for*/ return(pstr); } /* end get_ibm_desc() */ /* * decode_sensor_lenovo * inputs: * sdr = the SDR buffer * reading = the 3 or 4 bytes of data from GetSensorReading * pstring = points to the output string buffer * slen = size of the output buffer * outputs: * rv = 0 if this sensor was successfully interpreted here, * non-zero otherwise, to use default interpretations. * pstring = contains the sensor reading interpretation string (if rv==0) */ int decode_sensor_lenovo(uchar *sdr,uchar *reading,char *pstring, int slen) { int rv = -1; uchar stype, etype, entity; uchar bval; ushort rval; char *pstr = NULL; int b; int vend, prod; if (sdr == NULL || reading == NULL) return(rv); if (pstring == NULL || slen == 0) return(rv); /* sdr[3] is 0x01 for Full, 0x02 for Compact */ bval = reading[2]; if (sdr[3] == 0x01) return(rv); /*skip if full sensor*/ entity = sdr[8]; stype = sdr[12]; etype = sdr[13]; rval = reading[2] | ((reading[3] & 0x7f) << 8); b = bitnum(rval); get_mfgid(&vend,&prod); /*saved from ipmi_getdeviceid */ if (fdebug) printf("oem_lenovo: mfg=%04x:%04x sensor type=%x evt=%x entity=%x rval=%04x\n", vend,prod,stype,etype,entity,rval); switch(stype) { case 0x07: /* CPU sensor type */ if ((etype == 0x6F) && (entity == 25)) { /*All CPUs*/ switch(b) { case 0x00: pstr = "OK"; break; case 0x02: pstr = "BIST_Fail"; break; case 0x05: pstr = "Config_Error"; break; case 0x06: pstr = "Uncorr_Error"; break; case 0x08: pstr = "Disabled"; break; default: pstr = "OK*"; break; } rv = 0; } else if ((etype == 0x6F) && (entity == 3)) { /*CPU status*/ /* Special CPU status reported on IBM/Lenovo */ switch(rval) { case 0x00: pstr = "Absent"; break; case 0x80: pstr = "Present"; break; default: pstr = "Error"; break; } rv = 0; } break; case 0x0C: /* DIMM slot status */ /* Special DIMM status reported on IBM/Lenovo */ /* IBM x3650 M2 (0x0002, 0x00dc) and * Lenovo x3650 M4 (0x4f4d, 0x0143) */ if (etype == 0x6F) { switch(rval) { case 0x00: pstr = "Absent"; break; case 0x40: pstr = "Present"; break; default: pstr = "Error"; break; } rv = 0; } break; case 0x0D: /* Disk Drive slots */ if (etype == 0x6F) { switch(bval) { case 0x00: pstr = "Absent"; break; case 0x01: pstr = "Present"; break; case 0x21: pstr = "NotRedundant"; break; case 0x40: pstr = "NotAvailable"; break; /*not initialized*/ default: pstr = "Faulty"; break; /*e.g. 0x03*/ } rv = 0; } break; case 0x0F: /* ABR Status, Firmware Error, Sys Boot Status, etc. */ if (etype == 0x6F) { /* should be entity 0x22 */ if (bval == 0x00) pstr = "OK"; else if (bval & 0x01) pstr = "FirmwareError"; /*bit 0*/ else if ((bval & 0x02) != 0) pstr = "FirmwareHang"; /*bit 1*/ else pstr = "OK*"; rv = 0; } break; case 0x17: /* RSA II Detect, Mem1 Detect (mfg=0002:0077) */ /* mfg=0002:0077 sensor type=17 evt=8 entity=b rval=0002, RSA II*/ /* mfg=0002:0077 sensor type=17 evt=8 entity=8 rval=0002, Mem1 */ switch(rval) { case 0x02: pstr = "OK"; break; default: pstr = "Unknown"; break; } rv = 0; break; case 0x1B: /* Front USB, nvDIMM Cable, etc. */ if (etype == 0x6F) { /* 0x01 = connected/OK, 0x02 = cable connect error */ switch(bval) { case 0x01: pstr = "OK"; break; case 0x02: pstr = "CableError"; break; default: pstr = "OK*"; break; } rv = 0; } break; case 0x1E: /* No Boot Device */ if (etype == 0x6F) { switch(b) { case 0x00: pstr = "OK"; break; /*No Media*/ default: pstr = "Asserted"; break; } rv = 0; } case 0x21: /*All PCI Error, PCI 1, Internal RAID, No Op ROM, etc.*/ if (etype == 0x6F) { if (bval == 0x00) pstr = "OK"; else pstr = "Fault"; rv = 0; } break; case 0x25: /* DASD Backplane*/ /*spec says 00 = Present, 01 = Absent, but not match results*/ /* 0066 SDR Comp 02 6f 20 a 25 snum 20 DASD Backplane 1 = 0001 OK* 0067 SDR Comp 02 6f 20 a 25 snum 21 DASD Backplane 2 = 0000 Absent 0068 SDR Comp 02 6f 20 a 25 snum 22 DASD Backplane 3 = 0000 Absent 0069 SDR Comp 02 6f 20 a 25 snum 23 DASD Backplane 4 = 0000 Absent 006a SDR Comp 02 6f 20 a 25 snum 24 DASD Backplane 5 = 0000 Absent 006b SDR Comp 02 6f 20 a 25 snum 25 DASD Backplane 6 = 0000 Absent */ rv = -1; break; case 0x2B: /* ROM Recovery, Bkup Auto Update, IMM*/ if (etype == 0x6F) { switch(bval) { case 0x00: pstr = "OK"; break; case 0x01: pstr = "Changed"; break; /*entity 0x22*/ case 0x05: pstr = "Invalid"; break; /*entity 0x21*/ case 0x07: pstr = "ChangedOK"; break; /*entity 21,22*/ default: pstr = "_"; break; } rv = 0; } break; case 0x02: /* SysBrd Vol Fault: et 07 8004=error */ if (etype == 0x07) { if ((bval & 0x04) != 0) pstr = "Faulty"; else pstr = "OK"; rv = 0; } break; case 0x28: /* Low Security Jmp et 08 8002=error*/ if (etype == 0x08) { if ((bval & 0x02) != 0) pstr = "Faulty"; else pstr = "OK"; rv = 0; } break; default: break; } if (rv == 0) snprintf(pstring,slen,"%s",pstr); // if (rv == 0) strncpy(pstring, pstr, slen); return(rv); } /* * decode_sel_lenovo * inputs: * evt = the 16-byte IPMI SEL event * outbuf = points to the output string buffer * outsz = size of the output buffer * outputs: * rv = 0 if this event was successfully interpreted here, * non-zero otherwise, to use default interpretations. * outbuf = will contain the interpreted event text string (if rv==0) */ int decode_sel_lenovo(uchar *evt, char *outbuf, int outsz, char fdesc, char fdbg) { int rv = -1; ushort id; uchar rectype; ulong timestamp; char mybuf[64]; char *type_str = ""; char *pstr = NULL; uchar sevid; ushort genid; uchar snum, etype; uchar data1, data2, data3; fdebug = fdbg; sevid = SEV_INFO; id = evt[0] + (evt[1] << 8); rectype = evt[2]; snum = evt[11]; timestamp = evt[3] + (evt[4] << 8) + (evt[5] << 16) + (evt[6] << 24); genid = evt[7] | (evt[8] << 8); etype = evt[12]; data1 = evt[13]; data2 = evt[14]; data3 = evt[15]; if (rectype == 0x02) { sprintf(mybuf,"%02x [%02x %02x %02x]", etype,data1,data2,data3); pstr = get_ibm_desc(evt[10], snum, etype, data1, data2, data3, &sevid); if (pstr != NULL) { type_str = "IBM_type"; rv = 0; } else { switch(evt[10]) { /*sensor type*/ case 0xC0: /* OEM type */ type_str = "OEM_type"; pstr = "OEM Sensor "; sevid = SEV_MAJ; rv = -1; break; default: /*other sensor types*/ break; } } } if (rv == 0) { format_event(id,timestamp, sevid, genid, type_str, snum,NULL,pstr,mybuf,outbuf,outsz); } return(rv); } static void usage(void) { printf("Usage: %s [arg]\n",progname); printf("These commands may not work on all Lenovo systems\n"); } static int ipmi_oemlenovo_main(int argc, char **argv) { int rv = 0; if (strncmp(argv[0],"other",9) == 0) { usage(); rv = ERR_USAGE; } else { usage(); rv = ERR_USAGE; } return(rv); } #ifdef METACOMMAND int i_oemlenovo(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int rv = 0; uchar devrec[16]; int c, i; char *s1; printf("%s ver %s\n", progname,progver); set_loglevel(LOG_NOTICE); parse_lan_options('V',"4",0); /*default to admin priv*/ while ( (c = getopt( argc, argv,"m:xzEF:J:N:P:R:T:U:V:YZ:?")) != EOF ) switch(c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'x': fdebug = 2; /* normal (dbglog if isol) */ verbose = 1; break; case 'z': fdebug = 3; /*full debug (for isol)*/ verbose = 1; break; case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: usage(); return(ERR_USAGE); break; } for (i = 0; i < optind; i++) { argv++; argc--; } if (argc == 0) { usage(); return(ERR_USAGE); } rv = ipmi_getdeviceid(devrec,16,fdebug); if (rv == 0) { char ipmi_maj, ipmi_min; ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16); prod_id = devrec[9] + (devrec[10] << 8); show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); } rv = ipmi_oemlenovo_main(argc, argv); ipmi_close_(); return(rv); } /* end oem_lenovo.c */ ipmiutil-3.1.5/util/ifru.h0000644000076400007640000000043713566765324015555 0ustar mgportalloggers/* * ifru.h * common routines from ifru.c */ #ifndef uchar #define uchar unsigned char #endif int load_fru(uchar sa, uchar frudev, uchar frutype, uchar **pfrubuf); int show_fru(uchar sa, uchar frudev, uchar frutype, uchar *pfrubuf); void free_fru(uchar *pfrubuf); /* end ifru.h */ ipmiutil-3.1.5/util/oem_kontron.c0000644000076400007640000007060713566765324017143 0ustar mgportalloggers/* * oem_kontron.c * This code implements Kontron OEM proprietary commands. * * Change history: * 08/25/2010 ARCress - included in source tree * *--------------------------------------------------------------------- */ /* * Copyright (c) 2004 Kontron Canada, Inc. All Rights Reserved. * * Base on code from * Copyright (c) 2003 Sun Microsystems, 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: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution 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. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ /* * Tue Mar 7 14:36:12 2006 * * * This code implements an Kontron OEM proprietary commands. */ #ifdef WIN32 #include #include #include #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int typedef uint32_t socklen_t; #else #include #include #include #include #endif #include #include #include #include "ipmicmd.h" #include "ievents.h" #include "oem_kontron.h" #define FRU_TYPE_COMPONENT 0x01 #define FRU_TYPE_BASEBOARD 0x07 #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil kontronoem"; #else static char * progver = "3.08"; static char * progname = "ikontronoem"; #endif const struct valstr ktc5520_post[] = { /*from EAS*/ { 0x0003, "Start POST Init" }, { 0x0004, "Check CMOS" }, { 0x0005, "Init interrupt HW" }, { 0x0006, "Init INT1Ch" }, { 0x0008, "Init CPUs" }, { 0x000A, "Init 8042 Keyboard" }, { 0x000B, "Detect PS2 Mouse" }, { 0x000C, "Detect KBC Keyboard" }, { 0x000E, "Test Input Devices" }, { 0x0013, "PreInit chipset regs" }, { 0x0024, "Init platform modules" }, { 0x002A, "Init PCI devices" }, { 0x002C, "Init Video" }, { 0x002E, "Init Output devices" }, { 0x0030, "Init SMI" }, { 0x0031, "Init ADM module" }, { 0x0033, "Init Silent boot" }, { 0x0037, "Show first message" }, { 0x0038, "Init Buses" }, { 0x0039, "Init DMAC" }, { 0x003A, "Init RTC" }, { 0x003B, "Memory Test" }, { 0x003C, "MidInit chipset regs" }, { 0x0040, "Detect Ports" }, { 0x0050, "Adjust RAM size" }, { 0x0052, "Update CMOS size" }, { 0x0060, "Init Kbd Numlock" }, { 0x0075, "Init Int13" }, { 0x0078, "Init IPL" }, { 0x007A, "Init OpRoms" }, { 0x007C, "Write ESCD to NV" }, { 0x0084, "Log errors" }, { 0x0085, "Display errors" }, { 0x0087, "Run BIOS Setup" }, { 0x008C, "LateInit chipset regs" }, { 0x008D, "Build ACPI Tables" }, { 0x008E, "Program peripherals" }, { 0x0090, "LateInit SMI" }, { 0x00A0, "Check Boot password" }, { 0x00A1, "PreBoot Cleanup" }, { 0x00A2, "Init Runtime image" }, { 0x00A4, "Init Runtime lang" }, { 0x00A7, "Show Config, Init MTRR" }, { 0x00A8, "Prep CPU for OS boot" }, { 0x00A9, "Wait for input" }, { 0x00AA, "Deinit ADM, Int1C" }, { 0x00AB, "Prepare BBS" }, { 0x00AC, "EndInit chipse regs" }, { 0x00B1, "Save context for ACPI" }, { 0x00C0, "EarlyCPU Init APIC" }, { 0x00C1, "Setup BSP info" }, { 0x00C2, "Setup BSP for POST" }, { 0x00C5, "Setup App Processors" }, { 0x00C6, "Setup BSP cache" }, { 0x00C7, "EarlyCPU Init exit" }, { 0x0000, "OS Loader" }, { 0xffff , NULL } /*end of list*/ }; /* 61-70, OEM POST Error. This range is reserved for chipset vendors & system manufacturers. The error associated with this value may be different from one platform to the next. DD-DE, OEM PCI init debug POST code during DIMM init, See DIM Code Checkpoints section of document for more information. DD-DE, OEM PCI init debug POST code during DIMM init. DEh during BUS number */ extern int verbose; /*ipmilanplus.c*/ #ifdef METACOMMAND extern int load_fru(uchar sa, uchar frudev, uchar frutype, uchar **pfrubuf); extern int write_fru_data(uchar id, ushort offset, uchar *data, int dlen, char fdebug); /*ifru.c*/ #endif /* local function prototypes */ static void ipmi_kontron_help(void); static int ipmi_kontron_set_serial_number(void * intf); static int ipmi_kontron_set_mfg_date (void * intf); static void print_buf( uint8_t * buf, int len, char * desc) { dump_buf(desc,buf,len,0); } #ifdef METACOMMAND /* get_fru_area_str - Parse FRU area string from raw data * @data: raw FRU data * @offset: offset into data for area * returns pointer to FRU area string */ static char * get_fru_area_str(uint8_t * data, uint32_t * offset) { static const char bcd_plus[] = "0123456789 -.:,_"; char * str; int len, off, size, i, j, k, typecode; union { uint32_t bits; char chars[4]; } u; size = 0; off = *offset; /* bits 6:7 contain format */ typecode = ((data[off] & 0xC0) >> 6); /* bits 0:5 contain length */ len = data[off++]; len &= 0x3f; switch (typecode) { case 0: /* 00b: binary/unspecified */ /* hex dump -> 2x length */ size = (len*2); break; case 2: /* 10b: 6-bit ASCII */ /* 4 chars per group of 1-3 bytes */ size = ((((len+2)*4)/3) & ~3); break; case 3: /* 11b: 8-bit ASCII */ case 1: /* 01b: BCD plus */ /* no length adjustment */ size = len; break; } if (size < 1) { *offset = off; return NULL; } str = malloc(size+1); if (str == NULL) return NULL; memset(str, 0, size+1); if (len == 0) { str[0] = '\0'; *offset = off; return str; } switch (typecode) { case 0: /* Binary */ strncpy(str, buf2str(&data[off], len), len*2); break; case 1: /* BCD plus */ for (k=0; k 1 ? data[off+i+1] : 0); u.chars[1] = (k > 2 ? data[off+i+2] : 0); #define CHAR_IDX 3 #else memcpy((void *)&u.bits, &data[off+i], k); #define CHAR_IDX 0 #endif for (k=0; k<4; k++) { str[j++] = ((u.chars[CHAR_IDX] & 0x3f) + 0x20); u.bits >>= 6; } } str[j] = '\0'; break; case 3: memcpy(str, &data[off], len); str[len] = '\0'; break; } off += len; *offset = off; return str; } #endif static char *bootdev[] = {"BIOS", "FDD", "HDD", "CDROM", "network", 0}; static void ipmi_kontron_nextboot_help(void) { int i; printf("nextboot \n" "Supported devices:\n"); for (i = 0; bootdev[i] != 0; i++) { printf("- %s\n", bootdev[i]); } } /* ipmi_kontron_next_boot_set - Select the next boot order on CP6012 * * @intf: ipmi interface * @id: fru id * * returns -1 on error * returns 1 if successful */ static int ipmi_kontron_nextboot_set(void * intf, int argc, char **argv) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t msg_data[8]; int i; memset(msg_data, 0, sizeof(msg_data)); msg_data[0] = 0xb4; msg_data[1] = 0x90; msg_data[2] = 0x91; msg_data[3] = 0x8b; msg_data[4] = 0x9d; msg_data[5] = 0xFF; msg_data[6] = 0xFF; /* any */ for (i = 0; bootdev[i] != 0; i++) { if (strcmp(argv[0], bootdev[i]) == 0) { msg_data[5] = (uchar)i; break; } } /* Invalid device selected? */ if (msg_data[5] == 0xFF) { printf("Unknown boot device: %s\n", argv[0]); return -1; } memset(&req, 0, sizeof(req)); req.msg.netfn = 0x3E; req.msg.cmd = 0x02; req.msg.data = msg_data; req.msg.data_len = 7; /* Set Lun temporary, necessary for this oem command */ req.msg.lun = 0x03; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { printf(" Device not present (No Response)\n"); return (rv); } if (rv > 0) { printf(" NextBoot Device error (%s)\n",decode_cc(0,rv)); return(rv); } return (rv); } #ifdef METACOMMAND int ipmi_kontronoem_main(void * intf, int argc, char ** argv) { int rc = 0; if (argc == 0) ipmi_kontron_help(); else if (strncmp(argv[0], "help", 4) == 0) ipmi_kontron_help(); else if(!strncmp(argv[0], "setsn", 5)) { if(argc >= 1) { rc = ipmi_kontron_set_serial_number(intf); if(rc == 0) { printf("FRU serial number set successfully\n"); } else { printf("FRU serial number set failed\n"); } } else { printf("fru setsn\n"); } } else if(!strncmp(argv[0], "setmfgdate", 5)) { if(argc >= 1) { rc = ipmi_kontron_set_mfg_date(intf); if (rc == 0) { printf("FRU manufacturing date set successfully\n"); } else { printf("FRU manufacturing date set failed\n"); } } else { printf("fru setmfgdate\n"); } } else if (!strncmp(argv[0], "nextboot", sizeof("nextboot")-1)) { if (argc > 1) { if ((rc = ipmi_kontron_nextboot_set(intf, argc-1, argv+1)) == 0) { printf("Nextboot set successfully\n"); } else { printf("Nextboot set failed\n"); } } else { ipmi_kontron_nextboot_help(); } } else { printf("Invalid Kontron command: %s", argv[0]); ipmi_kontron_help(); rc = ERR_USAGE; } return rc; } static void ipmi_kontron_help(void) { printf("Kontron Commands: setsn setmfgdate nextboot\n"); } /* ipmi_fru_set_serial_number - Set the Serial Number in FRU * * @intf: ipmi interface * @id: fru id * * returns -1 on error * returns 1 if successful */ static int ipmi_kontron_set_serial_number(void * intf) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; struct fru_info fru; struct fru_header header; uint8_t msg_data[4]; char *sn; uint8_t sn_size, checksum; uint8_t *fru_data; char *fru_area; uint32_t fru_data_offset, fru_data_offset_tmp, board_sec_len, prod_sec_len, i; uint8_t bus, sa, lun, mtype; sn = NULL; fru_data = NULL; ipmi_get_mc(&bus, &sa, &lun, &mtype); memset(msg_data, 0, 4); msg_data[0] = 0xb4; msg_data[1] = 0x90; msg_data[2] = 0x91; msg_data[3] = 0x8b; memset(&req, 0, sizeof(req)); req.msg.netfn = 0x3E; req.msg.cmd = 0x0C; req.msg.data = msg_data; req.msg.data_len = 4; /* Set Lun, necessary for this oem command */ req.msg.lun = 0x03; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { printf(" Device not present (No Response)\n"); return (rv); } if (rv > 0) { if (verbose) printf("sernum cmd ccode = %02x\n",rv); printf(" This option is not implemented for this board\n"); #ifdef TEST strcpy(rsp,"serialnumber"); rsp_len = 12; #else return (rv); #endif } sn_size = (uchar)rsp_len; if (sn_size < 1) { printf(" Original serial number is zero length, was cleared.\n"); return(ERR_BAD_LENGTH); } sn = malloc(sn_size + 1); if(sn == NULL) { printf("Out of memory!"); return(-1); } memset(sn, 0, sn_size + 1); memcpy(sn, rsp, sn_size); if(verbose >= 1) { printf("Original serial number is : [%s]\n", sn); } memset(msg_data, 0, 4); msg_data[0] = 0; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_STORAGE; req.msg.cmd = GET_FRU_INFO; req.msg.data = msg_data; req.msg.data_len = 1; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { printf(" Device not present (No Response)\n"); free(sn); return (rv); } if (rv > 0) { printf(" Device not present (%s)\n",decode_cc(0,rv)); free(sn); return (rv); } fru.size = (rsp[1] << 8) | rsp[0]; fru.access = rsp[2] & 0x1; if (fru.size < 1) { printf(" Invalid FRU size %d", fru.size); free(sn); return(ERR_BAD_LENGTH); } /* * retrieve the FRU header */ msg_data[0] = 0; msg_data[1] = 0; msg_data[2] = 0; msg_data[3] = 8; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_STORAGE; req.msg.cmd = GET_FRU_DATA; req.msg.data = msg_data; req.msg.data_len = 4; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { printf(" Device not present (No Response)\n"); free(sn); return(rv); } if (rv > 0) { printf(" Device not present (%s)\n",decode_cc(0,rv)); free(sn); return(rv); } if (verbose >= 1) print_buf(rsp, rsp_len, "FRU DATA"); memcpy(&header, rsp + 1, 8); if (header.version != 1) { printf(" Unknown FRU header version 0x%02x\n", header.version); free(sn); return(-1); } /* Set the Board Section */ board_sec_len = (header.offset.product * 8) - (header.offset.board * 8); rv = load_fru(sa,0, FRU_TYPE_BASEBOARD, &fru_data); if (rv != 0) { printf(" Cannot Read FRU, error %d\n",rv); free(sn); if (fru_data != NULL) free(fru_data); return(rv); } if (verbose >= 1) print_buf(fru_data, fru.size, "FRU BUFFER"); /*Position at Board Manufacturer*/ fru_data_offset = (header.offset.board * 8) + 6; fru_area = &fru_data[fru_data_offset]; if (verbose) printf("board_area: offset=0x%x len=%d\n",fru_data_offset,board_sec_len); fru_area = get_fru_area_str(fru_data, &fru_data_offset); /*Position at Board Product Name*/ fru_area = get_fru_area_str(fru_data, &fru_data_offset); fru_data_offset_tmp = fru_data_offset; /*Position at Serial Number*/ fru_area = get_fru_area_str(fru_data, &fru_data_offset_tmp); if (fru_area == NULL) { printf("Bad FRU area data read.\n"); free(sn); free(fru_data); return(-1); } fru_data_offset ++; if (verbose) printf("%x: Old board sernum [%s], New board sernum [%s]\n", fru_data_offset,fru_area,sn); if (strlen(fru_area) != sn_size) { printf("The length of the serial number in the FRU Board Area is wrong.\n"); free(sn); free(fru_data); return(ERR_BAD_LENGTH); } /* Copy the new serial number in the board section saved in memory*/ memcpy(fru_data + fru_data_offset, sn, sn_size); /* Calculate Header Checksum */ checksum = 0; for( i = (header.offset.board * 8); i < (((header.offset.board * 8)+board_sec_len) - 2) ; i ++ ) { checksum += fru_data[i]; } checksum = (~checksum) + 1; fru_data[(header.offset.board * 8)+board_sec_len - 1] = checksum; #ifdef TEST if (verbose >= 1) print_buf(fru_data, fru.size, "FRU BUFFER, New"); /* Write the new FRU Board section */ rv = write_fru_data(0, 0, fru_data, fru.size, verbose); // if(write_fru_area(intf, &fru, 0, (header.offset.board * 8), (header.offset.board * 8), board_sec_len, fru_data) < 0) if ( rv != 0 ) { printf(" Cannot Write FRU, error %d\n",rv); free(sn); free(fru_data); return(rv); } if (fru_data != NULL) { free(fru_data); fru_data = NULL; } rv = load_fru(sa,0, FRU_TYPE_BASEBOARD, &fru_data); if (rv != 0) { printf(" Cannot Read FRU, error %d\n",rv); free(sn); if (fru_data != NULL) free(fru_data); return(rv); } #endif /* Set the Product Section */ prod_sec_len = (header.offset.multi * 8) - (header.offset.product * 8); /*Position at Product Manufacturer*/ fru_data_offset = (header.offset.product * 8) + 3; fru_area = get_fru_area_str(fru_data, &fru_data_offset); /*Position at Product Name*/ fru_area = get_fru_area_str(fru_data, &fru_data_offset); /*Position at Product Part*/ fru_area = get_fru_area_str(fru_data, &fru_data_offset); /*Position at Product Version*/ fru_area = get_fru_area_str(fru_data, &fru_data_offset); fru_data_offset_tmp = fru_data_offset; /*Position at Serial Number*/ fru_area = get_fru_area_str(fru_data, &fru_data_offset_tmp); fru_data_offset ++; if (verbose) printf("%x: Old product sernum [%s], New product sernum [%s]\n", fru_data_offset,fru_area,sn); if(strlen(fru_area) != sn_size) { free(sn); free(fru_data); printf("The length of the serial number in the FRU Product Area is wrong.\n"); return(ERR_BAD_LENGTH); } /* Copy the new serial number in the product section saved in memory*/ memcpy(fru_data + fru_data_offset, sn, sn_size); /* Calculate Header Checksum */ checksum = 0; for( i = (header.offset.product * 8); i < (((header.offset.product * 8)+prod_sec_len) - 2) ; i ++ ) { checksum += fru_data[i]; } checksum = (~checksum) + 1; fru_data[(header.offset.product * 8)+prod_sec_len - 1] = checksum; if (verbose >= 1) print_buf(fru_data, fru.size, "FRU BUFFER, New"); /* Write the new FRU Board section */ rv = write_fru_data(0, 0, fru_data, fru.size, (char)verbose); if ( rv != 0 ) { printf(" Cannot Write FRU, error %d\n",rv); /* fall through and free(sn); free(fru_data); return(rv); */ } free(sn); free(fru_data); return(rv); } /* ipmi_fru_set_mfg_date - Set the Manufacturing Date in FRU * * @intf: ipmi interface * @id: fru id * * returns -1 on error * returns 1 if successful */ static int ipmi_kontron_set_mfg_date (void * intf) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; struct fru_info fru; struct fru_header header; uint8_t msg_data[4]; uint8_t mfg_date[3]; uint32_t board_sec_len, i; uint8_t *fru_data, checksum; uint8_t bus, sa, lun, mtype; ipmi_get_mc(&bus, &sa, &lun, &mtype); memset(msg_data, 0, 4); msg_data[0] = 0xb4; msg_data[1] = 0x90; msg_data[2] = 0x91; msg_data[3] = 0x8b; memset(&req, 0, sizeof(req)); req.msg.netfn = 0x3E; req.msg.cmd = 0x0E; req.msg.data = msg_data; req.msg.data_len = 4; /* Set Lun temporary, necessary for this oem command */ req.msg.lun = 0x03; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { printf("Device not present (No Response)\n"); return(rv); } if (rv > 0) { printf("This option is not implemented for this board\n"); return(rv); } if(rsp_len != 3) { printf("Invalid response for the Manufacturing date\n"); return(ERR_BAD_LENGTH); } if(rsp[0] == 0 && rsp[1] == 0 && rsp[2] == 0) { printf("Manufacturing date is zero, has been cleared\n"); return(ERR_BAD_FORMAT); } memset(mfg_date, 0, 3); memcpy(mfg_date, rsp, 3); memset(msg_data, 0, 4); msg_data[0] = 0; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_STORAGE; req.msg.cmd = GET_FRU_INFO; req.msg.data = msg_data; req.msg.data_len = 1; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { printf(" Device not present (No Response)\n"); return(rv); } if (rv > 0) { printf(" Device not present (%s)\n",decode_cc(0,rv)); return(rv); } fru.size = (rsp[1] << 8) | rsp[0]; fru.access = rsp[2] & 0x1; if (fru.size < 1) { printf(" Invalid FRU size %d", fru.size); return(ERR_BAD_LENGTH); } /* * retrieve the FRU header */ msg_data[0] = 0; msg_data[1] = 0; msg_data[2] = 0; msg_data[3] = 8; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_STORAGE; req.msg.cmd = GET_FRU_DATA; req.msg.data = msg_data; req.msg.data_len = 4; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { printf(" Device not present (No Response)\n"); return(rv); } if (rv > 0) { printf(" Device not present (%s)\n",decode_cc(0,rv)); return(rv); } if (verbose > 1) print_buf(rsp, rsp_len, "FRU DATA"); memcpy(&header, &rsp[1], 8); if (header.version != 1) { printf(" Unknown FRU header version 0x%02x", header.version); return(ERR_BAD_FORMAT); } board_sec_len = (header.offset.product * 8) - (header.offset.board * 8); rv = load_fru(sa,0, FRU_TYPE_BASEBOARD, &fru_data); if (rv != 0) #ifdef NOT /* do not re-read the same fru buffer */ fru_data = malloc( fru.size); if(fru_data == NULL) { printf("Out of memory!"); return(-1); } memset(fru_data, 0, fru.size); rv = read_fru_area(intf ,&fru ,0 ,(header.offset.board * 8) ,board_sec_len , fru_data); if(rv < 0) #endif { if (fru_data != NULL) free(fru_data); return(rv); } /* Copy the new manufacturing date in the board section saved in memory*/ memcpy(fru_data + (header.offset.board * 8) + 3, mfg_date, 3); checksum = 0; /* Calculate Header Checksum */ for( i = (header.offset.board * 8); i < (((header.offset.board * 8)+board_sec_len) - 2) ; i ++ ) { checksum += fru_data[i]; } checksum = (~checksum) + 1; fru_data[(header.offset.board * 8)+board_sec_len - 1] = checksum; /* Write the new FRU Board section */ #ifdef NOT if(write_fru_area(intf, &fru, 0, (header.offset.board * 8), (header.offset.board * 8), board_sec_len, fru_data) < 0) #endif rv = write_fru_data(0, 0, fru_data, fru.size, (char)verbose); if ( rv != 0 ) { printf(" Cannot Write FRU, error %d\n",rv); /* fall through and free(fru_data); return(rv); */ } free(fru_data); return(rv); } #endif static char *assert_str(uchar val) { char *pstr; if ((val & 0x0f) == 0) pstr = "Deasserted"; else pstr = "Asserted"; return(pstr); } /* * decode_sel_kontron * inputs: * evt = the 16-byte IPMI SEL event * outbuf = points to the output string buffer * outsz = size of the output buffer * outputs: * rv = 0 if this event was successfully interpreted here, * non-zero otherwise, to use default interpretations. * outbuf = will contain the interpreted event text string (if rv==0) */ int decode_sel_kontron(uint8_t *evt, char *outbuf, int outsz, char fdesc, char fdebug) { int rv = -1; uint16_t id; uint8_t rectype; int oemid; uint32_t timestamp; char timestr[40]; char mybuf[64]; char oembuf[64]; char *type_str = NULL; char *gstr = NULL; char *pstr = NULL; int sevid; ushort genid; uchar snum; char *p1, *p2; sevid = SEV_INFO; id = evt[0] + (evt[1] << 8); /* instead try to decode some events manually */ rectype = evt[2]; timestamp = evt[3] + (evt[4] << 8) + (evt[5] << 16) + (evt[6] << 24); genid = evt[7] | (evt[8] << 8); snum = evt[11]; if (rectype == 0xc1) { /* OEM type C1 */ oemid = evt[7] + (evt[8] << 8) + (evt[9] << 16); if (oemid == VENDOR_KONTRON) { fmt_time(timestamp, timestr, sizeof(timestr)); type_str = "Kontron"; gstr = "BMC "; switch(evt[10]) { case 0x01: default: sprintf(mybuf,"OEM Event %02x %02x %02x %02x %02x %02x", evt[10], evt[11], evt[12], evt[13], evt[14], evt[15]); break; } snprintf(outbuf, outsz, "%04x %s %s %s %s %s\n", id,timestr,get_sev_str(sevid), gstr, type_str, mybuf); rv = 0; } /*endif kontron*/ } else if (rectype == 0x02) { type_str = ""; gstr = "BMC "; sprintf(mybuf,"%02x [%02x %02x %02x]", evt[12],evt[13],evt[14],evt[15]); switch(evt[10]) { /*sensor type*/ /* TODO: 0xC0, 0xC2, 0xC6 */ case 0xCF: /* Board Reset */ type_str = "Board Reset"; if (evt[12] == 0x03) { /*event trigger/type = discrete [de]assert */ pstr = ""; /*default*/ switch(evt[13]) { /*data1/offset*/ case 0x01: pstr = "Asserted"; break; case 0xa1: /*data2,3 bytes have meaning*/ /* data2: usually 0x01 */ /* data3: 05, 08, ff */ switch(evt[14]) { /*data2*/ case 0x00: p1 = "warm reset"; break; case 0x01: p1 = "cold reset"; break; case 0x02: p1 = "forced cold"; break; case 0x03: p1 = "soft reset"; break; case 0x04: p1 = "hard reset"; break; case 0x05: p1 = "forced hard"; break; default: p1 = "other"; break; } switch(evt[15]) { /*data3*/ case 0x00: p2 = "IPMI watchdog"; break; case 0x01: p2 = "IPMI command"; break; case 0x02: p2 = "Proc check stop"; break; /*internal*/ case 0x03: p2 = "Proc reset request"; break; /*internal*/ case 0x04: p2 = "Reset button"; break; case 0x05: p2 = "Power up"; break; case 0x06: p2 = "Legacy int watchdog"; break; /*internal*/ case 0x07: p2 = "Legacy prg watchdog"; break; /*programmable*/ case 0x08: p2 = "Software initiated"; break; case 0x09: p2 = "Setup reset"; break; case 0x0a: p2 = "Power cycle"; break; default: p2 = "Other"; break; } sprintf(oembuf,"%s/%s",p1,p2); pstr = oembuf; break; default: break; } rv = 0; } break; case 0x12: /* System Event */ /* snum 38, 6f 00, or ef 00 */ /* if (snum == 0x38) */ type_str = "System Event"; if (evt[12] == 0x6f) pstr = assert_str(1); /*asserted*/ else pstr = assert_str(0); /*0xef means deasserted*/ rv = 0; break; case 0x24: /* Platform Alert */ /* usu 03 01 */ type_str = "Platform Alert"; pstr = assert_str(evt[13]); /*data1*/ rv = 0; break; case 0x2B: /* Version Change */ /* 6f c1 02 ff */ type_str = "Version Change"; if ((evt[13] & 0x80) == 0) pstr = ""; else switch(evt[14]) { /*data2*/ case 0x01: pstr = "HW Changed"; break; case 0x02: pstr = "SW Changed"; break; case 0x03: pstr = "HW incompatible"; break; default: pstr = "Change failed"; break; /*TODO: add detail here*/ } rv = 0; break; case 0x70: type_str = "OEM Firmware Info 1"; pstr = assert_str(evt[13]); /*data1*/ rv = 0; break; case 0x71: type_str = "OEM Firmware Info 2"; pstr = assert_str(evt[13]); /*data1*/ rv = 0; break; default: break; } if (rv == 0) { format_event(id,timestamp, sevid, genid, type_str, snum,NULL,pstr,mybuf,outbuf,outsz); } } return rv; } /*end decode_sel_kontron*/ int decode_sensor_kontron(uchar *sdr,uchar *reading,char *pstring, int slen) { int rv = -1; uchar stype; char *pstr = NULL; int rdval; if (sdr == NULL || reading == NULL) return(rv); if (pstring == NULL || slen == 0) return(rv); if (sdr[3] != 0x02) return(rv); /*skip if not compact sensor*/ stype = sdr[12]; rdval = reading[2] | ((reading[3] & 0x7f) << 8); /* usually reading3 == 0x80 */ switch(stype) { case 0x08: /* Power Supply or PwrGood ... */ if (sdr[14] == 0x02) { if (reading[2] & 0x02) pstr = "Failed"; else pstr = "OK"; rv = 0; } break; case 0xC0: /* IPMI Info-N */ if (reading[2] == 0) pstr = "OK"; else pstr = "Asserted"; rv = 0; break; case 0xC2: /* IniAgent Err */ if ((reading[2] & 0x01) == 1) pstr = "OK"; else pstr = "Error"; /*could be 0x02*/ rv = 0; break; case 0xC6: /* POST Value */ pstr = (char *)val2str((ushort)rdval,ktc5520_post); if (pstr == NULL) { if (rdval >= 0x61 && rdval <= 0x71) pstr = "Error"; else if (rdval >= 0xDD && rdval <= 0xDE) pstr = "DIMM Debug"; else pstr = "Other"; } rv = 0; break; case 0xCF: /* Board Reset */ if ((reading[2] & 0x01) == 1) pstr = "OK"; else pstr = "Asserted"; rv = 0; break; default: break; } if (rv == 0) strncpy(pstring, pstr, slen); return(rv); } #ifdef METACOMMAND int i_kontronoem(int argc, char **argv) { printf("%s ver %s\n", progname,progver); return(0); } #endif /* end oem_kontron.c */ ipmiutil-3.1.5/util/iekanalyzer.c0000644000076400007640000045053213566765324017126 0ustar mgportalloggers/* * iekanalyzer.c * Handle FRU EKey Analyzer functions * * Change history: * 09/08/2010 ARCress - included in source tree * *--------------------------------------------------------------------- */ /* * Copyright (c) 2007 Kontron Canada, Inc. All Rights Reserved. * * Base on code from * Copyright (c) 2003 Sun Microsystems, 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: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution 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. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #include #include #include #include #ifdef WIN32 #include #include "getopt.h" #else #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include "ipmicmd.h" #include "iekanalyzer.h" #ifdef HAVE_EK extern int verbose; /*ipmilanplus.c*/ extern void lprintf(int level, const char * format, ...); /*ipmilanplus.c*/ extern void set_loglevel(int level); /* fseek wrapper for size_t/long compile warnings */ static int fseek_(FILE *fp, size_t offset, int whence) { return(fseek(fp, (long)offset, whence)); } /***************************************************************** * CONSTANT *****************************************************************/ const int ERROR_STATUS = -1; const int OK_STATUS = 0; const char * STAR_LINE_LIMITER = "*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*"; const char * EQUAL_LINE_LIMITER = "================================================================="; const int SIZE_OF_FILE_TYPE = 3; const unsigned char AMC_MODULE = 0x80; const int PICMG_ID_OFFSET = 3; #define MAX_ARGC (MAX_FILE_NUMBER+4) /*8+4=12*/ #define COMPARE_CANDIDATE 2 /*In AMC.0 or PICMG 3.0 specification offset start from 0 with 3 bytes of * Mfg.ID, 1 byte of Picmg record Id, and * 1 byte of format version, so the data offset start from 5 */ #define LOWER_OEM_TYPE 0xf0 #define UPPER_OEM_TYPE 0xfe const int START_DATA_OFFSET = 5; const unsigned char DISABLE_PORT = 0x1f; const struct valstr ipmi_ekanalyzer_module_type[] = { { ON_CARRIER_FRU_FILE, "On-Carrier Device" }, { A1_AMC_FRU_FILE, "AMC slot A1" }, { A2_AMC_FRU_FILE, "AMC slot A2" }, { A3_AMC_FRU_FILE, "AMC slot A3" }, { A4_AMC_FRU_FILE, "AMC slot A4" }, { B1_AMC_FRU_FILE, "AMC slot B1" }, { B2_AMC_FRU_FILE, "AMC slot B2" }, { B3_AMC_FRU_FILE, "AMC slot B3" }, { B4_AMC_FRU_FILE, "AMC slot B4" }, { RTM_FRU_FILE, "RTM" }, /*This is OEM specific module*/ { CONFIG_FILE, "Configuration file" }, { SHELF_MANAGER_FRU_FILE, "Shelf Manager" }, { 0xffff , NULL }, }; const struct valstr ipmi_ekanalyzer_IPMBL_addr[] = { { 0x72, "AMC slot A1" }, { 0x74, "AMC slot A2" }, { 0x76, "AMC slot A3" }, { 0x78, "AMC slot A4" }, { 0x7a, "AMC slot B1" }, { 0x7c, "AMC slot B2" }, { 0x7e, "AMC slot B3" }, { 0x80, "AMC slot B4" }, { 0x90, "RTM"}, /*This is OEM specific module*/ { 0xffff , NULL }, }; const struct valstr ipmi_ekanalyzer_link_type[] = { { 0x00, "Reserved" }, { 0x01, "Reserved" }, { 0x02, "AMC.1 PCI Express" }, { 0x03, "AMC.1 PCI Express Advanced Switching" }, { 0x04, "AMC.1 PCI Express Advanced Switching" }, { 0x05, "AMC.2 Ethernet" }, { 0x06, "AMC.4 Serial RapidIO" }, { 0x07, "AMC.3 Storage" }, /*This is OEM specific module*/ { 0xf0, "OEM Type 0"}, { 0xf1, "OEM Type 1"}, { 0xf2, "OEM Type 2"}, { 0xf3, "OEM Type 3"}, { 0xf4, "OEM Type 4"}, { 0xf5, "OEM Type 5"}, { 0xf6, "OEM Type 6"}, { 0xf7, "OEM Type 7"}, { 0xf8, "OEM Type 8"}, { 0xf9, "OEM Type 9"}, { 0xfa, "OEM Type 10"}, { 0xfb, "OEM Type 11"}, { 0xfc, "OEM Type 12"}, { 0xfd, "OEM Type 13"}, { 0xfe, "OEM Type 14"}, { 0xff , "Reserved" }, }; /*Reference: AMC.1 specification*/ const struct valstr ipmi_ekanalyzer_extension_PCIE[] = { { 0x00, "Gen 1 capable - non SSC" }, { 0x01, "Gen 1 capable - SSC" }, { 0x02, "Gen 2 capable - non SSC" }, { 0x03, "Gen 3 capable - SSC" }, { 0x0f, "Reserved"}, }; /*Reference: AMC.2 specification*/ const struct valstr ipmi_ekanalyzer_extension_ETHERNET[] = { { 0x00, "1000BASE-BX (SerDES Gigabit) Ethernet link" }, { 0x01, "10GBASE-BX4 10 Gigabit Ethernet link" }, }; /*Reference: AMC.3 specification*/ const struct valstr ipmi_ekanalyzer_extension_STORAGE[] = { { 0x00, "Fibre Channel (FC)" }, { 0x01, "Serial ATA (SATA)" }, { 0x02, "Serial Attached SCSI (SAS/SATA)" }, }; const struct valstr ipmi_ekanalyzer_asym_PCIE[] = { { 0x00, "exact match"}, { 0x01, "provides a Primary PCI Express Port" }, { 0x02, "provides a Secondary PCI Express Port" }, }; const struct valstr ipmi_ekanalyzer_asym_STORAGE[] = { { 0x00, "FC or SAS interface {exact match}" }, { 0x01, "SATA Server interface" }, { 0x02, "SATA Client interface" }, { 0x03, "Reserved" }, }; const struct valstr ipmi_ekanalyzer_picmg_record_id[] = { { 0x04, "Backplane Point to Point Connectivity Record" }, { 0x10, "Address Table Record" }, { 0x11, "Shelf Power Distribution Record" }, { 0x12, "Shelf Activation and Power Management Record" }, { 0x13, "Shelf Manager IP Connection Record" }, { 0x14, "Board Point to Point Connectivity Record" }, { 0x15, "Radial IPMB-0 Link Mapping Record" }, { 0x16, "Module Current Requirements Record" }, { 0x17, "Carrier Activation and Power Management Record" }, { 0x18, "Carrier Point-to-Point Connectivity Record" }, { 0x19, "AdvancedMC Point-to-Point Connectivity Record" }, { 0x1a, "Carrier Information Table" }, { 0x1b, "Shelf Fan Geography Record" }, { 0x2c, "Carrier Clock Point-to-Point Connectivity Record" }, { 0x2d, "Clock Configuration Record" }, }; struct ipmi_ek_multi_header { struct fru_multirec_header header; unsigned char * data; struct ipmi_ek_multi_header * prev; struct ipmi_ek_multi_header * next; }; struct ipmi_ek_amc_p2p_connectivity_record{ unsigned char guid_count; struct fru_picmgext_guid * oem_guid; unsigned char rsc_id; unsigned char ch_count; struct fru_picmgext_amc_channel_desc_record * ch_desc; unsigned char link_desc_count; struct fru_picmgext_amc_link_desc_record * link_desc; int * matching_result; /*For link descriptor comparision*/ }; /***************************************************************************** * Function prototype ******************************************************************************/ /* global variables */ static char * progname = "iekanalyzer"; static char * progver = "1.00"; static char fdebug = 0; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; #ifndef HAVE_LANPLUS /* define these routines in ipmilanplus.c if no lanplus/helper.c */ extern const char * val2str(uint16_t val, const struct valstr *vs); #endif /**************************************************************************** * command Functions *****************************************************************************/ static int ipmi_ekanalyzer_print( int argc, char * opt, char ** filename, int * file_type ); static tboolean ipmi_ekanalyzer_ekeying_match( int argc, char * opt, char ** filename, int * file_type ); /**************************************************************************** * Linked list Functions *****************************************************************************/ static void ipmi_ek_add_record2list( struct ipmi_ek_multi_header ** record, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_last ); static void ipmi_ek_display_record( struct ipmi_ek_multi_header * record, struct ipmi_ek_multi_header * list_head, struct ipmi_ek_multi_header * list_last ); static void ipmi_ek_remove_record_from_list( struct ipmi_ek_multi_header * record, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_last ); static int ipmi_ekanalyzer_fru_file2structure( char * filename, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_record, struct ipmi_ek_multi_header ** list_last ); /**************************************************************************** * Ekeying match Functions *****************************************************************************/ static int ipmi_ek_matching_process( int * file_type, int index1, int index2, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_last, char * opt, struct ipmi_ek_multi_header * pphysical ); static int ipmi_ek_get_resource_descriptor( int port_count, int index, struct fru_picmgext_carrier_p2p_descriptor * port_desc, struct ipmi_ek_multi_header * record ); static int ipmi_ek_create_amc_p2p_record( struct ipmi_ek_multi_header * record, struct ipmi_ek_amc_p2p_connectivity_record * amc_record ); static int ipmi_ek_compare_link( struct ipmi_ek_multi_header * physic_record, struct ipmi_ek_amc_p2p_connectivity_record record1, struct ipmi_ek_amc_p2p_connectivity_record record2, char * opt, int file_type1, int file_type2 ); static tboolean ipmi_ek_compare_channel_descriptor( struct fru_picmgext_amc_channel_desc_record ch_desc1, struct fru_picmgext_amc_channel_desc_record ch_desc2, struct fru_picmgext_carrier_p2p_descriptor * port_desc, int index_port, unsigned char rsc_id ); static int ipmi_ek_compare_link_descriptor( struct ipmi_ek_amc_p2p_connectivity_record record1, int index1, struct ipmi_ek_amc_p2p_connectivity_record record2, int index2 ); static int ipmi_ek_compare_asym( unsigned char asym[COMPARE_CANDIDATE] ); static int ipmi_ek_compare_number_of_enable_port( struct fru_picmgext_amc_link_desc_record link_desc[COMPARE_CANDIDATE] ); static int ipmi_ek_check_physical_connectivity( struct ipmi_ek_amc_p2p_connectivity_record record1, int index1, struct ipmi_ek_amc_p2p_connectivity_record record2, int index2, struct ipmi_ek_multi_header * record, int filetype1, int filetype2, char * option ); /**************************************************************************** * Display Functions *****************************************************************************/ static int ipmi_ek_display_fru_header( char * filename ); static void ipmi_ek_display_fru_header_detail( char * filename ); static void ipmi_ek_display_chassis_info_area( FILE * input_file, long offset ); static size_t ipmi_ek_display_board_info_area( FILE * input_file, char * board_type, unsigned int * board_length ); static void ipmi_ek_display_product_info_area( FILE * input_file, long offset ); static tboolean ipmi_ek_display_link_descriptor( int file_type, unsigned char rsc_id, char * str, struct fru_picmgext_amc_link_desc_record link_desc ); static void ipmi_ek_display_oem_guid( struct ipmi_ek_amc_p2p_connectivity_record amc_record1 ); static int ipmi_ek_diplay_carrier_connectivity( struct ipmi_ek_multi_header * record ); static int ipmi_ek_display_power( int argc, char * opt, char ** filename, int * file_type ); static void ipmi_ek_display_current_descriptor( struct fru_picmgext_carrier_activation_record car, struct fru_picmgext_activation_record * cur_desc, char * filename ); static void ipmi_ek_display_backplane_p2p_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_address_table_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_shelf_power_distribution_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_shelf_activation_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_shelf_ip_connection_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_board_p2p_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_radial_ipmb0_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_amc_current_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_amc_activation_record ( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_amc_p2p_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_amc_carrier_info_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_clock_carrier_p2p_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_clock_config_record( struct ipmi_ek_multi_header * record ); /************************************************************************** * * Function name: ipmi_ekanalyzer_usage * * Description : Print the usage (help menu) of ekeying analyzer tool * * Restriction : None * * Input : None * * Output : None * * Global : None * * Return : None * ***************************************************************************/ static void ipmi_ekanalyzer_usage( void ) { char * help_message = "Ekeying analyzer tool version 1.00 \r\n\ ekanalyzer Commands: \r\n\ print [carrier | power | all] ... \r\n\ frushow \r\n\ summary [match | unmatch | all] ... \r\n\ "; printf("%s",help_message); fflush(stdout); } /************************************************************************** * * Function name: ipmi_ek_get_file_type * * Description: this function takes an argument, then xtract the file type and * convert into module type (on carrier, AMC,...) value. * * * Restriction: None * * Input: argument: strings contain the type and the name of the file * together * * Output: None * * Global: None * * Return: Return value of module type: On carrier FRU file, A1 FRUM file... * if the file type is invalid, it return -1. See structure * ipmi_ekanalyzer_module_type for a list of valid type. ***************************************************************************/ static int ipmi_ek_get_file_type( char * argument ) { // int index_name=0; int filetype = ERROR_STATUS; if( strlen (argument) > MIN_ARGUMENT ){ if( strncmp( argument, "oc=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = ON_CARRIER_FRU_FILE; } else if( strncmp( argument, "a1=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = A1_AMC_FRU_FILE; } else if( strncmp( argument, "a2=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = A2_AMC_FRU_FILE; } else if( strncmp( argument, "a3=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = A3_AMC_FRU_FILE; } else if( strncmp( argument, "a4=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = A4_AMC_FRU_FILE; } else if( strncmp( argument, "b1=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = B1_AMC_FRU_FILE; } else if( strncmp( argument, "b2=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = B2_AMC_FRU_FILE; } else if( strncmp( argument, "b3=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = B3_AMC_FRU_FILE; } else if( strncmp( argument, "b4=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = B4_AMC_FRU_FILE; } else if( strncmp( argument, "rt=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = RTM_FRU_FILE; } else if( strncmp( argument, "rc=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = CONFIG_FILE; } else if( strncmp( argument, "sm=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = SHELF_MANAGER_FRU_FILE; } else{ filetype = ERROR_STATUS; } } return filetype; } /************************************************************************** * * Function name: ipmi_ekanalyzer_main * * Description: Main program of ekeying analyzer. It calls the appropriate * function according to the command received. * * Restriction: None * * Input: ipmi_intf * intf: ? * int argc : number of argument received * int ** argv: argument strings * * Output: None * * Global: None * * Return: OK_STATUS as success or ERROR_STATUS as error * ***************************************************************************/ int ipmi_ekanalyzer_main( void * intf, int argc, char ** argv ) { int rc = ERROR_STATUS; int file_type[MAX_FILE_NUMBER]; char * filename[MAX_FILE_NUMBER]; unsigned int argument_offset = 0; unsigned int type_offset = 0; /*list des multi record*/ struct ipmi_ek_multi_header * list_head = NULL; struct ipmi_ek_multi_header * list_record = NULL; struct ipmi_ek_multi_header * list_last = NULL; set_loglevel(LOG_NOTICE); if ( (argc == 0) || ( (argc - 1) > MAX_FILE_NUMBER ) ){ lprintf(LOG_ERR, "Too few or too many arguments."); ipmi_ekanalyzer_usage(); rc = ERR_BAD_PARAM; } else if ( strcmp(argv[argument_offset], "help") == 0) { ipmi_ekanalyzer_usage(); rc = ERR_USAGE; } else if ( (strcmp(argv[argument_offset], "frushow") == 0) && (argc > (MIN_ARGUMENT-1) ) ){ for ( type_offset = 0; (int)type_offset < (argc-1); type_offset++ ){ argument_offset++; file_type[type_offset] = ipmi_ek_get_file_type (argv[argument_offset]); if ( file_type[type_offset] != ERROR_STATUS ){ if ( file_type[type_offset] != CONFIG_FILE ){ /* because of strlen doesn't count '\0', we need to add 1 byte for * this character to filename size */ filename[type_offset] = malloc( strlen(argv[argument_offset]) + 1 - SIZE_OF_FILE_TYPE ); if( filename[type_offset] != NULL ){ strcpy(filename[type_offset], &argv[argument_offset][SIZE_OF_FILE_TYPE]); printf("Start converting file '%s'...\n", filename[type_offset]); /* Display FRU header offset */ rc = ipmi_ek_display_fru_header (filename[type_offset]); if ( rc != ERROR_STATUS ){ /* Display FRU header info in detail record */ ipmi_ek_display_fru_header_detail (filename[type_offset]); /* Convert from binary data into multi record structure */ rc = ipmi_ekanalyzer_fru_file2structure ( filename[type_offset], &list_head, &list_record, &list_last ); ipmi_ek_display_record ( list_record, list_head, list_last ); /* Remove record of list */ while ( list_head != NULL ){ ipmi_ek_remove_record_from_list( list_head, &list_head,&list_last ); if (verbose > 1) printf("record has been removed!\n"); } } free (filename[type_offset]); } } } else{ lprintf(LOG_ERR, "Invalid file type!"); lprintf(LOG_ERR, " ekanalyzer frushow ..."); } } } else if ( (strcmp(argv[argument_offset], "print") == 0) || (strcmp(argv[argument_offset], "summary") == 0) ){ /*Display help of the correspond command if there is not enought argument * passing in command line */ if ( argc < MIN_ARGUMENT ){ printf("Too few argument! \n"); if ( strcmp(argv[argument_offset], "print") == 0 ){ lprintf(LOG_ERR, " ekanalyzer print [carrier/power/all]" " [xx=frufile]" ); } else{ lprintf(LOG_ERR, " ekanalyzer summary [match/ unmatch/ all]" " [xx=frufile]" ); } } else{ char * option; /*index=1 indicates start position of first file name in command line*/ int index = 1; int filename_size=0; argument_offset++; if ( (strcmp(argv[argument_offset], "carrier") == 0) || (strcmp(argv[argument_offset], "power") == 0) || (strcmp(argv[argument_offset], "all") == 0) ){ option = argv[argument_offset]; index ++; argc--; } else if ( ( strcmp(argv[argument_offset], "match") == 0 ) || ( strcmp(argv[argument_offset], "unmatch") == 0 ) ){ option = argv[argument_offset]; index ++; argc--; } /*since the command line must receive xx=filename, so the position of * "=" sign is 2 */ else if ( strncmp(&argv[argument_offset][2], "=", 1) == 0 ){ option = "default"; /* Since there is no option from user, the first argument * becomes first file type */ index = 1; /* index of argument */ } else{ option = "invalid"; printf("Invalid option '%s'\n", argv[argument_offset]); argument_offset--; if (strcmp(argv[0], "print") == 0){ lprintf (LOG_ERR, " ekanalyzer print [carrier/power/all]" " [xx=frufile]" ); } else{ lprintf (LOG_ERR, " ekanalyzer summary [match/ unmatch/ all]" " [xx=frufile]" ); } rc = ERROR_STATUS; } if ( strcmp(option, "invalid") != 0 ){ int i=0; for ( i = 0; i < (argc-1); i++){ file_type[i] = ipmi_ek_get_file_type (argv[index]); if ( file_type[i] == ERROR_STATUS ){ /* display the first 2 charactors (file type) of argument */ lprintf(LOG_ERR, "Invalid file type: %c%c\n", argv[index][0], argv[index][1]); ipmi_ekanalyzer_usage(); rc = ERROR_STATUS; break; } /*size is equal to string size minus 3 bytes of file type plus * 1 byte of '\0' since the strlen doesn't count the '\0' */ filename_size = strlen_( argv[index] ) - SIZE_OF_FILE_TYPE + 1; if ( filename_size > 0 ){ filename[i] = malloc( filename_size ); if (filename[i] != NULL) strcpy( filename[i], &argv[index][SIZE_OF_FILE_TYPE] ); } rc = OK_STATUS; index++; } if ( rc != ERROR_STATUS ){ if (verbose > 0){ for (i = 0; i < (argc-1); i++){ printf ("Type: %s, ", val2str((uint16_t)file_type[i], ipmi_ekanalyzer_module_type)); printf("file name: %s\n", filename[i]); } } if (strcmp(argv[0], "print") == 0){ rc = ipmi_ekanalyzer_print( (argc-1), option, filename, file_type); } else{ rc = ipmi_ekanalyzer_ekeying_match( (argc-1), option, filename, file_type); } for (i = 0; i < (argc-1); i++){ if (filename[i] != NULL){ free (filename[i]); } } } /* End of ERROR_STATUS */ } /* End of comparison of invalid option */ } /* End of else MIN_ARGUMENT */ } /* End of print or summary option */ else{ lprintf(LOG_ERR, "Invalid ekanalyzer command: %s", argv[0]); ipmi_ekanalyzer_usage(); rc = ERROR_STATUS; } return rc; } /************************************************************************** * * Function name: ipmi_ekanalyzer_print * * Description: this function will display the topology, power or both * information together according to the option that it received. * * Restriction: None * * Input: int argc: number of the argument received * char* opt: option string that will tell what to display * char** filename: strings that contained filename of FRU data binary file * int* file_type: a pointer that contain file type (on carrier file, * a1 file, b1 file...). See structure * ipmi_ekanalyzer_module_type for a list of valid type * * Output: None * * Global: None * * Return: return 0 as success and -1 as error. * ***************************************************************************/ static int ipmi_ekanalyzer_print( int argc,char * opt, char ** filename, int * file_type ) { int return_value = OK_STATUS; /*Display carrier topology*/ if ( (strcmp(opt, "carrier") == 0) || (strcmp(opt, "default") == 0) ){ tboolean found_flag = FALSE; int index = 0; int index_name[MAX_ARGC]; int list = 0; /*list of multi record*/ struct ipmi_ek_multi_header * list_head[MAX_ARGC]; struct ipmi_ek_multi_header * list_record[MAX_ARGC]; struct ipmi_ek_multi_header * list_last[MAX_ARGC]; for ( list=0; list < argc; list++ ){ list_head[list] = NULL; list_record[list] = NULL; list_last[list] = NULL; } list=0; /* reset list count */ for ( index = 0; index < argc; index++ ){ if ( file_type[index] == ON_CARRIER_FRU_FILE ){ index_name[list] = index; return_value = ipmi_ekanalyzer_fru_file2structure( filename[index], &list_head[list], &list_record[list], &list_last[list] ); list++; found_flag = TRUE; } } if ( !found_flag ){ printf("No carrier file has been found\n"); return_value = ERROR_STATUS; } else{ int i = 0; for ( i = 0; i < argc; i++ ){ /*this is a flag to advoid displaying the same data multiple time*/ tboolean first_data = TRUE; for ( list_record[i] = list_head[i]; list_record[i] != NULL; list_record[i] = list_record[i]->next ){ if ( list_record[i]->data[PICMG_ID_OFFSET] == FRU_AMC_CARRIER_P2P ){ if ( first_data ){ printf("%s\n", STAR_LINE_LIMITER); printf("From Carrier file: %s\n", filename[index_name[i]]); first_data = FALSE; } return_value = ipmi_ek_diplay_carrier_connectivity( list_record[i] ); } else if ( list_record[i]->data[PICMG_ID_OFFSET] == FRU_AMC_CARRIER_INFO ){ /*See AMC.0 specification Table3-3 for mor detail*/ #define COUNT_OFFSET 6 if ( first_data ){ printf("From Carrier file: %s\n", filename[index_name[i]]); first_data = FALSE; } printf(" Number of AMC bays supported by Carrier: %d\n", list_record[i]->data[COUNT_OFFSET] ); } } } /*Destroy the list of record*/ for ( i = 0; i < argc; i++ ){ while ( list_head[i] != NULL ){ ipmi_ek_remove_record_from_list( list_head[i], &list_head[i], &list_last[i] ); } /* display deleted result when we reach the last record */ if ( ( i == (list-1) ) && verbose ) printf("Record list has been removed successfully\n"); } } } else if ( (strcmp(opt, "power") == 0) ){ printf("Print power information\n"); return_value = ipmi_ek_display_power(argc, opt, filename, file_type); } else if ( strcmp(opt, "all") == 0 ){ printf("Print all information\n"); return_value = ipmi_ek_display_power(argc, opt, filename, file_type); } else{ lprintf(LOG_ERR, "Invalid option %s", opt); return_value = ERROR_STATUS; } return return_value; } /************************************************************************** * * Function name: ipmi_ek_display_carrier_connectivity * * Description: Display the topology between a Carrier and all AMC modules by * using carrier p2p connectivity record * * Restriction: Ref: AMC.0 Specification: Table 3-13 and Table 3-14 * * Input: struct ipmi_ek_multi_header* record: a pointer to the carrier p2p * connectivity record. * * Output: None * * Global: None * * Return: return 0 on success and -1 if the record doesn't exist. * ***************************************************************************/ static int ipmi_ek_diplay_carrier_connectivity( struct ipmi_ek_multi_header * record ) { int return_value = ERROR_STATUS; struct fru_picmgext_carrier_p2p_record rsc_desc; struct fru_picmgext_carrier_p2p_descriptor port_desc; if ( record == NULL ){ lprintf(LOG_ERR, "P2P connectivity record is invalid\n"); return_value = ERROR_STATUS; } else{ int offset = START_DATA_OFFSET; if ( verbose > 1 ){ int k = 0; printf("Binary data of Carrier p2p connectivity"\ " record starting from mfg id\n"); for ( k = 0; k < ( record->header.len ); k++ ){ printf("%02x ", record->data[k]); } printf("\n"); } while ( offset <= (record->header.len - START_DATA_OFFSET) ){ rsc_desc.resource_id = record->data[offset++]; rsc_desc.p2p_count = record->data[offset++]; if ( verbose > 0 ){ printf("resource id= %02x port count= %d\n", rsc_desc.resource_id,rsc_desc.p2p_count); } /*check if it is an AMC Module*/ if ( ( (rsc_desc.resource_id & AMC_MODULE) ) == AMC_MODULE ) { /*check if it is an RTM module*/ if (rsc_desc.resource_id == AMC_MODULE) { printf(" %s topology:\n", val2str( RTM_IPMB_L, ipmi_ekanalyzer_IPMBL_addr)); } else{ /*The last four bits of resource ID represent site number * (mask = 0x0f) */ printf(" %s topology:\n", val2str( (rsc_desc.resource_id & 0x0f), ipmi_ekanalyzer_module_type)); } } else{ printf(" On Carrier Device ID %d topology: \n", (rsc_desc.resource_id & 0x0f)); } while ( rsc_desc.p2p_count > 0 ){ memcpy ( &port_desc, &record->data[offset], sizeof ( struct fru_picmgext_carrier_p2p_descriptor ) ); offset += sizeof ( struct fru_picmgext_carrier_p2p_descriptor ); if ( (port_desc.remote_resource_id & AMC_MODULE) == AMC_MODULE ){ printf("\tPort %d =====> %s, Port %d\n", port_desc.local_port, val2str( (port_desc.remote_resource_id & 0x0f), ipmi_ekanalyzer_module_type), port_desc.remote_port ); } else{ printf("\tPort %d =====> On Carrier Device ID %d, Port %d\n", port_desc.local_port,(port_desc.remote_resource_id & 0x0f), port_desc.remote_port ); } rsc_desc.p2p_count--; } } return_value = OK_STATUS; } return return_value; } /************************************************************************** * * Function name: ipmi_ek_display_power * * Description: Display the power management of the Carrier and AMC module by * using current management record. If the display option equal to all, * it will display power and carrier topology together. * * Restriction: Reference: AMC.0 Specification, Table 3-11 * * Input: int argc: number of the argument received * char* opt: option string that will tell what to display * char** filename: strings that contained filename of FRU data binary file * int* file_type: a pointer that contain file type (on carrier file, * a1 file, b1 file...) * * Output: None * * Global: None * * Return: return 0 on success and -1 if the record doesn't exist. * ***************************************************************************/ static int ipmi_ek_display_power(int argc, char * opt, char ** filename, int * file_type) { int num_file=0; int return_value = ERROR_STATUS; int index = 0; /*list des multi record*/ struct ipmi_ek_multi_header * list_head[MAX_ARGC]; struct ipmi_ek_multi_header * list_record[MAX_ARGC]; struct ipmi_ek_multi_header * list_last[MAX_ARGC]; for ( num_file = 0; num_file < argc; num_file++ ){ list_head[num_file] = NULL; list_record[num_file] = NULL; list_last[num_file] = NULL; } for ( num_file = 0; num_file < argc; num_file++ ){ tboolean is_first_data = TRUE; if ( file_type[num_file] == CONFIG_FILE ){ num_file++; } if ( is_first_data ){ printf("%s\n", STAR_LINE_LIMITER); printf("\nFrom %s file '%s'\n", val2str( (uint16_t)file_type[num_file], ipmi_ekanalyzer_module_type), filename[num_file]); is_first_data = FALSE; } return_value = ipmi_ekanalyzer_fru_file2structure( filename[num_file], &list_head[num_file], &list_record[num_file], &list_last[num_file]); if ( list_head[num_file] != NULL ){ for ( list_record[num_file] = list_head[num_file]; list_record[num_file] != NULL; list_record[num_file] = list_record[num_file]->next ){ if ( ( strcmp(opt, "all") == 0 ) && ( file_type[num_file] == ON_CARRIER_FRU_FILE ) ){ if ( list_record[num_file]->data[PICMG_ID_OFFSET] == FRU_AMC_CARRIER_P2P ){ return_value = ipmi_ek_diplay_carrier_connectivity( list_record[num_file] ); } else if ( list_record[num_file]->data[PICMG_ID_OFFSET] == FRU_AMC_CARRIER_INFO ){ /*Ref: See AMC.0 Specification Table 3-3: Carrier Information * Table about offset value */ printf( " Number of AMC bays supported by Carrier: %d\n", list_record[num_file]->data[START_DATA_OFFSET+1] ); } } /*Ref: AMC.0 Specification: Table 3-11 * Carrier Activation and Current Management Record */ if ( list_record[num_file]->data[PICMG_ID_OFFSET] == FRU_AMC_ACTIVATION ){ int index_data = START_DATA_OFFSET; struct fru_picmgext_carrier_activation_record car; struct fru_picmgext_activation_record * cur_desc; memcpy ( &car, &list_record[num_file]->data[index_data], sizeof (struct fru_picmgext_carrier_activation_record) ); index_data += sizeof (struct fru_picmgext_carrier_activation_record); cur_desc = malloc (car.module_activation_record_count * \ sizeof (struct fru_picmgext_activation_record) ); for(index=0; indexdata[index_data], sizeof (struct fru_picmgext_activation_record) ); index_data += sizeof (struct fru_picmgext_activation_record); } /*Display the current*/ ipmi_ek_display_current_descriptor( car, cur_desc, filename[num_file] ); free (cur_desc); } /*Ref: AMC.0 specification, Table 3-10: Module Current Requirement*/ else if ( list_record[num_file]->data[PICMG_ID_OFFSET] == FRU_AMC_CURRENT ){ float power_in_watt = 0; float current_in_amp = 0; printf(" %s power required (Current Draw): ", val2str ( (uint16_t)file_type[num_file], ipmi_ekanalyzer_module_type) ); current_in_amp = (float)(list_record[num_file]->data[START_DATA_OFFSET]*0.1); power_in_watt = current_in_amp * AMC_VOLTAGE; printf("%.2f Watts (%.2f Amps)\n",power_in_watt, current_in_amp); } } return_value = OK_STATUS; /*Destroy the list of record*/ for ( index = 0; index < argc; index++ ){ while ( list_head[index] != NULL ){ ipmi_ek_remove_record_from_list ( list_head[index], &list_head[index],&list_last[index] ); } if ( verbose > 1 ) printf("Record list has been removed successfully\n"); } } } printf("%s\n", STAR_LINE_LIMITER); return return_value; } /************************************************************************** * * Function name: ipmi_ek_display_current_descriptor * * Description: Display the current descriptor under format xx Watts (xx Amps) * * Restriction: None * * Input: struct fru_picmgext_carrier_activation_record car: contain binary data * of carrier activation record * struct fru_picmgext_activation_record * cur_desc: contain current * descriptor * char* filename: strings that contained filename of FRU data binary file * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_current_descriptor( struct fru_picmgext_carrier_activation_record car, struct fru_picmgext_activation_record * cur_desc, char * filename ) { int index = 0; float power_in_watt = 0.0; float current_in_amp = 0.0; for ( index = 0; index < car.module_activation_record_count; index++ ){ /*See AMC.0 specification, Table 3-12 for detail about calculation*/ current_in_amp = (float)(cur_desc[index].max_module_curr * 0.1); power_in_watt = (float) current_in_amp * AMC_VOLTAGE; printf(" Carrier AMC power available on %s:\n", val2str( cur_desc[index].ibmb_addr, ipmi_ekanalyzer_IPMBL_addr ) ); printf("\t- Local IPMB Address \t: %02x\n", cur_desc[index].ibmb_addr); printf("\t- Maximum module Current\t: %.2f Watts (%.2f Amps)\n", power_in_watt, current_in_amp ); } /*Display total power on Carrier*/ current_in_amp = (float)(car.max_internal_curr * 0.1); power_in_watt = (float) current_in_amp * AMC_VOLTAGE; printf(" Carrier AMC total power available for all bays from file '%s':", filename); printf(" %.2f Watts (%.2f Amps)\n", power_in_watt, current_in_amp ); } /************************************************************************** * * Function name: ipmi_ekanalyzer_ekeying_match * * Description: Check for possible Ekeying match between two FRU files * * Restriction: None * * Input: argc: number of the argument received * opt: string that contains display option received from user. * filename: strings that contained filename of FRU data binary file * file_type: a pointer that contain file type (on carrier file, * a1 file, b1 file...) * * Output: None * * Global: None * * Return: return TRUE on success and FALSE if the record doesn't exist. * ***************************************************************************/ static tboolean ipmi_ekanalyzer_ekeying_match( int argc, char * opt, char ** filename, int * file_type ) { tboolean return_value = FALSE; if ( (strcmp(opt, "carrier") == 0 ) || (strcmp(opt, "power") == 0) ){ lprintf(LOG_ERR, " ekanalyzer summary [match/ unmatch/ all]"\ " [xx=frufile]"); return_value = ERROR_STATUS; } else{ int num_file=0; // int index_data = 0; // int first_data = 1; tboolean amc_file = FALSE; /*used to indicate the present of AMC file*/ tboolean oc_file = FALSE; /*used to indicate the present of Carrier file*/ /*Check for possible ekeying match between files*/ for ( num_file=0; num_file < argc; num_file++ ){ if ( ( file_type[num_file] == ON_CARRIER_FRU_FILE ) || ( file_type[num_file] == CONFIG_FILE ) || ( file_type[num_file] == SHELF_MANAGER_FRU_FILE ) ){ amc_file = FALSE; } else { /*there is an amc file*/ amc_file = TRUE; break; } } if ( amc_file == FALSE ){ printf("\nNo AMC FRU file is provided --->" \ " No possible ekeying match!\n"); return_value = ERROR_STATUS; } else{ /*If no carrier file is provided, return error*/ for ( num_file=0; num_file < argc; num_file++ ){ if ( (file_type[num_file] == ON_CARRIER_FRU_FILE ) || ( file_type[num_file] == CONFIG_FILE ) || ( file_type[num_file] == SHELF_MANAGER_FRU_FILE ) ){ oc_file = TRUE; break; } } if ( !oc_file ){ printf("\nNo Carrier FRU file is provided" \ " ---> No possible ekeying match!\n"); return_value = ERROR_STATUS; } else{ /*list des multi record*/ struct ipmi_ek_multi_header * list_head[MAX_ARGC]; struct ipmi_ek_multi_header * list_record[MAX_ARGC]; struct ipmi_ek_multi_header * list_last[MAX_ARGC]; struct ipmi_ek_multi_header * pcarrier_p2p = NULL; int list = 0; int match_pair = 0; // tboolean match_result = FALSE; /*Create an empty list*/ for ( list=0; listnext ){ if ( pcarrier_p2p->data[PICMG_ID_OFFSET] == FRU_AMC_CARRIER_P2P ){ break; } } break; } } /*Determine the match making pair*/ while ( match_pair < argc ){ for ( num_file = (match_pair+1); num_file0){ printf("Start matching process\n"); } return_value = ipmi_ek_matching_process( file_type, match_pair, num_file, list_head, list_last, opt, pcarrier_p2p); } } } match_pair ++; } for( num_file=0; num_file < argc; num_file++ ){ if (list_head[num_file] != NULL ){ ipmi_ek_remove_record_from_list( list_head[num_file], &list_record[num_file], &list_last[num_file]); } if ( ( num_file == argc-1 ) && verbose ) printf("Record list has been removed successfully\n"); } return_value = OK_STATUS; } } } return return_value; } /************************************************************************** * * Function name: ipmi_ek_matching_process * * Description: This function process the OEM check, Physical Connectivity check, * and Link Descriptor comparison to do Ekeying match * * Restriction: None * * Input: file_type: a pointer that contain file type (on carrier file, * a1 file, b1 file...) * index1: position of the first record in the list of the record * index2: position of the second record in the list of the record * ipmi_ek_multi_header ** list_head: pointer to the header of a * linked list that contain FRU multi record * ipmi_ek_multi_header ** list_last: pointer to the tale of a * linked list that contain FRU multi record * opt: string that contain display option such as "match", "unmatch", or * "all". * pphysical: a pointer that contain a carrier p2p connectivity record * to perform physical check * * Output: None * * Global: None * * Return: return OK_STATUS on success and ERROR_STATUS if the record doesn't * exist. * ***************************************************************************/ static int ipmi_ek_matching_process( int * file_type, int index1, int index2, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_last, char * opt, struct ipmi_ek_multi_header * pphysical ) { int result = ERROR_STATUS; struct ipmi_ek_multi_header * record; int num_amc_record1 = 0;/*Number of AMC records in the first module*/ int num_amc_record2 = 0;/*Number of AMC records in the second module*/ /* Comparison between an On-Carrier and an AMC*/ if ( file_type[index2] == ON_CARRIER_FRU_FILE ){ int index_temp = 0; index_temp = index1; index1 = index2; /*index1 indicate on carrier*/ index2 = index_temp; /*index2 indcate an AMC*/ } /*Calculate record size for Carrier file*/ for ( record=list_head[index1]; record != NULL;record = record->next ){ if ( record->data[PICMG_ID_OFFSET] == FRU_AMC_P2P ){ num_amc_record2++; } } /*Calculate record size for amc file*/ for ( record=list_head[index2]; record != NULL;record = record->next){ if ( record->data[PICMG_ID_OFFSET] == FRU_AMC_P2P ){ num_amc_record1++; } } if ( (num_amc_record1 > 0) && (num_amc_record2 > 0) ){ int index_record1 = 0; int index_record2 = 0; /* Multi records of AMC module */ struct ipmi_ek_amc_p2p_connectivity_record * amc_record1 = NULL; /* Multi records of Carrier or an AMC module */ struct ipmi_ek_amc_p2p_connectivity_record * amc_record2 = NULL; amc_record1 = malloc ( num_amc_record1 * \ sizeof(struct ipmi_ek_amc_p2p_connectivity_record)); amc_record2 = malloc ( num_amc_record2 * \ sizeof(struct ipmi_ek_amc_p2p_connectivity_record)); for (record=list_head[index2]; record != NULL;record = record->next){ if ( record->data[PICMG_ID_OFFSET] == FRU_AMC_P2P ){ result = ipmi_ek_create_amc_p2p_record( record, &amc_record1[index_record1] ); if (result != ERROR_STATUS){ struct ipmi_ek_multi_header * current_record = NULL; for ( current_record=list_head[index1]; current_record != NULL ; current_record = current_record->next ){ if ( current_record->data[PICMG_ID_OFFSET] == FRU_AMC_P2P ){ result = ipmi_ek_create_amc_p2p_record( current_record, &amc_record2[index_record2] ); if ( result != ERROR_STATUS ){ if ( result == OK_STATUS ){ /*Compare Link descriptor*/ result = ipmi_ek_compare_link ( pphysical, amc_record1[index_record1], amc_record2[index_record2], opt, file_type[index1], file_type[index2]); } index_record2++; } } /*end of FRU_AMC_P2P */ } /* end of for loop */ index_record1++; } } } free(amc_record1) ; free(amc_record2) ; } else{ printf("No amc record is found!\n"); } return result; } /************************************************************************** * * Function name: ipmi_ek_check_physical_connectivity * * Description: This function check for point to point connectivity between * two modules by comparing each enable port in link descriptor * with local and remote ports of port descriptor in * carrier point-to-point connectivity record according to the * corresponding file type ( a1, b1, b2...). * * Restriction: In order to perform physical check connectivity, it needs to * compare between 2 AMC Modules, so the use of index ( 1 and 2 ) * can facilitate the comparison in this case. * * Input: record1: is an AMC p2p record for an AMC module * record2 is an AMC p2p record for an On-Carrier record or an AMC module * char* opt: option string that will tell if a matching result, unmatched * result or all the results will be displayed. * file_type1: indicates type of the first module * file_type2: indicates type of the second module * * Output: None * * Global: None * * Return: return OK_STATUS if both link are matched, otherwise * return ERROR_STATUS * ***************************************************************************/ static int ipmi_ek_check_physical_connectivity( struct ipmi_ek_amc_p2p_connectivity_record record1, int index1, struct ipmi_ek_amc_p2p_connectivity_record record2, int index2, struct ipmi_ek_multi_header * record, int filetype1, int filetype2, char * option ) { int return_status = OK_STATUS; if ( record == NULL ){ printf("NO Carrier p2p connectivity !\n"); return_status = ERROR_STATUS; } else{ #define INVALID_AMC_SITE_NUMBER -1 int index = START_DATA_OFFSET; int amc_site = INVALID_AMC_SITE_NUMBER; struct fru_picmgext_carrier_p2p_record rsc_desc; struct fru_picmgext_carrier_p2p_descriptor * port_desc = NULL; /* Get the physical connectivity record */ while ( index < record->header.len ) { rsc_desc.resource_id = record->data[index++]; rsc_desc.p2p_count = record->data[index++]; /* carrier p2p record starts with on-carrier device */ if ( (rsc_desc.resource_id == record1.rsc_id) || (rsc_desc.resource_id == record2.rsc_id) ){ if (rsc_desc.p2p_count <= 0){ printf("No p2p count\n"); return_status = ERROR_STATUS; } else{ port_desc = malloc ( rsc_desc.p2p_count * sizeof(struct fru_picmgext_carrier_p2p_descriptor) ); index = ipmi_ek_get_resource_descriptor( rsc_desc.p2p_count, index, port_desc, record ); amc_site = INVALID_AMC_SITE_NUMBER; break; } } else{ /* carrier p2p record starts with AMC module */ if (rsc_desc.resource_id == AMC_MODULE){ if (filetype1 != ON_CARRIER_FRU_FILE){ amc_site = filetype1; } else{ amc_site = filetype2; } } else{ amc_site = rsc_desc.resource_id & 0x0f; } if ( amc_site > 0 ){ if ( (amc_site == filetype1) || (amc_site == filetype2) ){ port_desc = malloc ( rsc_desc.p2p_count * sizeof(struct fru_picmgext_carrier_p2p_descriptor) ); index = ipmi_ek_get_resource_descriptor( rsc_desc.p2p_count, index, port_desc, record ); break; } } else{ return_status = ERROR_STATUS; } } /*If the record doesn't contain the same AMC site number in command * line, go to the next record */ index += ( sizeof(struct fru_picmgext_carrier_p2p_descriptor) * rsc_desc.p2p_count ); } if ( (port_desc != NULL) && (return_status != ERROR_STATUS) ){ int j=0; for ( j = 0; j < rsc_desc.p2p_count; j++ ){ /* Compare only enable channel descriptor */ if ( record1.ch_desc[index1].lane0port != DISABLE_PORT ){ /* matching result from channel descriptor comparison */ tboolean match_lane = FALSE; match_lane = ipmi_ek_compare_channel_descriptor ( record1.ch_desc[index1], record2.ch_desc[index2], port_desc, j, rsc_desc.resource_id ); if ( match_lane ){ if ( filetype1 != ON_CARRIER_FRU_FILE ){ if ( ( (filetype1 == (rsc_desc.resource_id & 0x0f)) && (filetype2 ==(port_desc[j].remote_resource_id &0x0f)) ) || ( (filetype2 == (rsc_desc.resource_id & 0x0f)) && (filetype1 ==(port_desc[j].remote_resource_id &0x0f)) ) ){ if ( ! (strcmp(option, "unmatch") == 0) ){ printf("%s port %d ==> %s port %d\n", val2str((uint16_t)filetype2, ipmi_ekanalyzer_module_type), record1.ch_desc[index1].lane0port, val2str((uint16_t)filetype1, ipmi_ekanalyzer_module_type), record2.ch_desc[index2].lane0port); } return_status = OK_STATUS; break; } else{ if (verbose >= 2){ //was == LOG_DEBUG) printf("No point 2 point connectivity\n"); } return_status = ERROR_STATUS; } } else{ if ( (record2.rsc_id == (rsc_desc.resource_id) ) && (filetype2 == (port_desc[j].remote_resource_id & 0x0f)) ){ if ( ! (strcmp(option, "unmatch") == 0) ){ printf("%s port %d ==> %s port %d\n", val2str((uint16_t)filetype2, ipmi_ekanalyzer_module_type), record1.ch_desc[index1].lane0port, val2str((uint16_t)filetype1, ipmi_ekanalyzer_module_type), record2.ch_desc[index2].lane0port); } return_status = OK_STATUS; break; } else if ( (filetype2 == (rsc_desc.resource_id & 0x0f) ) && (record2.rsc_id == (port_desc[j].remote_resource_id)) ){ if ( ! (strcmp(option, "unmatch") == 0) ){ printf("%s port %d ==> %s %x port %d\n", val2str((uint16_t)filetype2, ipmi_ekanalyzer_module_type), record1.ch_desc[index1].lane0port, val2str((uint16_t)filetype1, ipmi_ekanalyzer_module_type), record2.rsc_id,record2.ch_desc[index2].lane0port); } return_status = OK_STATUS; break; } else{ if (verbose >= 2){ //was == LOG_DEBUG printf("No point 2 point connectivity\n"); } return_status = ERROR_STATUS; } } } else{ if (verbose >= 2){ //was == LOG_DEBUG printf("No point 2 point connectivity\n"); } return_status = ERROR_STATUS; } } else{ /*If the link is disable, the result is always true*/ return_status = OK_STATUS; } } } else{ if (verbose >= 2) { //was == LOG_WARN printf("Invalid Carrier p2p connectivity record\n"); } return_status = ERROR_STATUS; } if (port_desc != NULL){ free (port_desc); } } return return_status; } /************************************************************************** * * Function name: ipmi_ek_compare_link * * Description: This function compares link grouping id of each * amc p2p connectiviy record * * Restriction: None * * Input: record1: is an AMC p2p record for an AMC module * record2 is an AMC p2p record for an On-Carrier record or an AMC module * char* opt: option string that will tell if a matching result, unmatched * result or all the results will be displayed. * file_type1: indicates type of the first module * file_type2: indicates type of the second module * * Output: None * * Global: None * * Return: return 0 if both link are matched, otherwise return -1 * ***************************************************************************/ static int ipmi_ek_compare_link( struct ipmi_ek_multi_header * physic_record, struct ipmi_ek_amc_p2p_connectivity_record record1, struct ipmi_ek_amc_p2p_connectivity_record record2, char * opt, int file_type1, int file_type2 ) { int result = ERROR_STATUS; int index1 = 0; /*index for AMC module*/ int index2 = 0; /*index for On-carrier type*/ record1.matching_result = malloc ( record1.link_desc_count * sizeof(int) ); record2.matching_result = malloc ( record2.link_desc_count * sizeof(int) ); /*Initialize all the matching_result to false*/ for( index2 = 0; index2 < record2.link_desc_count; index2++ ){ record2.matching_result[index2] = FALSE; } for( index1 = 0; index1 < record1.link_desc_count; index1++ ){ for( index2 = 0; index2 < record2.link_desc_count; index2++ ){ if( record1.link_desc[index1].group_id == 0 ){ if( record2.link_desc[index2].group_id == 0 ){ result = ipmi_ek_compare_link_descriptor( record1, index1, record2, index2 ); if ( result == OK_STATUS ){ /*Calculate the index for Channel descriptor in function of * link designator channel ID */ /*first channel_id in the AMC Link descriptor of record1*/ static int flag_first_link1; int index_ch_desc1; /*index of channel descriptor */ /*first channel_id in the AMC Link descriptor of record2*/ static int flag_first_link2; int index_ch_desc2; /*index of channel descriptor*/ if (index1==0){ /*this indicate the first link is encounter*/ flag_first_link1 = record1.link_desc[index1].channel_id; } index_ch_desc1 = record1.link_desc[index1].channel_id - flag_first_link1; if (index2==0){ flag_first_link2 = record2.link_desc[index2].channel_id; } index_ch_desc2 = record2.link_desc[index2].channel_id - flag_first_link2; /*Check for physical connectivity for each link*/ result = ipmi_ek_check_physical_connectivity ( record1, index_ch_desc1, record2, index_ch_desc2, physic_record, file_type1, file_type2, opt ); if ( result == OK_STATUS ){ /*Display the result if option = match or all*/ if ( (strcmp( opt, "match" ) == 0) || (strcmp( opt, "all" ) == 0) || (strcmp( opt, "default" ) == 0) ){ tboolean isOEMtype = FALSE; printf(" Matching Result\n"); isOEMtype = ipmi_ek_display_link_descriptor( file_type1, record2.rsc_id, "From", record2.link_desc[index2]); if (isOEMtype){ ipmi_ek_display_oem_guid (record2); } isOEMtype = ipmi_ek_display_link_descriptor( file_type2, record1.rsc_id, "To", record1.link_desc[index1] ); if (isOEMtype){ ipmi_ek_display_oem_guid (record1); } printf(" %s\n", STAR_LINE_LIMITER); } record2.matching_result[index2] = TRUE; record1.matching_result[index1] = TRUE; /*quit the fist loop since the match is found*/ index2 = record2.link_desc_count; } } } } else { /*Link Grouping ID is non zero, Compare all link descriptor * that has non-zero link grouping id together */ if (record2.link_desc[index2].group_id != 0 ){ result = ipmi_ek_compare_link_descriptor( record1, index1, record2, index2 ); if ( result == OK_STATUS ){ /*Calculate the index for Channel descriptor in function of * link designator channel ID */ /*first channel_id in the AMC Link descriptor of record1*/ static int flag_first_link1; int index_ch_desc1; /*index of channel descriptor */ /*first channel_id in the AMC Link descriptor of record2*/ static int flag_first_link2; int index_ch_desc2; /*index of channel descriptor*/ if (index1==0){ /*this indicate the first link is encounter*/ flag_first_link1 = record1.link_desc[index1].channel_id; } index_ch_desc1 = record1.link_desc[index1].channel_id - flag_first_link1; if (index2==0){ flag_first_link2 = record2.link_desc[index2].channel_id; } index_ch_desc2 = record2.link_desc[index2].channel_id - flag_first_link2; /*Check for physical connectivity for each link*/ result = ipmi_ek_check_physical_connectivity ( record1, index_ch_desc1, record2, index_ch_desc2, physic_record, file_type1, file_type2, opt ); if ( result == OK_STATUS ){ if ( (strcmp( opt, "match" ) == 0) || (strcmp( opt, "all" ) == 0) || (strcmp( opt, "default" ) == 0) ){ tboolean isOEMtype = FALSE; printf(" Matching Result\n"); isOEMtype = ipmi_ek_display_link_descriptor( file_type1, record2.rsc_id, "From", record2.link_desc[index2] ); if ( isOEMtype ){ ipmi_ek_display_oem_guid (record2); } isOEMtype = ipmi_ek_display_link_descriptor( file_type2, record1.rsc_id, "To", record1.link_desc[index1] ); if (isOEMtype){ ipmi_ek_display_oem_guid (record1); } printf(" %s\n", STAR_LINE_LIMITER); } record2.matching_result[index2] = TRUE; record1.matching_result[index1] = TRUE; /*leave the fist loop since the match is found*/ index2 = record2.link_desc_count; } } } } } } if ( (strcmp(opt, "unmatch") == 0) || (strcmp(opt, "all") == 0) ){ int isOEMtype = FALSE; printf(" Unmatching result\n"); for (index1 = 0; index1 < record1.link_desc_count; index1++){ isOEMtype = ipmi_ek_display_link_descriptor( file_type2, record1.rsc_id, "", record1.link_desc[index1] ); if ( isOEMtype ){ ipmi_ek_display_oem_guid (record1); } printf(" %s\n", STAR_LINE_LIMITER); } for ( index2 = 0; index2 < record2.link_desc_count; index2++){ if ( !record2.matching_result[index2] ){ isOEMtype = ipmi_ek_display_link_descriptor( file_type1, record2.rsc_id, "", record2.link_desc[index2] ); if ( isOEMtype ){ ipmi_ek_display_oem_guid (record2); } printf(" %s\n", STAR_LINE_LIMITER); } } } free (record1.matching_result); free (record2.matching_result); return result; } /************************************************************************** * * Function name: ipmi_ek_compare_channel_descriptor * * Description: This function compares 2 channel descriptors of 2 AMC * point-to-point connectivity records with port descriptor of * carrier point-to-point connectivity record. The comparison is * made between each enable port only. * * Restriction: Reference: AMC.0 specification: * - Table 3-14 for port descriptor * - Table 3-17 for channel descriptor * * Input: ch_desc1: first channel descriptor * ch_desc2: second channel descriptor * port_desc: a pointer that contain a list of port descriptor * index_port: index of the port descriptor * rsc_id: resource id that represents as local resource id in the * resource descriptor table. * * Output: None * * Global: None * * Return: return TRUE if both channel descriptor are matched, * or FALSE otherwise * ***************************************************************************/ static tboolean ipmi_ek_compare_channel_descriptor( struct fru_picmgext_amc_channel_desc_record ch_desc1, struct fru_picmgext_amc_channel_desc_record ch_desc2, struct fru_picmgext_carrier_p2p_descriptor * port_desc, int index_port, unsigned char rsc_id ) { tboolean match_lane = FALSE; /* carrier p2p record start with AMC_MODULE as local port */ if ( (rsc_id & AMC_MODULE) == AMC_MODULE ){ if ( (ch_desc1.lane0port == port_desc[index_port].local_port) && (ch_desc2.lane0port == port_desc[index_port].remote_port) ){ /*check if the port is enable*/ if (ch_desc1.lane1port != DISABLE_PORT){ index_port ++; if ( (ch_desc1.lane1port == port_desc[index_port].local_port) && (ch_desc2.lane1port == port_desc[index_port].remote_port) ){ if (ch_desc1.lane2port != DISABLE_PORT){ index_port++; if ( (ch_desc1.lane2port == port_desc[index_port].local_port) && (ch_desc2.lane2port == port_desc[index_port].remote_port) ){ if (ch_desc1.lane3port != DISABLE_PORT){ index_port++; if ( (ch_desc1.lane3port == port_desc[index_port].local_port) && (ch_desc2.lane3port == port_desc[index_port].remote_port) ){ match_lane = TRUE; } } else{ match_lane = TRUE; } } /* end of if lane2port */ } else{ match_lane = TRUE; } } /* end of if lane1port */ } else{ /*if the port is disable, the compare result is always true*/ match_lane = TRUE; } }/* end of if lane0port */ } /* carrier p2p record start with Carrier as local port */ else{ if ( (ch_desc1.lane0port == port_desc[index_port].remote_port) && (ch_desc2.lane0port == port_desc[index_port].local_port) ){ if (ch_desc1.lane1port != DISABLE_PORT){ index_port ++; if ( (ch_desc1.lane1port == port_desc[index_port].remote_port) && (ch_desc2.lane1port == port_desc[index_port].local_port) ){ if (ch_desc1.lane2port != DISABLE_PORT){ index_port++; if ( (ch_desc1.lane2port == port_desc[index_port].remote_port) && (ch_desc2.lane2port == port_desc[index_port].local_port) ){ if (ch_desc1.lane3port != DISABLE_PORT){ index_port++; if ( (ch_desc1.lane3port == port_desc[index_port].remote_port) && (ch_desc2.lane3port == port_desc[index_port].local_port) ){ match_lane = TRUE; } } else{ match_lane = TRUE; } } /* end of if lane2port */ } else{ match_lane = TRUE; } } /* end of if lane1port */ } else{ match_lane = TRUE; } } /* end of if lane0port */ } return match_lane; } /************************************************************************** * * Function name: ipmi_ek_compare_link_descriptor * * Description: This function compares 2 link descriptors of 2 * amc p2p connectiviy record * * Restriction: None * * Input: record1: AMC p2p connectivity record of the 1rst AMC or Carrier Module * index1: index of AMC link descriptor in 1rst record * record2: AMC p2p connectivity record of the 2nd AMC or Carrier Module * index1: index of AMC link descriptor in 2nd record * * Output: None * * Global: None * * Return: return OK_STATUS if both link are matched, * otherwise return ERROR_STATUS * ***************************************************************************/ static int ipmi_ek_compare_link_descriptor( struct ipmi_ek_amc_p2p_connectivity_record record1, int index1, struct ipmi_ek_amc_p2p_connectivity_record record2, int index2 ) { int result = ERROR_STATUS; if (record1.link_desc[index1].type == record2.link_desc[index2].type){ /*if it is an OEM type, we compare the OEM GUID*/ if ( (record1.link_desc[index1].type >= LOWER_OEM_TYPE) && (record1.link_desc[index1].type <= UPPER_OEM_TYPE) ){ if ( (record1.guid_count == 0) && (record2.guid_count == 0) ){ /*there is no GUID for comparison, so the result is always OK*/ result = OK_STATUS; } else{ int i=0; int j=0; for( i=0; i= LOWER_OEM_TYPE) && (link_desc.type <= UPPER_OEM_TYPE) ){ isOEMtype = TRUE; } return isOEMtype; } /************************************************************************** * * Function name: ipmi_ek_display_oem_guid * * Description: Display the oem guid of an AMC p2p connectivity record * * Restriction: None * * Input: amc_record: AMC p2p connectivity record * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_oem_guid( struct ipmi_ek_amc_p2p_connectivity_record amc_record ) { int index_oem = 0; int index = 0; if ( amc_record.guid_count == 0 ){ printf("\tThere is no OEM GUID for this module\n"); } for (index_oem = 0; index_oem < amc_record.guid_count; index_oem++){ printf(" - GUID: "); for(index = 0; index < SIZE_OF_GUID; index++){ printf("%02x", amc_record.oem_guid[index_oem].guid[index]); /*For a better look: putting a "-" after displaying four bytes of GUID*/ if (!(index % 4)){ printf("-"); } } printf("\n"); } } /************************************************************************** * * Function name: ipmi_ek_create_amc_p2p_record * * Description: this function create an AMC point 2 point connectivity record * that contain link descriptor, channel descriptor, oem guid * * Restriction: Reference: AMC.0 Specification Table 3-16 * * Input: record: a pointer to FRU multi record * * Output: amc_record: a pointer to the created AMC p2p record * * Global: None * * Return: Return OK_STATUS on success, or ERROR_STATUS if no record has been * created. * ***************************************************************************/ static int ipmi_ek_create_amc_p2p_record( struct ipmi_ek_multi_header * record, struct ipmi_ek_amc_p2p_connectivity_record * amc_record ) { int return_status = OK_STATUS; int index_data = START_DATA_OFFSET; amc_record->guid_count = record->data[index_data++]; if ( amc_record->guid_count > 0){ int index_oem = 0; amc_record->oem_guid = malloc (amc_record->guid_count * \ sizeof(struct fru_picmgext_guid) ); for (index_oem = 0; index_oem < amc_record->guid_count; index_oem++){ memcpy ( &amc_record->oem_guid[index_oem].guid, &record->data[index_data], SIZE_OF_GUID ); index_data += (int)SIZE_OF_GUID; } amc_record->rsc_id = record->data[index_data++]; amc_record->ch_count = record->data[index_data++]; /*Calculate link descriptor count*/ amc_record->link_desc_count = ( (record->header.len) - 8 - (SIZE_OF_GUID*amc_record->guid_count) - ( sizeof(struct fru_picmgext_amc_channel_desc_record)* amc_record->ch_count ) )/5 ; } else{ amc_record->rsc_id = record->data[index_data++]; amc_record->ch_count = record->data[index_data++]; /*Calculate link descriptor count see spec AMC.0 for detail*/ amc_record->link_desc_count = ( (record->header.len) - 8 - ( sizeof(struct fru_picmgext_amc_channel_desc_record)* amc_record->ch_count ) ) / 5; } if (amc_record->ch_count > 0){ int ch_index = 0; amc_record->ch_desc = malloc ( (amc_record->ch_count) * \ sizeof(struct fru_picmgext_amc_channel_desc_record)); for (ch_index = 0; ch_index < amc_record->ch_count; ch_index++){ memcpy(&amc_record->ch_desc[ch_index], &record->data[index_data], sizeof(struct fru_picmgext_amc_channel_desc_record) ); index_data += sizeof(struct fru_picmgext_amc_channel_desc_record) ; } } if (amc_record->link_desc_count > 0){ int i=0; amc_record->link_desc = malloc ( amc_record->link_desc_count * sizeof(struct fru_picmgext_amc_link_desc_record) ); for (i = 0; i< amc_record->link_desc_count; i++ ){ memcpy (&amc_record->link_desc[i], &record->data[index_data], sizeof(struct fru_picmgext_amc_link_desc_record) ); index_data += sizeof (struct fru_picmgext_amc_link_desc_record); } } else{ return_status = ERROR_STATUS; } return return_status; } /************************************************************************** * * Function name: ipmi_ek_get_resource_descriptor * * Description: this function create the resource descriptor of Carrier p2p * connectivity record. * * Restriction: None * * Input: port_count: number of port count * index: index to the position of data start offset * record: a pointer to FRU multi record * * Output: port_desc: a pointer to the created resource descriptor * * Global: None * * Return: Return index that indicates the current position of data in record. * ***************************************************************************/ static int ipmi_ek_get_resource_descriptor( int port_count, int index, struct fru_picmgext_carrier_p2p_descriptor * port_desc, struct ipmi_ek_multi_header * record ) { int num_port = 0; while ( num_port < port_count ){ memcpy ( &port_desc[num_port], &record->data[index], sizeof (struct fru_picmgext_carrier_p2p_descriptor) ); index += sizeof (struct fru_picmgext_carrier_p2p_descriptor); num_port++; } return index; } /************************************************************************** * * Function name: ipmi_ek_display_fru_header * * Description: this function display FRU header offset from a FRU binary file * * Restriction: Reference: IPMI Platform Management FRU Information Storage * Definition V1.0, Section 8 * * Input: filename: name of FRU binary file * * Output: None * * Global: None * * Return: Return OK_STATUS on sucess, ERROR_STATUS on error * ***************************************************************************/ static int ipmi_ek_display_fru_header( char * filename ) { FILE * input_file; /* this structure is declared in ipmi_fru.h */ struct fru_header header; int return_status = ERROR_STATUS; input_file = fopen ( filename, "r"); if ( input_file == NULL ){ lprintf(LOG_ERR, "file: '%s' is not found", filename); return_status = ERROR_STATUS; } else{ if ( !feof (input_file) ){ fread ( &header, sizeof (struct fru_header), 1, input_file ); printf("%s\n", EQUAL_LINE_LIMITER); printf("FRU Header Info\n"); printf("%s\n", EQUAL_LINE_LIMITER); printf("Format Version :0x%02x %s\n", (header.version & 0x0f), ((header.version & 0x0f)==1) ? "" : "{unsupported}"); printf("Internal Use Offset :0x%02x\n", header.offset.internal); printf("Chassis Info Offset :0x%02x\n", header.offset.chassis); printf("Board Info Offset :0x%02x\n", header.offset.board); printf("Product Info Offset :0x%02x\n", header.offset.product); printf("MultiRecord Offset :0x%02x\n", header.offset.multi); printf("Common header Checksum :0x%02x\n", header.checksum); return_status = OK_STATUS; } else{ lprintf(LOG_ERR, "Invalid FRU header!"); return_status = ERROR_STATUS; } fclose( input_file ); } return return_status; } /************************************************************************** * * Function name: ipmi_ek_display_fru_header_detail * * Description: this function display detail FRU header information * from a FRU binary file. * * Restriction: Reference: IPMI Platform Management FRU Information Storage * Definition V1.0, Section 8 * * Input: filename: name of FRU binary file * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_fru_header_detail( char * filename ) { FILE * input_file; struct fru_header header; input_file = fopen ( filename, "r"); if ( input_file == NULL ){ lprintf(LOG_ERR, "file: '%s' is not found", filename); } else{ /* the offset in each fru is in multiple of 8 bytes * See IPMI Platform Management FRU Information Storage Definition * for detail */ #define FACTOR_OFFSET 8 if ( !feof (input_file) ){ fread ( &header, sizeof( struct fru_header ), 1, input_file ); } else{ lprintf(LOG_ERR, "Invalid FRU header!"); } /*** Display FRU Internal Use Info ***/ if ( !feof (input_file) ){ unsigned char format_version; unsigned long len; printf("%s\n", EQUAL_LINE_LIMITER); printf("FRU Internal Use Info\n"); printf("%s\n", EQUAL_LINE_LIMITER); fread ( &format_version, 1, 1, input_file ); printf("Format Version: %d\n", (format_version & 0x0f) ); if ( header.offset.chassis > 0 ){ len = (header.offset.chassis * FACTOR_OFFSET) - (header.offset.internal * FACTOR_OFFSET); } else{ len = (header.offset.board * FACTOR_OFFSET) - (header.offset.internal * FACTOR_OFFSET); } printf("Length: %d\n", len); printf("Data dump:\n"); while ( (len > 0) && ( !feof (input_file) ) ) { unsigned char data; fread ( &data, 1, 1, input_file ); printf("0x%02x ", data); len --; } printf("\n"); } /*** Chassis Info Area ***/ if (header.offset.chassis != 0){ long offset = 0; offset = header.offset.chassis * FACTOR_OFFSET; ipmi_ek_display_chassis_info_area (input_file, offset); } /*** Display FRU Board Info Area ***/ if (header.offset.board != 0){ fseek_( input_file, (header.offset.board * FACTOR_OFFSET), SEEK_SET); if ( !feof(input_file) ){ unsigned char data; unsigned int board_length; size_t file_offset = ftell (input_file); printf("%s\n", EQUAL_LINE_LIMITER); printf("FRU Board Info Area\n"); printf("%s\n", EQUAL_LINE_LIMITER); fread ( &data, 1, 1, input_file ); /* Format version */ printf("Format Version: %d\n", (data & 0x0f)); if ( !feof(input_file) ){ fread ( &data, 1, 1, input_file ); /* Board Area Length */ board_length = (data * FACTOR_OFFSET); printf("Area Length: %d\n", board_length); /* Decrease the length of board area by 1 byte of format version * and 1 byte for area length itself. the rest of this length will * be used to check for additional custom mfg. byte */ board_length -= 2; } if ( !feof(input_file) ){ unsigned char lan_code; fread ( &lan_code, 1, 1, input_file ); /* Language Code */ printf("Language Code: %d\n", lan_code ); board_length --; } /* Board Mfg Date */ if ( !feof(input_file) ){ #define SIZE_MFG_DATE 3 time_t tval; unsigned char mfg_date[SIZE_MFG_DATE]; fread ( mfg_date, SIZE_MFG_DATE, 1, input_file ); tval=((mfg_date[2] << 16) + (mfg_date[1] << 8) + (mfg_date[0])); tval = tval * 60; tval = (time_t)(tval + secs_from_1970_1996); printf("Board Mfg Date: %ld, %s", tval, asctime(localtime(&tval))); board_length -= SIZE_MFG_DATE; /* Board Mfg */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Board Manufacture Data", &board_length); fseek_(input_file, file_offset, SEEK_SET); /* Board Product */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Board Product Name", &board_length); fseek_(input_file, file_offset, SEEK_SET); /* Board Serial */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Board Serial Number", &board_length); fseek_(input_file, file_offset, SEEK_SET); /* Board Part */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Board Part Number", &board_length); fseek_(input_file, file_offset, SEEK_SET); /* FRU file ID */ file_offset = ipmi_ek_display_board_info_area ( input_file, "FRU File ID", &board_length); fseek_(input_file, file_offset, SEEK_SET); /* Additional Custom Mfg. */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Custom", &board_length); } } } /*** Product Info Area ***/ if ( header.offset.product ){ if ( !feof(input_file) ){ long offset = 0; offset = header.offset.product * FACTOR_OFFSET; ipmi_ek_display_product_info_area (input_file, offset); } } fclose( input_file ); } } /************************************************************************** * * Function name: ipmi_ek_display_chassis_info_area * * Description: this function displays detail format of product info area record * into humain readable text format * * Restriction: Reference: IPMI Platform Management FRU Information Storage * Definition V1.0, Section 10 * * Input: input_file: pointer to file stream * offset: start offset of chassis info area * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_chassis_info_area( FILE * input_file, long offset ) { if ( input_file != NULL ){ printf("%s\n", EQUAL_LINE_LIMITER); printf("Chassis Info Area\n"); printf("%s\n", EQUAL_LINE_LIMITER); fseek_(input_file, offset, SEEK_SET); if ( !feof(input_file) ){ unsigned char data = 0; unsigned int len = 0; fread (&data, 1, 1, input_file); printf("Format Version Number: %d\n", (data & 0x0f) ); if ( !feof(input_file) ){ fread (&len, 1, 1, input_file); /* len is in factor of 8 bytes */ len = len * 8; printf("Area Length: %d\n", len); len -= 2; } if ( !feof(input_file) ){ unsigned char ch_type = 0; size_t file_offset = ftell (input_file); /* Chassis Type*/ fread (&ch_type, 1, 1, input_file); printf("Chassis Type: %d\n", ch_type); len --; /* Chassis Part Number*/ file_offset = ipmi_ek_display_board_info_area ( input_file, "Chassis Part Number", &len); fseek_(input_file, file_offset, SEEK_SET); /* Chassis Serial */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Chassis Serial Number", &len); fseek_(input_file, file_offset, SEEK_SET); /* Custom product info area */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Custom", &len); } } } else{ lprintf(LOG_ERR, "Invalid Chassis Info Area!"); } } /************************************************************************** * * Function name: ipmi_ek_display_board_info_area * * Description: this function displays board info area depending on board type * that pass in argument. Board type can be: * Manufacturer, Serial, Product or Part... * * Restriction: IPMI Platform Management FRU Information Storage * Definition V1.0, Section 11 * * Input: input_file: pointer to file stream * board_type: a string that contain board type * board_length: length of info area * * Output: None * * Global: None * * Return: the current position of input_file * ***************************************************************************/ static size_t ipmi_ek_display_board_info_area( FILE * input_file, char * board_type, unsigned int * board_length ) { size_t file_offset = ftell (input_file); unsigned char len = 0; /* Board length*/ if ( !feof(input_file) ){ fread ( &len, 1, 1, input_file ); (*board_length)--; } /* Board Data */ if ( !feof(input_file) ){ unsigned int size_board = 0; /*Bit 5:0 of Board Mfg type represent legnth*/ size_board = (len & 0x3f); if (size_board > 0){ if ( strncmp( board_type, "Custom", 6 ) == 0 ){ #define NO_MORE_INFO_FIELD 0xc1 while ( !feof(input_file) && (*board_length > 0) ){ if (len != NO_MORE_INFO_FIELD){ printf("Additional Custom Mfg. length: 0x%02x\n", len); if ( (size_board > 0) && (size_board < (*board_length)) ){ unsigned char * additional_data = NULL; int i=0; additional_data = malloc (size_board); if (additional_data != NULL){ fread ( additional_data, size_board, 1, input_file ); printf("Additional Custom Mfg. Data: %02x", additional_data[0]); for ( i =1; i<(int)size_board; i++){ printf("-%02x", additional_data[i]); } printf("\n"); free (additional_data); (*board_length) -= size_board; } } else{ printf("No Additional Custom Mfg. %d\n", *board_length); board_length = 0; } } else{ unsigned char padding; /*take the rest of data in the area minus 1 byte of checksum*/ printf("Additional Custom Mfg. length: 0x%02x\n", len); padding = (*board_length) - 1; /*we reach the end of the record, so its length is set to 0*/ board_length = 0; if ( ( padding > 0 ) && ( !feof(input_file) ) ){ printf("Unused space: %d (bytes)\n", padding); fseek_(input_file, padding, SEEK_CUR); } if ( !feof(input_file) ){ unsigned char checksum = 0; fread ( &checksum, 1, 1, input_file ); printf("Checksum: 0x%02x\n", checksum); } } } } else{ unsigned char * data; unsigned int i=0; #define TYPE_CODE 0xc0 /*Language code*/ data = malloc (size_board); fread ( data, size_board, 1, input_file ); printf("%s type: 0x%02x\n", board_type, len); printf("%s: ", board_type); for ( i = 0; i < size_board; i++ ){ if ( (len & TYPE_CODE) == TYPE_CODE ){ printf("%c", data[i]); } /*other than language code (binary, BCD, ASCII 6 bit...) is not * supported */ else{ printf("%02x", data[i]); } } printf("\n"); free (data); (*board_length) -= size_board; file_offset = ftell (input_file); } } else{ printf("%s: None\n", board_type); file_offset = ftell (input_file); } } return file_offset; } /************************************************************************** * * Function name: ipmi_ek_display_product_info_area * * Description: this function displays detail format of product info area record * into humain readable text format * * Restriction: Reference: IPMI Platform Management FRU Information Storage * Definition V1.0, Section 12 * * Input: input_file: pointer to file stream * offset: start offset of product info area * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_product_info_area( FILE * input_file, long offset ) { if ( input_file != NULL ){ printf("%s\n", EQUAL_LINE_LIMITER); printf("Product Info Area\n"); printf("%s\n", EQUAL_LINE_LIMITER); fseek_(input_file, offset, SEEK_SET); if ( !feof(input_file) ){ unsigned char data = 0; unsigned int len = 0; fread (&data, 1, 1, input_file); printf("Format Version Number: %d\n", (data & 0x0f) ); if ( !feof(input_file) ){ fread (&len, 1, 1, input_file); /* length is in factor of 8 bytes */ len = len * 8; printf("Area Length: %d\n", len); len -= 2; /* -1 byte of format version and -1 byte itself */ } if ( !feof(input_file) ){ size_t file_offset = ftell (input_file); fread (&data, 1, 1, input_file); printf("Language Code: %d\n", data); len --; /* Product Mfg */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Product Manufacture Data", &len); fseek_(input_file, file_offset, SEEK_SET); /* Product Name */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Product Name", &len); fseek_(input_file, file_offset, SEEK_SET); /* Product Part */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Product Part/Model Number", &len); fseek_(input_file, file_offset, SEEK_SET); /* Product Version */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Product Version", &len); fseek_(input_file, file_offset, SEEK_SET); /* Product Serial */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Product Serial Number", &len); fseek_(input_file, file_offset, SEEK_SET); /* Product Asset Tag */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Asset Tag", &len); fseek_(input_file, file_offset, SEEK_SET); /* FRU file ID */ file_offset = ipmi_ek_display_board_info_area ( input_file, "FRU File ID", &len); fseek_(input_file, file_offset, SEEK_SET); /* Custom product info area */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Custom", &len); } } } else{ lprintf(LOG_ERR, "Invalid Product Info Area!"); } } /************************************************************************** * * Function name: ipmi_ek_display_record * * Description: this function displays FRU multi record information. * * Restriction: None * * Input: record: a pointer to current record * list_head: a pointer to header of the list * list_last: a pointer to tale of the list * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_record( struct ipmi_ek_multi_header * record, struct ipmi_ek_multi_header * list_head, struct ipmi_ek_multi_header * list_last ) { if ( list_head == NULL ){ printf("***empty list***\n"); } else{ printf("%s\n", EQUAL_LINE_LIMITER); printf("FRU Multi Info area\n"); printf("%s\n", EQUAL_LINE_LIMITER); for ( record = list_head; record != NULL; record = record->next ){ printf("Record Type ID: 0x%02x\n", record->header.type); printf("Record Format version: 0x%02x\n", record->header.format); if (record->header.len > PICMG_ID_OFFSET){ /* In picmg3.0 specification, picmg record id lower than 4 or * greater than 0x2d is not supported */ #define PICMG_ID_LOWER_LIMIT 0x04 #define PICMG_ID_UPPER_LIMIT 0x2d unsigned char picmg_id; picmg_id = record->data[PICMG_ID_OFFSET]; printf("Manufacturer ID: %02x%02x%02x h\n", record->data[2], record->data[1], record->data[0] ); if( ( picmg_id < PICMG_ID_LOWER_LIMIT ) || ( picmg_id > PICMG_ID_UPPER_LIMIT ) ){ printf("Picmg record ID: Unsupported {0x%02x}\n", picmg_id ); } else{ printf("Picmg record ID: %s {0x%02x}\n", val2str(picmg_id, ipmi_ekanalyzer_picmg_record_id), picmg_id ); } switch (picmg_id){ case FRU_PICMG_BACKPLANE_P2P: /*0x04*/ ipmi_ek_display_backplane_p2p_record (record); break; case FRU_PICMG_ADDRESS_TABLE: /*0x10*/ ipmi_ek_display_address_table_record (record); break; case FRU_PICMG_SHELF_POWER_DIST: /*0x11*/ ipmi_ek_display_shelf_power_distribution_record (record); break; case FRU_PICMG_SHELF_ACTIVATION: /*/0x12*/ ipmi_ek_display_shelf_activation_record (record); break; case FRU_PICMG_SHMC_IP_CONN: /*0x13*/ ipmi_ek_display_shelf_ip_connection_record (record); break; case FRU_PICMG_BOARD_P2P: /*0x14*/ ipmi_ek_display_board_p2p_record (record); break; case FRU_RADIAL_IPMB0_LINK_MAPPING: /*0x15*/ ipmi_ek_display_radial_ipmb0_record (record); break; case FRU_AMC_CURRENT: /*0x16*/ ipmi_ek_display_amc_current_record (record); break; case FRU_AMC_ACTIVATION: /*0x17*/ ipmi_ek_display_amc_activation_record (record); break; case FRU_AMC_CARRIER_P2P: /*0x18*/ ipmi_ek_diplay_carrier_connectivity (record); break; case FRU_AMC_P2P: /*0x19*/ ipmi_ek_display_amc_p2p_record (record); break; case FRU_AMC_CARRIER_INFO: /*0x1a*/ ipmi_ek_display_amc_carrier_info_record (record); break; case FRU_PICMG_CLK_CARRIER_P2P: /*0x2c*/ ipmi_ek_display_clock_carrier_p2p_record (record); break; case FRU_PICMG_CLK_CONFIG: /*0x2d*/ ipmi_ek_display_clock_config_record (record); break; default: if (verbose > 0){ int i; printf("%02x %02x %02x %02x %02x ", record->header.type, record->header.format, record->header.len, record->header.record_checksum, record->header.header_checksum ); for ( i = 0; i < record->header.len; i++ ){ printf("%02x ", record->data[i]); } printf("\n"); } break; } printf("%s\n", STAR_LINE_LIMITER); } } } } /************************************************************************** * * Function name: ipmi_ek_display_backplane_p2p_record * * Description: this function displays backplane p2p record. * * Restriction: Reference: PICMG 3.0 Specification Table 3-40 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_backplane_p2p_record( struct ipmi_ek_multi_header * record ) { uint8_t index; int offset = START_DATA_OFFSET; struct fru_picmgext_slot_desc * slot_d = (struct fru_picmgext_slot_desc*) &record->data[offset]; offset += sizeof(struct fru_picmgext_slot_desc); while ( offset <= record->header.len ) { printf(" Channel Type: "); switch ( slot_d -> chan_type ) { case 0x00: case 0x07: printf("PICMG 2.9\n"); break; case 0x08: printf("Single Port Fabric IF\n"); break; case 0x09: printf("Double Port Fabric IF\n"); break; case 0x0a: printf("Full Channel Fabric IF\n"); break; case 0x0b: printf("Base IF\n"); break; case 0x0c: printf("Update Channel IF\n"); break; default: printf("Unknown IF\n"); break; } printf(" Slot Address: %02x\n", slot_d -> slot_addr); printf(" Channel Count: %i\n", slot_d -> chn_count); for ( index = 0; index < (slot_d -> chn_count); index++ ) { struct fru_picmgext_chn_desc * d = (struct fru_picmgext_chn_desc *) &record->data[offset]; if ( verbose ){ printf( "\t" "Chn: %02x --> " "Chn: %02x in " "Slot: %02x\n", d->local_chn, d->remote_chn, d->remote_slot ); } offset += sizeof(struct fru_picmgext_chn_desc); } slot_d = (struct fru_picmgext_slot_desc*) &record->data[offset]; offset += sizeof(struct fru_picmgext_slot_desc); } } /************************************************************************** * * Function name: ipmi_ek_display_address_table_record * * Description: this function displays address table record. * * Restriction: Reference: PICMG 3.0 Specification Table 3-6 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_address_table_record( struct ipmi_ek_multi_header * record ) { unsigned char entries = 0; unsigned char i; int offset = START_DATA_OFFSET; #define SIZE_SHELF_ADDRESS_BYTE 20 printf(" Type/Len: 0x%02x\n", record->data[offset++]); printf(" Shelf Addr: "); for ( i = 0; i < SIZE_SHELF_ADDRESS_BYTE; i++ ){ printf("0x%02x ", record->data[offset++]); } printf("\n"); entries = record->data[offset++]; printf(" Addr Table Entries count: 0x%02x\n", entries); for ( i = 0; i < entries; i++ ){ printf("\tHWAddr: 0x%02x - SiteNum: 0x%02x - SiteType: 0x%02x \n", record->data[offset+0], record->data[offset+1], record->data[offset+2]); offset += 3; } } /************************************************************************** * * Function name: ipmi_ek_display_shelf_power_distribution_record * * Description: this function displays shelf power distribution record. * * Restriction: Reference: PICMG 3.0 Specification Table 3-70 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_shelf_power_distribution_record( struct ipmi_ek_multi_header * record ) { int offset = START_DATA_OFFSET; unsigned char i,j; unsigned char feeds = 0; feeds = record->data[offset++]; printf(" Number of Power Feeds: 0x%02x\n", feeds); for (i=0; idata[offset+0] | (record->data[offset+1]<<8); printf(" Max External Available Current: %ld Amps\n", (max_ext*10) ); offset += 2; max_int = record->data[offset+0] | (record->data[offset+1]<<8); printf(" Max Internal Current:\t %ld Amps\n", (max_int*10)); offset += 2; printf(" Min Expected Operating Voltage: %ld Volts\n", (record->data[offset++]/2)); entries = record->data[offset++]; printf(" Feed to FRU count: 0x%02x\n", entries); for (j=0; jdata[offset++]); printf("\tFRU ID: 0x%02x\n", record->data[offset++]); } } } /************************************************************************** * * Function name: ipmi_ek_display_shelf_activation_record * * Description: this function displays shelf activation record. * * Restriction: Reference: PICMG 3.0 Specification Table 3-73 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_shelf_activation_record( struct ipmi_ek_multi_header * record ) { unsigned char count = 0; int offset = START_DATA_OFFSET; printf(" Allowance for FRU Act Readiness: 0x%02x\n", record->data[offset++]); count = record->data[offset++]; printf(" FRU activation and Power Desc Cnt: 0x%02x\n", count); while ( count > 0 ) { printf(" FRU activation and Power descriptor:\n"); printf("\tHardware Address:\t\t0x%02x\n", record->data[offset++]); printf("\tFRU Device ID:\t\t\t0x%02x\n", record->data[offset++]); printf("\tMax FRU Power Capability:\t0x%04x Watts\n", ( record->data[offset+0] | (record->data[offset+1]<<8) )); offset += 2; printf("\tConfiguration parameter:\t0x%02x\n", record->data[offset++]); count --; } } /************************************************************************** * * Function name: ipmi_ek_display_shelf_ip_connection_record * * Description: this function displays shelf ip connection record. * * Restriction: Fix me: Don't test yet * Reference: PICMG 3.0 Specification Table 3-31 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_shelf_ip_connection_record( struct ipmi_ek_multi_header * record ) { int ioffset = START_DATA_OFFSET; if (ioffset > record->header.len){ printf(" Shelf Manager IP Address: %d.%d.%d.%d\n", record->data[ioffset+0], record->data[ioffset+1], record->data[ioffset+2], record->data[ioffset+3]); ioffset += 4; } if (ioffset > record->header.len){ printf(" Default Gateway Address: %d.%d.%d.%d\n", record->data[ioffset+0], record->data[ioffset+1], record->data[ioffset+2], record->data[ioffset+3]); ioffset += 4; } if (ioffset > record->header.len){ printf(" Subnet Mask: %d.%d.%d.%d\n", record->data[ioffset+0], record->data[ioffset+1], record->data[ioffset+2], record->data[ioffset+3]); ioffset += 4; } } #ifdef NOT_USED static void ipmi_ek_display_shelf_fan_geography_record( struct ipmi_ek_multi_header * record ); /************************************************************************** * * Function name: ipmi_ek_display_shelf_fan_geography_record * * Description: this function displays shelf fan geography record. * * Restriction: Fix me: Don't test yet * Reference: PICMG 3.0 Specification Table 3-75 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_shelf_fan_geography_record( struct ipmi_ek_multi_header * record ) { int ioffset = START_DATA_OFFSET; unsigned char fan_count = 0; fan_count = record->data[ioffset]; ioffset ++; printf(" Fan-to-FRU Entry Count: 0x%02x\n", fan_count); while ( (fan_count > 0) && (ioffset <= record->header.len) ){ printf(" Fan-to-FRU Mapping Entry: {%2x%2x%2x%2x}\n", record->data[ioffset], record->data[ioffset+1], record->data[ioffset+2], record->data[ioffset+3] ); printf(" Hardware Address: 0x%02x\n", record->data[ioffset++]); printf(" FRU device ID: 0x%02x\n", record->data[ioffset++]); printf(" Site Number: 0x%02x\n", record->data[ioffset++]); printf(" Site Type: 0x%02x\n", record->data[ioffset++]); fan_count --; } } #endif /************************************************************************** * * Function name: ipmi_ek_display_board_p2p_record * * Description: this function displays board pont-to-point record. * * Restriction: Reference: PICMG 3.0 Specification Table 3-44 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_board_p2p_record( struct ipmi_ek_multi_header * record ) { unsigned char guid_count; int offset = START_DATA_OFFSET; int i = 0; guid_count = record->data[offset++]; printf(" GUID count: %2d\n", guid_count); for (i = 0 ; i < guid_count; i++ ) { int j; printf("\tGUID: "); for (j=0; j < sizeof(struct fru_picmgext_guid); j++) { printf("%02x", record->data[offset+j]); } printf("\n"); offset += sizeof(struct fru_picmgext_guid); } for ( /*offset set above*/ ; offset < record->header.len; offset += sizeof(struct fru_picmgext_link_desc) ) { /* to solve little endian /big endian problem */ unsigned long data; struct fru_picmgext_link_desc * d; data = (record->data[offset+0]) | (record->data[offset+1] << 8)\ | (record->data[offset+2] << 16)\ | (record->data[offset+3] << 24); d = (struct fru_picmgext_link_desc *) &data; printf(" Link Descriptor\n"); printf("\tLink Grouping ID:\t0x%02x\n", d->grouping); printf("\tLink Type Extension:\t0x%02x - ", d->ext); if (d->type == FRU_PICMGEXT_LINK_TYPE_BASE){ switch (d->ext){ case 0: printf("10/100/1000BASE-T Link (four-pair)\n"); break; case 1: printf("ShMC Cross-connect (two-pair)\n"); break; default: printf("Unknwon\n"); break; } } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET){ switch (d->ext){ case 0: printf("Fixed 1000Base-BX\n"); break; case 1: printf("Fixed 10GBASE-BX4 [XAUI]\n"); break; case 2: printf("FC-PI\n"); break; default: printf("Unknwon\n"); break; } } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND){ printf("Unknwon\n"); } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR){ printf("Unknwon\n"); } else if (d->type == FRU_PICMGEXT_LINK_TYPE_PCIE){ printf("Unknwon\n"); } else{ printf("Unknwon\n"); } printf("\tLink Type:\t\t0x%02x - ",d->type); if (d->type == 0 || d->type == 0xff){ printf("Reserved\n"); } else if (d->type >= 0x06 && d->type <= 0xef) { printf("Reserved\n"); } else if (d->type >= LOWER_OEM_TYPE && d->type <= UPPER_OEM_TYPE) { printf("OEM GUID Definition\n"); } else { switch (d->type){ case FRU_PICMGEXT_LINK_TYPE_BASE: printf("PICMG 3.0 Base Interface 10/100/1000\n"); break; case FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET: printf("PICMG 3.1 Ethernet Fabric Interface\n"); break; case FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND: printf("PICMG 3.2 Infiniband Fabric Interface\n"); break; case FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR: printf("PICMG 3.3 Star Fabric Interface\n"); break; case FRU_PICMGEXT_LINK_TYPE_PCIE: printf("PICMG 3.4 PCI Express Fabric Interface\n"); break; default: printf("Invalid\n"); break; } } printf("\tLink Designator: \n"); printf("\t Port 0 Flag: %s\n", (d->desig_port & 0x01) ? "enable" : "disable"); printf("\t Port 1 Flag: %s\n", (d->desig_port & 0x02) ? "enable" : "disable"); printf("\t Port 2 Flag: %s\n", (d->desig_port & 0x04) ? "enable" : "disable"); printf("\t Port 3 Flag: %s\n", (d->desig_port & 0x08) ? "enable" : "disable"); printf("\t Interface: 0x%02x - ", d->desig_if); switch (d->desig_if){ case FRU_PICMGEXT_DESIGN_IF_BASE: printf("Base Interface\n"); break; case FRU_PICMGEXT_DESIGN_IF_FABRIC: printf("Fabric Interface\n"); break; case FRU_PICMGEXT_DESIGN_IF_UPDATE_CHANNEL: printf("Update Channel\n"); break; case FRU_PICMGEXT_DESIGN_IF_RESERVED: printf("Reserved\n"); break; default: printf("Invalid"); break; } printf("\t Channel Number: 0x%02x\n", d->desig_channel); } } /************************************************************************** * * Function name: ipmi_ek_display_radial_ipmb0_record * * Description: this function displays radial IPMB-0 record. * * Restriction: Fix me: Don't test yet * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_radial_ipmb0_record( struct ipmi_ek_multi_header * record ) { int offset = START_DATA_OFFSET; #define SIZE_OF_CONNECTOR_DEFINER 3; /*bytes*/ /*Ref: PICMG 3.0 Specification Revision 2.0, Table 3-59*/ printf(" IPMB-0 Connector Definer: "); #ifndef WORDS_BIGENDIAN printf("%02x %02x %02x h\n", record->data[offset], record->data[offset+1], record->data[offset+2]); #else printf("%02x %02x %02x h\n", record->data[offset+2], record->data[offset+1], record->data[offset]); #endif /*3 bytes of connector definer was used*/ offset += SIZE_OF_CONNECTOR_DEFINER; printf (" IPMB-0 Connector version ID: "); #ifndef WORDS_BIGENDIAN printf("%02x %02x h\n", record->data[offset], record->data[offset+1]); #else printf("%02x %02x h\n", record->data[offset+1], record->data[offset]); #endif offset += 2; printf(" IPMB-0 Hub Descriptor Count: 0x%02x", record->data[offset++]); if (record->data[offset] > 0){ for (/*offset*/; offset < record->header.len;){ unsigned char entry_count = 0; printf(" IPMB-0 Hub Descriptor\n"); printf("\tHardware Address: 0x%02x\n", record->data[offset++]); printf("\tHub Info {0x%02x}: ", record->data[offset]); /* Bit mask specified in Table 3-59 of PICMG 3.0 Specification */ if ( (record->data[offset] & 0x01) == 0x01 ){ printf("IPMB-A only\n"); } else if ( (record->data[offset] & 0x02) == 0x02 ){ printf("IPMB-B only\n"); } else if ( (record->data[offset] & 0x03) == 0x03 ){ printf("IPMB-A and IPMB-B\n"); } else{ printf("Reserved.\n"); } offset ++; entry_count = record->data[offset++]; printf("\tAddress Entry count: 0x%02x", entry_count); while (entry_count > 0){ printf("\t Hardware Address: 0x%02x\n", record->data[offset++]); printf("\t IPMB-0 Link Entry: 0x%02x\n",record->data[offset++]); entry_count --; } } } } /************************************************************************** * * Function name: ipmi_ek_display_amc_current_record * * Description: this function displays AMC current record. * * Restriction: None * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_amc_current_record( struct ipmi_ek_multi_header * record ) { unsigned char current; current = record->data[START_DATA_OFFSET]; printf(" Current draw: %.1f A @ 12V => %.2f Watt\n", (float) current/10.0, ((float)current/10.0)*12.0 ); printf("\n"); } /************************************************************************** * * Function name: ipmi_ek_display_amc_activation_record * * Description: this function displays carrier activation and current management * record. * * Restriction: Reference: AMC.0 Specification Table 3-11 and Table 3-12 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_amc_activation_record( struct ipmi_ek_multi_header * record ) { uint16_t max_current; int offset = START_DATA_OFFSET; max_current = record->data[offset]; max_current |= record->data[++offset] << 8; printf(" Maximum Internal Current(@12V): %.2f A [ %.2f Watt ]\n", (float) max_current / 10, (float) max_current / 10 * 12); printf(" Module Activation Readiness: %i sec.\n", record->data[++offset]); printf(" Descriptor Count: %i\n", record->data[++offset]); for(++offset; (offset < record->header.len); offset += 3 ) { struct fru_picmgext_activation_record * a = (struct fru_picmgext_activation_record *) &record->data[offset]; printf("\tIPMB-Address:\t\t0x%x\n", a->ibmb_addr); printf("\tMax. Module Current:\t%.2f A\n", (float)a->max_module_curr/10); printf("\n"); } } /************************************************************************** * * Function name: ipmi_ek_display_amc_p2p_record * * Description: this function display amc p2p connectivity record in humain * readable text format * * Restriction: Reference: AMC.0 Specification Table 3-16 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_amc_p2p_record( struct ipmi_ek_multi_header * record ) { int index_data = START_DATA_OFFSET; int oem_count = 0; int ch_count = 0; int index=0; oem_count = record->data[index_data++]; printf("OEM GUID count: %02x\n", oem_count); if ( oem_count > 0 ){ while ( oem_count > 0 ){ printf("OEM GUID: "); for ( index = 1; index <= SIZE_OF_GUID; index++ ){ printf("%02x", record->data[index_data++]); /* For a better look, display a "-" character after each 5 bytes * of OEM GUID */ if ( !(index % 5) ){ printf("-"); } } printf("\n"); oem_count--; } } if ( ( record->data[index_data] & AMC_MODULE ) == AMC_MODULE ){ printf("AMC module connection\n"); } else{ printf("On-Carrier Device %02x h\n", ( record->data[index_data] & 0x0f )); } index_data ++; ch_count = record->data[index_data++]; printf("AMC Channel Descriptor count: %02x h\n", ch_count); if ( ch_count > 0 ){ for ( index = 0; index < ch_count; index++ ){ struct fru_picmgext_amc_channel_desc_record * ch_desc; printf(" AMC Channel Descriptor {%02x%02x%02x}\n", record->data[index_data+2], record->data[index_data+1], record->data[index_data] ); /*Warning: For gcc version between 4.0 and 4.3 this code doesnt work*/ ch_desc = ( struct fru_picmgext_amc_channel_desc_record * )\ &record->data[index_data]; printf(" Lane 0 Port: 0x%02x\n", ch_desc->lane0port); printf(" Lane 1 Port: 0x%02x\n", ch_desc->lane1port); printf(" Lane 2 Port: 0x%02x\n", ch_desc->lane2port); printf(" Lane 3 Port: 0x%02x\n\n", ch_desc->lane3port); index_data += sizeof (struct fru_picmgext_amc_channel_desc_record) ; } } while ( index_data < record->header.len ){ /*Warning: For gcc version between 4.0 and 4.3 this code doesnt work*/ struct fru_picmgext_amc_link_desc_record * link_desc = (struct fru_picmgext_amc_link_desc_record *)&record->data[index_data]; printf(" AMC Link Descriptor:\n" ); printf("\t- Link Type: %s \n", val2str (link_desc->type, ipmi_ekanalyzer_link_type)); switch ( link_desc->type ){ case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE: case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS1: case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS2: printf("\t- Link Type extension: %s\n", val2str (link_desc->type_ext, ipmi_ekanalyzer_extension_PCIE)); printf("\t- Link Group ID: %d\n ", link_desc->group_id ); printf("\t- Link Asym. Match: %s\n", val2str (link_desc->asym_match, ipmi_ekanalyzer_asym_PCIE)); break; case FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET: printf("\t- Link Type extension: %s\n", val2str (link_desc->type_ext, ipmi_ekanalyzer_extension_ETHERNET)); printf("\t- Link Group ID: %d \n", link_desc->group_id ); printf("\t- Link Asym. Match: %s\n", val2str (link_desc->asym_match, ipmi_ekanalyzer_asym_PCIE)); break; case FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE: printf("\t- Link Type extension: %s\n", val2str (link_desc->type_ext, ipmi_ekanalyzer_extension_STORAGE)); printf("\t- Link Group ID: %d \n", link_desc->group_id ); printf("\t- Link Asym. Match: %s\n", val2str (link_desc->asym_match, ipmi_ekanalyzer_asym_STORAGE)); break; default: printf("\t- Link Type extension: %i\n", link_desc->type_ext ); printf("\t- Link Group ID: %d \n", link_desc->group_id ); printf("\t- Link Asym. Match: %i\n", link_desc->asym_match); break; } printf("\t- AMC Link Designator:\n"); printf("\t Channel ID: %i\n", link_desc->channel_id); printf("\t\t Lane 0: %s\n", (link_desc->port_flag_0)?"enable":"disable"); printf("\t\t Lane 1: %s\n", (link_desc->port_flag_1)?"enable":"disable"); printf("\t\t Lane 2: %s\n", (link_desc->port_flag_2)?"enable":"disable"); printf("\t\t Lane 3: %s\n", (link_desc->port_flag_3)?"enable":"disable"); index_data += sizeof (struct fru_picmgext_amc_link_desc_record); } } /************************************************************************** * * Function name: ipmi_ek_display_amc_carrier_info_record * * Description: this function displays Carrier information table. * * Restriction: Reference: AMC.0 Specification Table 3-3 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: START_DATA_OFFSET * * Return: None * ***************************************************************************/ static void ipmi_ek_display_amc_carrier_info_record( struct ipmi_ek_multi_header * record ) { unsigned char extVersion; unsigned char siteCount; int offset = START_DATA_OFFSET; extVersion = record->data[offset++]; siteCount = record->data[offset++]; printf(" AMC.0 extension version: R%d.%d\n", (extVersion >> 0)& 0x0F, (extVersion >> 4)& 0x0F ); printf(" Carrier Sie Number Count: %d\n", siteCount); while (siteCount > 0){ printf("\tSite ID (%d): %s \n", record->data[offset], val2str(record->data[offset], ipmi_ekanalyzer_module_type) ); offset++; siteCount--; } printf("\n"); } /************************************************************************** * * Function name: ipmi_ek_display_clock_carrier_p2p_record * * Description: this function displays Carrier clock point-to-pont * connectivity record. * * Restriction: the following code is copy from ipmi_fru.c with modification in * reference to AMC.0 Specification Table 3-29 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_clock_carrier_p2p_record( struct ipmi_ek_multi_header * record ) { unsigned char desc_count; int i,j; int offset = START_DATA_OFFSET; desc_count = record->data[offset++]; for(i=0; idata[offset++]; channel_count = record->data[offset++]; printf(" Clock Resource ID: 0x%02x\n", resource_id); printf(" Type: "); if((resource_id & 0xC0)>>6 == 0) { printf("On-Carrier-Device\n"); } else if((resource_id & 0xC0)>>6 == 1) { printf("AMC slot\n"); } else if((resource_id & 0xC0)>>6 == 2) { printf("Backplane\n"); } else{ printf("reserved\n"); } printf(" Channel Count: 0x%02x\n", channel_count); for(j=0; jdata[offset++]; rem_channel = record->data[offset++]; rem_resource = record->data[offset++]; printf("\tCLK-ID: 0x%02x ---> ", loc_channel); printf(" remote CLKID: 0x%02x ", rem_channel); if((rem_resource & 0xC0)>>6 == 0) { printf("[ Carrier-Dev"); } else if((rem_resource & 0xC0)>>6 == 1) { printf("[ AMC slot "); } else if((rem_resource & 0xC0)>>6 == 2) { printf("[ Backplane "); } else{ printf("reserved "); } printf(" 0x%02x ]\n", rem_resource&0xF); } } printf("\n"); } /************************************************************************** * * Function name: ipmi_ek_display_clock_config_record * * Description: this function displays clock configuration record. * * Restriction: the following codes are copy from ipmi_fru.c with modification * in reference to AMC.0 Specification Table 3-35 and Table 3-36 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: START_DATA_OFFSET * * Return: None * ***************************************************************************/ void ipmi_ek_display_clock_config_record( struct ipmi_ek_multi_header * record ) { unsigned char resource_id, descr_count; int i; int offset = START_DATA_OFFSET; resource_id = record->data[offset++]; descr_count = record->data[offset++]; printf(" Clock Resource ID: 0x%02x\n", resource_id); printf(" Clock Configuration Descriptor Count: 0x%02x\n", descr_count); for(i=0; idata[offset++]; control = record->data[offset++]; printf("\tCLK-ID: 0x%02x - ", channel_id); printf("CTRL 0x%02x [ %12s ]\n", control, ((control&0x1)==0)?"Carrier IPMC":"Application"); indirect_cnt = record->data[offset++]; direct_cnt = record->data[offset++]; printf("\t Count: Indirect 0x%02x / Direct 0x%02x\n", indirect_cnt, direct_cnt ); /* indirect desc */ for(j=0; jdata[offset++]; dep_chn_id = record->data[offset++]; printf("\t\tFeature: 0x%02x [%8s] - ", feature, (feature&0x1)==1?"Source":"Receiver"); printf(" Dep. CLK-ID: 0x%02x\n", dep_chn_id); } /* direct desc */ for(j=0; jdata[offset++]; family = record->data[offset++]; accuracy = record->data[offset++]; freq = (record->data[offset+0] << 0 ) | (record->data[offset+1] << 8 ) | (record->data[offset+2] << 16) | (record->data[offset+3] << 24); offset += 4; min_freq = (record->data[offset+0] << 0 ) | (record->data[offset+1] << 8 ) | (record->data[offset+2] << 16) | (record->data[offset+3] << 24); offset += 4; max_freq = (record->data[offset+0] << 0 ) | (record->data[offset+1] << 8 ) | (record->data[offset+2] << 16) | (record->data[offset+3] << 24); offset += 4; printf("\t- Feature: 0x%02x - PLL: %x / Asym: %s\n", feature, (feature > 1) & 1, (feature&1)?"Source":"Receiver"); printf("\tFamily: 0x%02x - AccLVL: 0x%02x\n", family, accuracy); printf("\tFRQ: %-9d - min: %-9d - max: %-9d\n", freq, min_freq, max_freq); } printf("\n"); } } /************************************************************************** * * Function name: ipmi_ekanalyzer_fru_file2structure * * Description: this function convert a FRU binary file into a linked list of * FRU multi record * * Restriction: None * * Input/Ouput: filename1: name of the file that contain FRU binary data * record: a pointer to current record * list_head: a pointer to header of the list * list_last: a pointer to tale of the list * * Global: None * * Return: return -1 as Error status, and 0 as Ok status * ***************************************************************************/ static int ipmi_ekanalyzer_fru_file2structure( char * filename, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_record, struct ipmi_ek_multi_header ** list_last ) { int return_status = ERROR_STATUS; FILE * input_file; input_file = fopen ( filename, "r"); if ( input_file == NULL ){ lprintf(LOG_ERR, "File: '%s' is not found", filename); return_status = ERROR_STATUS; } else{ long multi_offset = 0; fseek_( input_file, START_DATA_OFFSET, SEEK_SET ); fread ( &multi_offset, 1, 1, input_file ); if ( multi_offset <= 0 ){ lprintf(LOG_NOTICE, "There is no multi record in the file %s\n", filename); } else{ int record_count = 0; if ( verbose >= 2) { // was == LOG_DEBUG printf( "start multi offset = 0x%02x\n", multi_offset ); } /*the offset value is in multiple of 8 bytes.*/ multi_offset = multi_offset * 8; fseek_( input_file, multi_offset, SEEK_SET ); while ( !feof( input_file ) ){ *list_record = malloc ( sizeof (struct ipmi_ek_multi_header) ); fread ( &(*list_record)->header, START_DATA_OFFSET, 1, input_file); if ( (*list_record)->header.len > 0 ){ (*list_record)->data = malloc ((*list_record)->header.len); if ( (*list_record)->data == NULL ){ lprintf(LOG_ERR, "Lack of memory"); } else{ unsigned char last_record = 0; fread ( (*list_record)->data, ((*list_record)->header.len), 1, input_file); if ( verbose > 0 ) printf("Record %d has length = %02x\n", record_count, (*list_record)->header.len); if ( verbose > 1 ){ int i; printf("%02x\t", (*list_record)->header.type); for ( i = 0; i < ( (*list_record)->header.len ); i++ ){ printf("%02x\t", (*list_record)->data[i]); } printf("\n"); } ipmi_ek_add_record2list ( list_record, list_head, list_last ); /*mask the 8th bits to see if it is the last record*/ last_record = ((*list_record)->header.format) & 0x80; if ( last_record ){ break; } } } record_count++; } } fclose( input_file ); return_status = OK_STATUS; } return return_status; } /************************************************************************** * * Function name: ipmi_ek_add_record2list * * Description: this function adds a sigle FRU multi record to a linked list of * FRU multi record. * * Restriction: None * * Input/Output: record: a pointer to current record * list_head: a pointer to header of the list * list_last: a pointer to tale of the list * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_add_record2list( struct ipmi_ek_multi_header ** record, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_last ) { if (*list_head == NULL) { *list_head = *record; (*record)->prev = NULL; if (verbose > 2) printf("Adding first record to list\n"); } else { (*list_last)->next = *record; (*record)->prev = *list_last; if (verbose > 2) printf("Add 1 record to list\n"); } *list_last = *record; (*record)->next = NULL; } /************************************************************************** * * Function name: ipmi_ek_remove_record_from_list * * Description: this function removes a sigle FRU multi record from a linked * list of FRU multi record. * * Restriction: None * * Input/Output: record: a pointer to record to be deleted * list_head: a pointer to header of the list * list_last: a pointer to tale of the list * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_remove_record_from_list( struct ipmi_ek_multi_header * record, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_last ) { if (record->prev == NULL) *list_head = record->next; else record->prev->next = record->next; if ( record->next == NULL ) (*list_last) = record->prev; else record->next->prev = record->prev; free (record); } #ifdef METACOMMAND int i_ekanalyzer(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { void *intf = NULL; int rc = 0; int c, i; char *s1; printf("%s ver %s\n", progname,progver); while ( (c = getopt( argc, argv,"m:p:T:V:J:EYF:P:N:R:U:Z:x?")) != EOF ) switch (c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'x': fdebug = 1; verbose = 2; break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; case '?': ipmi_ekanalyzer_usage(); return ERR_USAGE; break; } for (i = 0; i < optind; i++) { argv++; argc--; } rc = ipmi_ekanalyzer_main(intf, argc, argv); ipmi_close_(); return rc; } #else /* ekanalyzer stub */ #ifdef METACOMMAND int i_ekanalyzer(int argc, char **argv) { printf("ekanalyzer function is not enabled\n"); return -1; } #endif #endif /*end iekanalyzer.c*/ ipmiutil-3.1.5/util/oem_newisys.c0000644000076400007640000001105713566765324017144 0ustar mgportalloggers/* * oem_newisys.c * * This module handles OEM-specific functions for newisys firmware. * * Copyright (c) 2012 Kontron America, Inc. * * 04/05/12 Andy Cress v1.0 new, with input from ipmitool */ /*M* Copyright (c) 2012 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 Kontron 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*/ #ifdef WIN32 #include #endif #include #include #include #include "ipmicmd.h" #include "ievents.h" #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil newisysoem"; #else static char * progver = "3.08"; static char * progname = "inewisysoem"; #endif static char fdebug = 0; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; //static uchar g_addrtype = ADDR_SMI; #define DESC_MAX 200 /* * decode_sel_newisys * inputs: * evt = the 16-byte IPMI SEL event * outbuf = points to the output string buffer * outsz = size of the output buffer * outputs: * rv = 0 if this event was successfully interpreted here, * non-zero otherwise, to use default interpretations. * outbuf = will contain the interpreted event text string (if rv==0) */ int decode_sel_newisys(uchar *evt, char *outbuf, int outsz, char fdesc, char fdbg) { int rv = -1; ushort id, genid; ulong timestamp; char *type_str = NULL; char *gstr = NULL; char *pstr = NULL; int sevid; char description[DESC_MAX]; int rlen, i; uchar idata[16]; uchar rdata[DESC_MAX]; uchar cc; uchar snum, stype, rectype; fdebug = fdbg; id = evt[0] + (evt[1] << 8); rectype = evt[2]; timestamp = evt[3] + (evt[4] << 8) + (evt[5] << 16) + (evt[6] << 24); genid = evt[7] | (evt[8] << 8); stype = evt[10]; snum = evt[11]; gstr = "BMC "; if (genid == 0x0033) gstr = "Bios"; type_str = ""; if (rectype == 0x02) type_str = get_sensor_type_desc(stype); sevid = SEV_INFO; idata[0] = 0x15; /* IANA LSB */ idata[1] = 0x24; /* IANA */ idata[2] = 0x00; /* IANA MSB */ idata[3] = 0x01; /* Subcommand */ idata[4] = id & 0x00FF; /* SEL Record ID LSB */ idata[5] = (id & 0xFF00) >> 8; /* SEL Record ID MSB */ rlen = sizeof(rdata); rv = ipmi_cmdraw(0x01, 0x2E, g_sa,g_bus,g_lun, idata, 6, rdata, &rlen, &cc, fdebug); if ((rv == 0) && (cc != 0)) rv = cc; if (rv == 0) { if (rlen < 5) { printf("Newisys OEM response too short"); return LAN_ERR_TOO_SHORT; } else if (rlen != (4 + rdata[3])) { printf("Newisys OEM response has unexpected length"); return LAN_ERR_TOO_SHORT; } /* copy the description */ i = rdata[3]; if (i >= DESC_MAX) i = DESC_MAX - 1; if (i > (rlen-4)) i = rlen - 4; memcpy(description, &rdata[4], i); description[i] = 0;; pstr = description; /*TODO: parse for severity, setting sevid */ format_event(id,timestamp, sevid, genid, type_str, snum,NULL,pstr,NULL,outbuf,outsz); } return rv; } #ifdef METACOMMAND int i_newisysoem(int argc, char **argv) { printf("%s ver %s\n", progname,progver); return(0); } #endif /* end oem_newisys.c */ ipmiutil-3.1.5/util/AnsiTerm.cpp0000644000076400007640000014324213566765324016667 0ustar mgportalloggers/* * AnsiTerm.cpp * Windows ANSI Terminal Emulation * * Author: Robert Nelson robertnelson at users.sourceforge.net * Copyright (c) 2009 Robert Nelson * * 10/07/09 Robert Nelson - Created * 10/08/09 Robert Nelson * - Fixed bug with resetting attribute to Black on Black on exit * - Fixed setting of attribute when erasing * - Added automatic handling of buffer resize events * - Added display of unrecognized escape sequences * 10/15/09 Robert Nelson * - Fixed display problems caused by custom ColorTable used by cmd.exe * - Fixed cursor positioning problems with OriginMode. * - Changed to use block cursor because I think its more terminal like :-) * - Added Reset handling * - Added Cursor Show / Hide * 10/16/09 Robert Nelson * - Better handling of ColorTable. * 10/17/09 Robert Nelson * - Use GetProcAddress for (Get/Set)ConsoleScreenBufferInfoEx since they * are only available on Vista and beyond. * 01/27/2015 Andy Cress * - handle ProcessRM asserts * * Todo: * - Implement soft tabs */ /* Copyright (c) 2009, Robert Nelson 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. 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. */ #include #include #include #include "AnsiTerm.h" extern "C" unsigned char fCRLF; extern "C" void dbglog( char *pattn, ... ); CAnsiTerm::CSICode CAnsiTerm::s_CSITable[] = { { '[', DS_CSIParam }, { '#', DS_DECPrivate }, { '(', DS_SelectG0 }, { ')', DS_SelectG1 }, { '=', DS_None, &ProcessDECKPAM }, // Keypad Application Mode { '>', DS_None, &ProcessDECKPNM }, // Keypad Numeric Mode { '7', DS_None, &ProcessDECSC }, // Save Cursor { '8', DS_None, &ProcessDECRC }, // Restore Cursor { 'D', DS_None, &ProcessIND }, // Index { 'E', DS_None, &ProcessNEL }, // Next Line { 'H', DS_None, &ProcessHTS }, // Horizontal Tab Set { 'M', DS_None, &ProcessRI }, // Reverse Index { 'Z', DS_None, &ProcessDECID }, // Identify Terminal { 'c', DS_None, &ProcessRIS }, // Reset to Initial State { 's', DS_None, &ProcessSCP }, // Save Cursor Position { 'u', DS_None, &ProcessRCP }, // Restore Cursor Position { '\0' } }; CAnsiTerm::CSIFunction CAnsiTerm::s_DECFunction[] = { { '3', &ProcessDECDHLT }, // Double Height Line Top { '4', &ProcessDECDHLB }, // Double Height Line Bottom { '5', &ProcessDECSWL }, // Single Width Line { '6', &ProcessDECDWL }, // Double Width Line { '8', &ProcessDECALN }, // Screen Alignment Display { '\0' } }; CAnsiTerm::CSIFunction CAnsiTerm::s_CSIFunction[] = { { 'A', &ProcessCUU }, // Cursor Up { 'B', &ProcessCUD }, // Cursor Down { 'C', &ProcessCUF }, // Cursor Forward { 'D', &ProcessCUB }, // Cursor Backward { 'H', &ProcessCUP }, // Cursor Position { 'J', &ProcessED }, // Erase in Display { 'K', &ProcessEL }, // Erase in Line { 'c', &ProcessDA }, // Device Attributes { 'f', &ProcessHVP }, // Horizontal and Vertical Position { 'g', &ProcessTBC }, // Tabulation Clear { 'h', &ProcessSM }, // Set Mode { 'l', &ProcessRM }, // Reset Mode { 'm', &ProcessSGR }, // Select Graphics Rendition { 'n', &ProcessDSR }, // Device Status Report { 'q', &ProcessDECLL }, // DEC Load LEDs { 'r', &ProcessDECSTBM }, // DEC Set Top and Bottom Margins { 'x', &ProcessDECREQTPARM }, // Request Terminal Parameters { 'y', &ProcessDECTST }, // Invoke Confidence Test { '\0' } }; wchar_t CAnsiTerm::s_GraphicChars[kMaxGraphicsChar - kMinGraphicsChar + 1] = { 0x0020, // 0137 5F 95 _ Blank 0x2666, // 0140 60 96 ` Diamond 0x2592, // 0141 61 97 a Checkerboard 0x2409, // 0142 62 98 b Horizontal Tab 0x240C, // 0143 63 99 c Form Feed 0x240D, // 0144 64 100 d Carriage Return 0x240A, // 0145 65 101 e Line Feed 0x00B0, // 0146 66 102 f Degree Symbol 0x00B1, // 0147 67 103 g Plus/Minus 0x2424, // 0150 68 104 h New Line 0x240B, // 0151 69 105 i Vertical Tab 0x2518, // 0152 6A 106 j Lower-right corner 0x2510, // 0153 6B 107 k Upper-right corner 0x250C, // 0154 6C 108 l Upper-left corner 0x2514, // 0155 6D 109 m Lower-left corner 0x253C, // 0156 6E 110 n Crossing Lines 0x00AF, // 0157 6F 111 o Horizontal Line - Scan 1 0x0070, // 0160 70 112 p Horizontal Line - Scan 3 (No translation) 0x2500, // 0161 71 113 q Horizontal Line - Scan 5 0x0072, // 0162 72 114 r Horizontal Line - Scan 7 (No translation) 0x005F, // 0163 73 115 s Horizontal Line - Scan 9 0x251C, // 0164 74 116 t Left "T" 0x2524, // 0165 75 117 u Right "T" 0x2534, // 0166 76 118 v Bottom "T" 0x252C, // 0167 77 119 w Top "T" 0x2502, // 0170 78 120 x | Vertical bar 0x2264, // 0171 79 121 y Less than or equal to 0x2265, // 0172 7A 122 z Greater than or equal to 0x03C0, // 0173 7B 123 { Pi 0x2260, // 0174 7C 124 | Not equal to 0x00A3, // 0175 7D 125 } UK Pound Sign 0x00B7 // 0176 7E 126 ~ Centered dot }; wchar_t CAnsiTerm::s_OemToUnicode[256] = { 0x2007, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, // 00-07 0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C, // 08-0F 0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8, // 10-17 0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC, // 18-1F 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, // 20-27 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, // 28-2F 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, // 30-37 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, // 38-3F 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, // 40-47 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, // 48-4F 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, // 50-57 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, // 58-5F 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, // 60-67 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, // 68-6F 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, // 70-77 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, // 78-7F 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, // 80-87 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, // 88-8F 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, // 90-97 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, // 98-9F 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, // A0-A7 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, // A8-AF 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, // B0-B7 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, // B8-BF 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, // C0-C7 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, // C8-CF 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, // D0-D7 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, // D8-DF 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, // E0-E7 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, // E8-EF 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, // F0-F7 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 // F8-FF }; COLORREF CAnsiTerm::s_ColorTable[kColorTableSize] = { RGB(0, 0, 0), RGB(0, 0, 128), RGB(0, 128, 0), RGB(0, 128, 128), RGB(128, 0, 0), RGB(128, 0, 128), RGB(128, 128, 0), RGB(192, 192, 192), RGB(128, 128, 128), RGB(0, 0, 255), RGB(0, 255, 0), RGB(0, 255, 255), RGB(255, 0, 0), RGB(255, 0, 255), RGB(255, 255, 0), RGB(255, 255, 255) }; CAnsiTerm::PFN_GetConsoleScreenBufferInfoEx CAnsiTerm::s_pfnGetConsoleScreenBufferInfoEx; CAnsiTerm::PFN_SetConsoleScreenBufferInfoEx CAnsiTerm::s_pfnSetConsoleScreenBufferInfoEx; CAnsiTerm::CAnsiTerm(void) { m_hConsole = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleMode(m_hConsole, &m_dwOrigConsoleMode); SetConsoleMode(m_hConsole, ENABLE_PROCESSED_OUTPUT); CONSOLE_CURSOR_INFO cursorInfo; GetConsoleCursorInfo(m_hConsole, &cursorInfo); m_dwOrigCursorSize = cursorInfo.dwSize; WindowSizeChanged(true); } CAnsiTerm::~CAnsiTerm(void) { CONSOLE_CURSOR_INFO cursorInfo = { m_dwOrigCursorSize, TRUE }; SetConsoleCursorInfo(m_hConsole, &cursorInfo); SetConsoleMode(m_hConsole, m_dwOrigConsoleMode); SetConsoleTextAttribute(m_hConsole, m_wOrigConsoleAttribute); if (m_bResetColorTable) { CONSOLE_SCREEN_BUFFER_INFOEX consoleInfo = { sizeof(consoleInfo) }; s_pfnGetConsoleScreenBufferInfoEx(m_hConsole, &consoleInfo); memcpy(consoleInfo.ColorTable, m_OrigColorTable, kColorTableSize * sizeof(consoleInfo.ColorTable[0])); // There is a bug between GetConsoleScreenBufferInfoEx and SetConsoleScreenBufferInfoEx. // The first treats srWindow.Right and srWindow.Bottom as inclusive and the latter as exclusive. consoleInfo.srWindow.Right++; consoleInfo.srWindow.Bottom++; s_pfnSetConsoleScreenBufferInfoEx(m_hConsole, &consoleInfo); // Reset the attributes on existing lines so that at least white on black looks // correct. COORD coordStart = { 0, 0 }; DWORD dwWritten; FillConsoleOutputAttribute(m_hConsole, m_wOrigConsoleAttribute, m_BufferSize.X * m_BufferSize.Y, coordStart, &dwWritten); } CloseHandle(m_hConsole); } void CAnsiTerm::WindowSizeChanged(bool bInitial) { WORD wCurrentAttribute; COORD dwCurrentCursorPosition; if (bInitial) { HMODULE hKernel32 = GetModuleHandle("kernel32"); if (hKernel32 != NULL) { s_pfnGetConsoleScreenBufferInfoEx = (PFN_GetConsoleScreenBufferInfoEx)GetProcAddress(hKernel32, "GetConsoleScreenBufferInfoEx"); s_pfnSetConsoleScreenBufferInfoEx = (PFN_SetConsoleScreenBufferInfoEx)GetProcAddress(hKernel32, "SetConsoleScreenBufferInfoEx"); if (s_pfnGetConsoleScreenBufferInfoEx == NULL || s_pfnSetConsoleScreenBufferInfoEx == NULL) { s_pfnGetConsoleScreenBufferInfoEx = NULL; s_pfnSetConsoleScreenBufferInfoEx = NULL; } } m_bResetColorTable = false; } if (s_pfnGetConsoleScreenBufferInfoEx != NULL) { CONSOLE_SCREEN_BUFFER_INFOEX consoleInfo = { sizeof(consoleInfo) }; s_pfnGetConsoleScreenBufferInfoEx(m_hConsole, &consoleInfo); m_BufferSize = consoleInfo.dwSize; m_WindowSize.X = consoleInfo.srWindow.Right - consoleInfo.srWindow.Left + 1; m_WindowSize.Y = consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1; wCurrentAttribute = consoleInfo.wAttributes; dwCurrentCursorPosition = consoleInfo.dwCursorPosition; if (bInitial) { m_bResetColorTable = memcmp(consoleInfo.ColorTable, s_ColorTable, sizeof(s_ColorTable)) != 0; if (m_bResetColorTable) { // The command prompt (cmd.exe) uses a nonstandard color table // So we save it away and reset it to match the Console API documentation size_t colorCopyLen = kColorTableSize * sizeof(consoleInfo.ColorTable[0]); memcpy(m_OrigColorTable, consoleInfo.ColorTable, colorCopyLen); memcpy(consoleInfo.ColorTable, s_ColorTable, colorCopyLen); // There is a bug between GetConsoleScreenBufferInfoEx and SetConsoleScreenBufferInfoEx. // The first treats srWindow.Right and srWindow.Bottom as inclusive and the latter as exclusive. consoleInfo.srWindow.Right++; consoleInfo.srWindow.Bottom++; s_pfnSetConsoleScreenBufferInfoEx(m_hConsole, &consoleInfo); // Reset the attributes on existing lines so that at least white on black looks // correct. COORD coordStart = { 0, 0 }; DWORD dwWritten; FillConsoleOutputAttribute(m_hConsole, kDefaultAttribute, m_BufferSize.X * m_BufferSize.Y, coordStart, &dwWritten); } } } else { CONSOLE_SCREEN_BUFFER_INFO consoleInfo; GetConsoleScreenBufferInfo(m_hConsole, &consoleInfo); m_BufferSize = consoleInfo.dwSize; m_WindowSize.X = consoleInfo.srWindow.Right - consoleInfo.srWindow.Left + 1; m_WindowSize.Y = consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1; wCurrentAttribute = consoleInfo.wAttributes; dwCurrentCursorPosition = consoleInfo.dwCursorPosition; } m_WindowOrigin.X = 0; m_WindowOrigin.Y = m_BufferSize.Y - m_WindowSize.Y; if (bInitial) { m_wOrigConsoleAttribute = wCurrentAttribute; SHORT nLines = dwCurrentCursorPosition.Y - m_WindowOrigin.Y; if (nLines != 0) { SMALL_RECT rectSource = { 0, 0, m_BufferSize.X - 1, m_BufferSize.Y - 1 }; COORD coordDest = { 0, 0 }; CHAR_INFO charInfo = { ' ', kDefaultAttribute }; if (nLines > 0) { rectSource.Top = nLines; } else { coordDest.Y -= nLines; rectSource.Bottom += nLines; } ScrollConsoleScreenBuffer(m_hConsole, &rectSource, NULL, coordDest, &charInfo); } } ResetTerm(); } int CAnsiTerm::ProcessInput(CAnsiTerm::KeyCode keyCode, unsigned char *pOutput, int iOutputSize) { int iOutputLength = 0; if (pOutput == NULL || iOutputSize < 1) { return 0; } if (!keyCode.bKeyDown) { return 0; } if (VK_F1 <= keyCode.VirtualKeyCode && keyCode.VirtualKeyCode <= VK_F12) { pOutput[iOutputLength++] = CH_ESC; pOutput[iOutputLength++] = 'O'; pOutput[iOutputLength++] = 'P' + keyCode.VirtualKeyCode - VK_F1; } else if (keyCode.VirtualKeyCode == VK_UP || keyCode.VirtualKeyCode == VK_DOWN || keyCode.VirtualKeyCode == VK_RIGHT || keyCode.VirtualKeyCode == VK_LEFT) { pOutput[iOutputLength++] = CH_ESC; if ((m_bCursorKeyMode && !keyCode.bControl) || (!m_bCursorKeyMode && keyCode.bControl)) { pOutput[iOutputLength++] = 'O'; } else { pOutput[iOutputLength++] = '['; } switch (keyCode.VirtualKeyCode) { case VK_UP: pOutput[iOutputLength++] = 'A'; break; case VK_DOWN: pOutput[iOutputLength++] = 'B'; break; case VK_RIGHT: pOutput[iOutputLength++] = 'C'; break; case VK_LEFT: pOutput[iOutputLength++] = 'D'; break; } } else if (keyCode.VirtualKeyCode == VK_HOME || keyCode.VirtualKeyCode == VK_INSERT || keyCode.VirtualKeyCode == VK_DELETE || keyCode.VirtualKeyCode == VK_END || keyCode.VirtualKeyCode == VK_PRIOR || keyCode.VirtualKeyCode == VK_NEXT) { pOutput[iOutputLength++] = CH_ESC; pOutput[iOutputLength++] = '['; switch (keyCode.VirtualKeyCode) { case VK_HOME: pOutput[iOutputLength++] = '1'; break; case VK_INSERT: pOutput[iOutputLength++] = '2'; break; case VK_DELETE: pOutput[iOutputLength++] = '3'; break; case VK_END: pOutput[iOutputLength++] = '4'; break; case VK_PRIOR: pOutput[iOutputLength++] = '5'; break; case VK_NEXT: pOutput[iOutputLength++] = '6'; break; } pOutput[iOutputLength++] = '~'; } else if (keyCode.VirtualKeyCode == VK_RETURN) { pOutput[iOutputLength++] = CH_CR; if (fCRLF == 1) { pOutput[iOutputLength++] = CH_LF; } } else if (keyCode.AsciiChar != '\0') { pOutput[iOutputLength++] = keyCode.AsciiChar; } return iOutputLength; } bool CAnsiTerm::ProcessOutput(const unsigned char *szData, int iLength) { const unsigned char *pEnd = &szData[iLength]; for (const unsigned char *pCurrent = szData; pCurrent < pEnd; pCurrent++) { if (*pCurrent < 0x20 || *pCurrent == 0x7F) { dbglog("ProcessOutput: control_ch = %02x\n",*pCurrent); OutputText(); switch (*pCurrent) { case CH_NUL: case CH_ENQ: case CH_DEL: // These are ignored break; case CH_BEL: MessageBeep(MB_ICONASTERISK); break; case CH_BS: ProcessBackspace(); break; case CH_HT: ProcessTab(); break; case CH_LF: case CH_VT: case CH_FF: ProcessLinefeed(m_bLineFeedNewLineMode); break; case CH_CR: ProcessReturn(); break; case CH_SO: m_SelectedCharset = CharsetG1; break; case CH_SI: m_SelectedCharset = CharsetG0; break; case CH_XON: // Not yet implemented break; case CH_XOF: // Not yet implemented break; #if 0 case CH_CAN: case CH_SUB: // Output error character break; #endif case CH_ESC: m_State = DS_Escape; break; default: AddOutputData(s_OemToUnicode[*pCurrent]); break; } } else { /* db b3 or b0 b3 */ if (*pCurrent & 0x80) dbglog("ProcessOutput: state=%d ch=%02x\n",m_State,*pCurrent); switch (m_State) { case DS_Normal: if (*pCurrent & 0x80) { // Could be start of a UTF-8 sequence or an ANSI extended character if ((*pCurrent & 0xE0) == 0xC0) { m_UTF8Size = 2; } else if ((*pCurrent & 0xF0) == 0xE0) { m_UTF8Size = 3; } else { // Not a UTF-8 lead character AddOutputData(s_OemToUnicode[*pCurrent]); break; } m_UTF8Count = 1; m_UTF8Buffer[0] = *pCurrent; m_State = DS_UTF8; break; } if ((m_SelectedCharset == CharsetG0 && m_G0Charset == SpecialGraphicsCharset) || (m_SelectedCharset == CharsetG1 && m_G1Charset == SpecialGraphicsCharset)) { if (kMinGraphicsChar <= *pCurrent && *pCurrent <= kMaxGraphicsChar) { AddOutputData(s_GraphicChars[*pCurrent - kMinGraphicsChar]); } else { AddOutputData(*pCurrent); } } else { AddOutputData(*pCurrent); } break; case DS_UTF8: if ((*pCurrent & 0xC0) != 0x80) { for (int index = 0; index < m_UTF8Count; index++) { AddOutputData(s_OemToUnicode[m_UTF8Buffer[index]]); } if (*pCurrent & 0x80) { AddOutputData(s_OemToUnicode[*pCurrent]); } else { AddOutputData(*pCurrent); } m_State = DS_Normal; } else { m_UTF8Buffer[m_UTF8Count++] = *pCurrent; if (m_UTF8Count == m_UTF8Size) { wchar_t wchUTF16; if (m_UTF8Size == 2) { wchUTF16 = ((m_UTF8Buffer[0] & 0x1F) << 6) | (m_UTF8Buffer[1] & 0x3F); } else { wchUTF16 = ((m_UTF8Buffer[0] & 0x0F) << 12) | ((m_UTF8Buffer[1] & 0x3F) << 6) | (m_UTF8Buffer[2] & 0x3F); } AddOutputData(wchUTF16); m_State = DS_Normal; } } break; case DS_Escape: for (int index = 0; s_CSITable[index].chCode != '\0'; index++) { if (*pCurrent == s_CSITable[index].chCode) { if (s_CSITable[index].dsNextState != DS_None) { m_State = s_CSITable[index].dsNextState; m_Parameters[0] = 0; m_ParameterCount = 0; m_bParametersStart = true; } else { (this->*s_CSITable[index].pfnProcess)(); m_State = DS_Normal; } break; } } if (m_State == DS_Escape) { AddOutputData(L'^'); AddOutputData(L'['); AddOutputData(*pCurrent); m_State = DS_Normal; } break; case DS_CSIParam: if (m_bParametersStart) { m_bParametersStart = false; if (*pCurrent == '?') { m_bPrivateParameters = true; break; } else { m_bPrivateParameters = false; } } if ('0' <= *pCurrent && *pCurrent <= '9') { if (m_ParameterCount < kMaxParameterCount) { m_Parameters[m_ParameterCount] *= 10; m_Parameters[m_ParameterCount] += *pCurrent - '0'; } } else if (*pCurrent == ';') { if (m_ParameterCount < kMaxParameterCount) { m_ParameterCount++; } if (m_ParameterCount < kMaxParameterCount) { m_Parameters[m_ParameterCount] = 0; } } else { if (m_ParameterCount < kMaxParameterCount) { m_ParameterCount++; } for (int index = 0; s_CSIFunction[index].chCode != '\0'; index++) { if (*pCurrent == s_CSIFunction[index].chCode) { (this->*s_CSIFunction[index].pfnProcess)(); m_State = DS_Normal; break; } } if (m_State != DS_Normal) { DisplayCSI(*pCurrent); m_State = DS_Normal; } } break; case DS_DECPrivate: for (int index = 0; s_DECFunction[index].chCode != '\0'; index++) { if (*pCurrent == s_DECFunction[index].chCode) { (this->*s_DECFunction[index].pfnProcess)(); m_State = DS_Normal; break; } } if (m_State != DS_Normal) { AddOutputData(L'^'); AddOutputData(L'['); AddOutputData(L'#'); AddOutputData(*pCurrent); } break; case DS_SelectG0: ProcessSCSG0(*pCurrent); m_State = DS_Normal; break; case DS_SelectG1: ProcessSCSG1(*pCurrent); m_State = DS_Normal; break; default: dbglog("ProcessOutput: illegal m_State=%d\n",m_State); assert(false); break; } } } OutputText(); return true; } void CAnsiTerm::DisplayCSI(char ch) { char szParam[15]; AddOutputData(L'^'); AddOutputData(L'['); AddOutputData(L'['); for (int idxParam = 0; idxParam < m_ParameterCount; idxParam++) { if (idxParam > 0) { AddOutputData(L';'); } int iLenParam = sprintf(szParam, "%d", m_Parameters[idxParam]); for (int idxChar = 0; idxChar < iLenParam; idxChar++) { AddOutputData(szParam[idxChar]); } } AddOutputData(ch); } bool CAnsiTerm::ResetTerm(void) { m_State = DS_Normal; m_SelectedCharset = CharsetG0; m_G0Charset = AsciiCharset; m_G1Charset = SpecialGraphicsCharset; m_Cursor.X = 0; m_Cursor.Y = 0; m_SavedCursor = m_Cursor; m_sTopMargin = 0; m_sBottomMargin = m_WindowSize.Y - 1; m_Attribute = kDefaultAttribute; UpdateTextAttribute(); m_dwOutputCount = 0; // if (fCRLF == 1) m_bLineFeedNewLineMode = true; /*was false*/ m_bCursorKeyMode = false; m_bAnsiMode = true; m_bColumnMode = true; m_bScrollingMode = false; m_bScreenMode = false; m_bOriginMode = false; m_bAutoRepeatingMode = true; m_bInterlaceMode = false; m_bDisplayCursor = true; m_bAutoWrapMode = true; /*default to wrap*/ EraseDisplay(EraseAll); SetCursorPosition(); DisplayCursor(); return true; } bool CAnsiTerm::DisplayCursor(void) { CONSOLE_CURSOR_INFO cursorInfo = { 100, m_bDisplayCursor }; return SetConsoleCursorInfo(m_hConsole, &cursorInfo) != FALSE; } bool CAnsiTerm::UpdateTextAttribute(void) { return SetConsoleTextAttribute(m_hConsole, m_Attribute) != FALSE; } bool CAnsiTerm::GetCursorPosition(void) { CONSOLE_SCREEN_BUFFER_INFO bufferInfo; if (GetConsoleScreenBufferInfo(m_hConsole, &bufferInfo)) { m_Cursor = bufferInfo.dwCursorPosition; m_Cursor.Y -= m_WindowOrigin.Y + (m_bOriginMode ? m_sTopMargin : 0); return true; } return false; } bool CAnsiTerm::SetCursorPosition(void) { COORD cursor = m_Cursor; cursor.Y += m_WindowOrigin.Y + (m_bOriginMode ? m_sTopMargin : 0); return SetConsoleCursorPosition(m_hConsole, cursor) != FALSE; } bool CAnsiTerm::ScrollDisplay(int n, bool bWindowOnly) { SHORT nLines = (SHORT)n; if (nLines == 0) { return true; } SMALL_RECT rectSource = { 0, 0, m_BufferSize.X - 1, m_BufferSize.Y - 1 }; COORD coordDest = { 0, 0 }; CHAR_INFO charInfo = { ' ', m_Attribute }; if (nLines > 0) { if (bWindowOnly || m_sTopMargin > 0) { coordDest.Y = m_WindowOrigin.Y + m_sTopMargin; rectSource.Top = m_WindowOrigin.Y + m_sTopMargin + nLines; rectSource.Bottom = m_WindowOrigin.Y + m_sBottomMargin; } else { rectSource.Top = nLines; rectSource.Bottom = m_WindowOrigin.Y + m_sBottomMargin; } } else { if (bWindowOnly) { coordDest.Y = m_WindowOrigin.Y + m_sTopMargin - nLines; rectSource.Top = m_WindowOrigin.Y + m_sTopMargin; rectSource.Bottom = m_WindowOrigin.Y + m_sBottomMargin + 1 + nLines; } else { coordDest.Y -= nLines; } rectSource.Bottom += nLines; } return ScrollConsoleScreenBuffer(m_hConsole, &rectSource, NULL, coordDest, &charInfo) != FALSE; } bool CAnsiTerm::EraseLine(EraseType eType) { DWORD dwLength; COORD coordStart = m_WindowOrigin; coordStart.Y += m_Cursor.Y + (m_bOriginMode ? m_sTopMargin : 0); switch (eType) { case EraseCursorToEnd: if (m_Cursor.X < m_WindowSize.X) { coordStart.X += m_Cursor.X; dwLength = m_BufferSize.X - m_Cursor.X; } else { dwLength = 0; } break; case EraseBeginningToCursor: if (m_Cursor.X < m_WindowSize.X) { dwLength = m_Cursor.X + 1; } else { dwLength = m_BufferSize.X; } break; case EraseAll: dwLength = m_BufferSize.X; break; default: return false; } if (dwLength > 0) { DWORD dwWritten; FillConsoleOutputAttribute(m_hConsole, m_Attribute, dwLength, coordStart, &dwWritten); return FillConsoleOutputCharacter(m_hConsole, ' ', dwLength, coordStart, &dwWritten) != FALSE; } else { return true; } } bool CAnsiTerm::EraseDisplay(EraseType eType) { COORD coordStart = m_WindowOrigin; DWORD dwLength; switch (eType) { case EraseCursorToEnd: if (m_Cursor.X < m_WindowSize.X) { coordStart.X += m_Cursor.X; coordStart.Y += m_Cursor.Y + (m_bOriginMode ? m_sTopMargin : 0); dwLength = (m_WindowSize.Y - m_Cursor.Y - (m_bOriginMode ? m_sTopMargin : 0)) * m_BufferSize.X - m_Cursor.X; } else if (m_Cursor.Y < (m_WindowSize.Y - 1)) { coordStart.X = 0; coordStart.Y += m_Cursor.Y + 1; dwLength = (m_WindowSize.Y - m_Cursor.Y - (m_bOriginMode ? m_sTopMargin : 0) - 1) * m_BufferSize.X; } else { dwLength = 0; } break; case EraseBeginningToCursor: if (m_Cursor.X < m_WindowSize.X) { dwLength = (m_Cursor.Y + (m_bOriginMode ? m_sTopMargin : 0)) * m_BufferSize.X + m_Cursor.X; } else { dwLength = (m_Cursor.Y + (m_bOriginMode ? m_sTopMargin : 0) + 1) * m_BufferSize.X; } break; case EraseAll: dwLength = m_BufferSize.X * m_WindowSize.Y; break; default: return false; } if (dwLength > 0) { DWORD dwWritten; FillConsoleOutputAttribute(m_hConsole, m_Attribute, dwLength, coordStart, &dwWritten); return FillConsoleOutputCharacter(m_hConsole, ' ', dwLength, coordStart, &dwWritten) != FALSE; } else { return true; } } DWORD CAnsiTerm::OutputText(void) { if (m_dwOutputCount == 0) { return 0; } DWORD dwTotalWritten = 0; wchar_t * pwszCurrent = m_OutputBuffer; DWORD dwLeftToWrite = m_dwOutputCount; while (dwLeftToWrite > 0) { DWORD dwWritten; if (m_Cursor.X >= m_WindowSize.X) { if (m_bAutoWrapMode) { ProcessLinefeed(true); } else { m_Cursor.X = m_WindowSize.X - 1; SetCursorPosition(); if (WriteConsoleW(m_hConsole, &m_OutputBuffer[m_dwOutputCount - 1], 1, &dwWritten, NULL)) { dbglog("OutputTest: WriteConsoleW error1\n"); assert(dwWritten == 1); } m_Cursor.X++; dwTotalWritten += dwLeftToWrite; break; } } DWORD dwPartialCount = min(dwLeftToWrite, (DWORD)(m_WindowSize.X - m_Cursor.X)); if (WriteConsoleW(m_hConsole, pwszCurrent, dwPartialCount, &dwWritten, NULL)) { dbglog("OutputTest: WriteConsoleW error2\n"); assert(dwWritten == dwPartialCount); } else { DWORD dwError = GetLastError(); } m_Cursor.X += (SHORT)dwPartialCount; pwszCurrent += dwPartialCount; dwTotalWritten += dwPartialCount; dwLeftToWrite -= dwPartialCount; } m_dwOutputCount = 0; return dwTotalWritten; } bool CAnsiTerm::ProcessBackspace(void) { if (m_Cursor.X > 0) { if (m_Cursor.X < m_WindowSize.X) { m_Cursor.X--; } else { m_Cursor.X = m_WindowSize.X - 1; } return SetCursorPosition(); } return true; } bool CAnsiTerm::ProcessTab(void) { if (m_Cursor.X >= m_WindowSize.X) { if (m_bAutoWrapMode) { ProcessLinefeed(true); } else { return true; } } int newX = m_Cursor.X + 8; newX &= ~7; if (newX >= m_WindowSize.X) { newX = m_WindowSize.X - 1; } int cntSpaces = newX - m_Cursor.X; for (int index = 0; index < cntSpaces; index++) { AddOutputData(L' '); } return true; } bool CAnsiTerm::ProcessReverseLinefeed(void) { if (m_Cursor.Y == 0) { ScrollDisplay(-1, true); } else { m_Cursor.Y--; } return SetCursorPosition(); } bool CAnsiTerm::ProcessLinefeed(bool bNewLine) { if (bNewLine) { m_Cursor.X = 0; } if (m_bOriginMode || (m_Cursor.Y >= m_sTopMargin && m_Cursor.Y <= m_sBottomMargin)) { if (m_Cursor.Y >= (m_sBottomMargin - m_sTopMargin)) { ScrollDisplay(1, false); m_Cursor.Y = m_sBottomMargin; } else { m_Cursor.Y++; } } else if (m_Cursor.Y < m_sBottomMargin) { m_Cursor.Y++; } return SetCursorPosition(); } bool CAnsiTerm::ProcessReturn(void) { m_Cursor.X = 0; return SetCursorPosition(); } bool CAnsiTerm::ProcessDECALN(void) { // Fill the display with 'E' for adjusting the CRT on a VT100 - Ignore it return true; } bool CAnsiTerm::ProcessDECDHLB(void) { // Double Height Line Bottom - Not supported return true; } bool CAnsiTerm::ProcessDECDHLT(void) { // Double Height Line Top - Not supported return true; } bool CAnsiTerm::ProcessDECDWL(void) { // Double Width Line - Not supported return true; } bool CAnsiTerm::ProcessDECID(void) { return ProcessDA(); } bool CAnsiTerm::ProcessDECKPAM(void) { // Keypad Application Mode - Not yet implemented return true; } bool CAnsiTerm::ProcessDECKPNM(void) { // Keypad Numeric Mode - Not yet implemented return true; } bool CAnsiTerm::ProcessDECLL(void) { // Load LEDs - Not Supported return true; } bool CAnsiTerm::ProcessDECRC(void) { return ProcessRCP(); } bool CAnsiTerm::ProcessDECREQTPARM(void) { // Request Terminal Parameters (Baud Rate, Parity, etc) - Not supported return true; } bool CAnsiTerm::ProcessDECSC(void) { return ProcessSCP(); } bool CAnsiTerm::ProcessDECSTBM(void) { assert(m_ParameterCount >= 1); if (m_Parameters[0] > 0) { m_Parameters[0]--; } if (m_ParameterCount < 2) { m_Parameters[1] = m_WindowSize.Y - 1; } else { if (m_Parameters[1] > 0) { m_Parameters[1]--; } else { m_Parameters[1] = m_WindowSize.Y - 1; } } if (m_Parameters[0] >= m_WindowSize.Y || m_Parameters[1] >= m_WindowSize.Y || m_Parameters[0] >= m_Parameters[1]) { return false; } m_sTopMargin = (SHORT)m_Parameters[0]; m_sBottomMargin = (SHORT)m_Parameters[1]; m_Cursor.X = 0; m_Cursor.Y = 0; SetCursorPosition(); return true; } bool CAnsiTerm::ProcessDECSWL(void) { // Single Width Line - Since Double Width Line isn't supported, this isn't necessary return true; } bool CAnsiTerm::ProcessDECTST(void) { // Perform Self Test - Not supported return true; } bool CAnsiTerm::ProcessCUB(void) { if (m_Parameters[0] == 0) { m_Parameters[0]++; } m_Cursor.X -= min(m_Cursor.X, m_Parameters[0]); return SetCursorPosition(); } bool CAnsiTerm::ProcessCUD(void) { if (m_Parameters[0] == 0) { m_Parameters[0]++; } m_Cursor.Y += min((m_bOriginMode ? m_sBottomMargin : m_WindowSize.Y - 1) - m_Cursor.Y, m_Parameters[0]); return SetCursorPosition(); } bool CAnsiTerm::ProcessCUF(void) { if (m_Parameters[0] == 0) { m_Parameters[0]++; } m_Cursor.X += min(m_WindowSize.X - m_Cursor.X - 1, m_Parameters[0]); return SetCursorPosition(); } bool CAnsiTerm::ProcessCUP(void) { return ProcessHVP(); } bool CAnsiTerm::ProcessCUU(void) { if (m_Parameters[0] == 0) { m_Parameters[0]++; } m_Cursor.Y -= min(m_Cursor.Y, m_Parameters[0]); return SetCursorPosition(); } bool CAnsiTerm::ProcessDA(void) { // Send Device Attributes - Not supported return true; } bool CAnsiTerm::ProcessDSR(void) { // Send Device Status Request - Not supported return true; } bool CAnsiTerm::ProcessED(void) { return EraseDisplay((EraseType)m_Parameters[0]); } bool CAnsiTerm::ProcessEL(void) { return EraseLine((EraseType)m_Parameters[0]); } bool CAnsiTerm::ProcessHTS(void) { // Soft Tab Set - Not implemented yet return true; } bool CAnsiTerm::ProcessHVP(void) { assert(m_ParameterCount >= 1); if (m_Parameters[0] > 0) { m_Parameters[0]--; } if (m_ParameterCount < 2) { m_Parameters[1] = 0; } else { if (m_Parameters[1] > 0) { m_Parameters[1]--; } } if (m_bOriginMode) { if (m_Parameters[0] >= (m_sBottomMargin - m_sTopMargin + 1)) { m_Parameters[0] = m_sBottomMargin - m_sTopMargin; } } else { if (m_Parameters[0] >= m_WindowSize.Y) { m_Parameters[0] = m_WindowSize.Y - 1; } } if (m_Parameters[1] >= m_WindowSize.X) { m_Parameters[1] = m_WindowSize.X - 1; } m_Cursor.Y = (SHORT)m_Parameters[0]; m_Cursor.X = (SHORT)m_Parameters[1]; return SetCursorPosition(); } bool CAnsiTerm::ProcessIND(void) { return ProcessLinefeed(false); } bool CAnsiTerm::ProcessNEL(void) { return ProcessLinefeed(true); } bool CAnsiTerm::ProcessRCP(void) { m_Cursor = m_SavedCursor; return SetCursorPosition(); } bool CAnsiTerm::ProcessRI(void) { return ProcessReverseLinefeed(); } bool CAnsiTerm::ProcessRIS(void) { return ResetTerm(); } bool CAnsiTerm::ProcessRM(void) { bool bret = true; if (m_bPrivateParameters) { for (int index = 0; index < m_ParameterCount; index++) { switch (m_Parameters[index]) { case 0: default: dbglog("ProcessRM: illegal private param %d\n",m_Parameters[index]); bret = false; break; case DECCKM: m_bCursorKeyMode = false; break; case DECANM: m_bAnsiMode = false; break; case DECCOLM: m_bColumnMode = false; break; case DECSCLM: m_bScrollingMode = false; break; case DECSCNM: m_bScreenMode = false; break; case DECOM: m_bOriginMode = false; m_Cursor.X = 0; m_Cursor.Y = 0; SetCursorPosition(); break; case DECAWM: m_bAutoWrapMode = false; break; case DECARM: m_bAutoRepeatingMode = false; break; case DECINLM: m_bInterlaceMode = false; break; case DECTCEM: m_bDisplayCursor = false; DisplayCursor(); break; } } } else { for (int index = 0; index < m_ParameterCount; index++) { switch (m_Parameters[index]) { case 20: m_bLineFeedNewLineMode = false; break; // LNM default: dbglog("ProcessRM: illegal public param %d\n",m_Parameters[index]); bret = false; break; } } } return bret; } bool CAnsiTerm::ProcessSCP(void) { m_SavedCursor = m_Cursor; return true; } bool CAnsiTerm::ProcessSCSG0(char ch) { switch (ch) { case 'B': // ASCII Charset m_G0Charset = AsciiCharset; break; case '0': // Special Graphics Charset m_G0Charset = SpecialGraphicsCharset; break; case 'A': // UK Charset case '1': // Alternate Character ROM Standard Charset case '2': // Alternate Character ROM Special Graphics Charset default: // Unsupported return false; } return true; } bool CAnsiTerm::ProcessSCSG1(char ch) { switch (ch) { case 'B': // ASCII Charset m_G1Charset = AsciiCharset; break; case '0': // Special Graphics Charset m_G1Charset = SpecialGraphicsCharset; break; case 'A': // UK Charset case '1': // Alternate Character ROM Standard Charset case '2': // Alternate Character ROM Special Graphics Charset default: // Unsupported return false; } return true; } bool CAnsiTerm::ProcessSGR(void) { for (int index = 0; index < m_ParameterCount; index++) { switch (m_Parameters[index]) { case 0: m_Attribute = kDefaultAttribute; break; case 1: m_Attribute |= FOREGROUND_INTENSITY; break; case 4: m_Attribute |= COMMON_LVB_UNDERSCORE; break; case 5: // Blinking isn't supported break; case 7: m_Attribute |= COMMON_LVB_REVERSE_VIDEO; break; case 22: m_Attribute &= ~FOREGROUND_INTENSITY; break; case 24: m_Attribute &= ~COMMON_LVB_UNDERSCORE; break; case 25: // Blinking isn't supported break; case 27: m_Attribute &= ~COMMON_LVB_REVERSE_VIDEO; break; case 30: // Black text m_Attribute &= ~(FOREGROUND_INTENSITY | COMMON_LVB_UNDERSCORE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); break; case 31: // Red text m_Attribute &= ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); m_Attribute |= FOREGROUND_RED; break; case 32: // Green text m_Attribute &= ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); m_Attribute |= FOREGROUND_GREEN; break; case 33: // Yellow text m_Attribute &= ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); m_Attribute |= FOREGROUND_RED | FOREGROUND_GREEN; break; case 34: // Blue text m_Attribute &= ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); m_Attribute |= FOREGROUND_BLUE; break; case 35: // Magenta text m_Attribute &= ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); m_Attribute |= FOREGROUND_RED | FOREGROUND_BLUE; break; case 36: // Cyan text m_Attribute &= ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); m_Attribute |= FOREGROUND_GREEN | FOREGROUND_BLUE; break; case 37: // White text m_Attribute |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break; case 40: // Black background m_Attribute &= ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); break; case 41: // Red background m_Attribute &= ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); m_Attribute |= BACKGROUND_RED; break; case 42: // Green background m_Attribute &= ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); m_Attribute |= BACKGROUND_GREEN; break; case 43: // Yellow background m_Attribute &= ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); m_Attribute |= BACKGROUND_RED | BACKGROUND_GREEN; break; case 44: // Blue background m_Attribute &= ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); m_Attribute |= BACKGROUND_BLUE; break; case 45: // Magenta background m_Attribute &= ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); m_Attribute |= BACKGROUND_RED | BACKGROUND_BLUE; break; case 46: // Cyan background m_Attribute &= ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); m_Attribute |= BACKGROUND_GREEN | BACKGROUND_BLUE; break; case 47: // White background m_Attribute |= BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE; break; default: dbglog("ERROR: bad SGR param %d (0x%02x)\n",index,index); m_Attribute = kDefaultAttribute; break; } } UpdateTextAttribute(); return true; } bool CAnsiTerm::ProcessSM(void) { dbglog("ProcessSM: start, priv=%d param0=%d cnt=%d\n", m_bPrivateParameters,m_Parameters[0],m_ParameterCount); if (m_bPrivateParameters) { for (int index = 0; index < m_ParameterCount; index++) { switch (m_Parameters[0]) { case 0: default: dbglog("ERROR: bad private SM param %d\n",m_Parameters[0]); assert(false); break; case DECCKM: m_bCursorKeyMode = true; break; case DECANM: m_bAnsiMode = true; break; case DECCOLM: m_bColumnMode = true; break; case DECSCLM: m_bScrollingMode = true; break; case DECSCNM: m_bScreenMode = true; break; case DECOM: m_bOriginMode = true; m_Cursor.X = 0; m_Cursor.Y = 0; m_SavedCursor = m_Cursor; SetCursorPosition(); break; case DECAWM: m_bAutoWrapMode = true; break; case DECARM: m_bAutoRepeatingMode = true; break; case DECINLM: m_bInterlaceMode = true; break; case DECTCEM: m_bDisplayCursor = true; DisplayCursor(); break; } } } else { for (int index = 0; index < m_ParameterCount; index++) { switch (m_Parameters[0]) { case 20: m_bLineFeedNewLineMode = true; break; // LNM default: dbglog("ProcessSM: param %d != 20\n",m_Parameters[0]); assert(false); break; } } } return true; } bool CAnsiTerm::ProcessTBC(void) { // Soft Tab Clear - Not implemented yet return true; } static CAnsiTerm *g_pDisplay; typedef unsigned char uchar; extern "C" { void console_open(char fdebugcmd) { g_pDisplay = new CAnsiTerm(); } void console_close(void) { delete g_pDisplay; g_pDisplay = NULL; } int console_in(DWORD keydata, uchar *pdata, int len) { if (keydata == ~0) { g_pDisplay->WindowSizeChanged(false); return 0; } return g_pDisplay->ProcessInput(*(CAnsiTerm::KeyCode *)&keydata, pdata, len); } void console_out(uchar *pdata, int len) { if (len > 0) { g_pDisplay->ProcessOutput(pdata, len); } } } ipmiutil-3.1.5/util/iwdt.c0000644000076400007640000003323413566765324015553 0ustar mgportalloggers/* * wdt.c * * This tool reads and enables the watchdog timer via IPMI. * Note that there are other methods for doing this, and the * standard interface is for the driver to expose a /dev/watchdog * device interface. * WARNING: If you enable the watchdog, make sure you have something * set up to keep resetting the timer at regular intervals, or it * will reset your system. * The Intel Server Management software does this automatically, * and also continues to reset the timer as long as it is running. * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2003-2006 Intel Corporation. * Copyright (c) 2009 Kontron America, Inc. * * 02/25/03 Andy Cress - created * 03/05/03 Andy Cress - added -d option to disable watchdog timer * 06/11/03 Andy Cress - new ver 1.2 for EMSGSIZE fix * 10/28/03 Andy Cress - fixed cc error in set_wdt (idata size), * show action. * 02/06/04 Andy Cress - added WIN32 flags * 03/11/04 Andy Cress - 1.4 fixed cc=0xcc if pretimeout not zero. * 05/05/04 Andy Cress - 1.5 call ipmi_close before exit * 11/01/04 Andy Cress - 1.6 add -N / -R for remote nodes * 11/16/04 Andy Cress - 1.7 add -U for remote username * 12/02/04 Andy Cress - 1.8 add counter & pretimeout display in show_wdt * added EFI ifdefs * 04/13/06 Andy Cress - 1.9 fix -t if nsec > 255 * 06/22/06 Andy Cress - 1.10 add -a action and -l dontlog options * 06/25/08 Andy Cress - 2.13 add -p for pre-timeout action */ /*M* Copyright (c) 2006, Intel Corporation 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 Corporation 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*/ #ifdef WIN32 #include #include #include #include "getopt.h" #elif defined(EFI) // EFI: defined (EFI32) || defined (EFI64) || defined(EFIX64) #ifndef NULL #define NULL 0 #endif #include #include #include #include #elif defined(DOS) #include #include #include #include #include "getopt.h" #else /* Linux, Solaris, BSD */ #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include #include "ipmicmd.h" /* * Global variables */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil wdt"; #else static char * progver = "3.08"; static char * progname = "iwdt"; #endif static char fdebug = 0; static char fdontlog = 0; static char fcanonical = 0; static char bdelim = BDELIM; /* '|' */ static uchar action = 1; /* default is Hard Reset */ /* 0 = "No action" * 1 = "Hard Reset" * 2 = "Power down" * 3 = "Power cycle" */ static uchar preaction = 0; /* default is None */ /* 1 = "SMI " * 2 = "NMI " * 3 = "Messaging Interrupt" */ static uchar pretime = 0; /* usually 30 second default pre-timeout */ static uchar ipmi_maj = 0; static uchar ipmi_min = 0; static int reset_wdt(void) { uchar idata[4]; uchar rdata[16]; int rlen = 4; uchar ccode; int ret; ret = ipmi_cmd(WATCHDOG_RESET, idata, 0, rdata, &rlen, &ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; return(ret); } static int get_wdt(uchar *rdata, int rlen) { uchar idata[4]; uchar ccode; int ret; ret = ipmi_cmd(WATCHDOG_GET, idata, 0, rdata, &rlen, &ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; return(ret); } /*end get_wdt()*/ static int set_wdt(int val) { uchar idata[6]; uchar rdata[16]; int rlen = 8; uchar ccode, bl; int ret, t; t = val * 10; /* val is in sec, make timeout in 100msec */ if (fdontlog) bl = 0x80; else bl = 0x00; if ((ipmi_maj > 1) || /* IPMI 1.5 or greater */ (ipmi_maj == 1 && ipmi_min >= 5)) { idata[0] = 0x44 | bl; /* DontLog=0, DontStop=1 & use SMS/OS */ } else idata[0] = 0x04 | bl; /* IPMI 1.0 or less */ idata[1] = (preaction << 4) | action; /* preaction/action */ idata[2] = 0; /* pretimeout: 0=disabled, or less than timeout */ if (preaction != 0) { /* enabled pretimeout */ idata[2] = pretime; /* pretimeout value in seconds */ } /*endif preaction/pretime */ idata[3] = 0x10; /* clear SMS/OS when done */ idata[4] = t & 0x00ff; /*timeout in 100msec: 0x4B0 = 1200. */ idata[5] = (t & 0xff00) >> 8; ret = ipmi_cmd(WATCHDOG_SET, idata, 6, rdata, &rlen, &ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; return(ret); } /*end set_wdt()*/ static int clear_wdt(void) { uchar idata[6]; uchar rdata[16]; int rlen = 8; uchar ccode = 0; int ret; idata[0] = 0x01; /* Use FRB2, stop timer */ idata[1] = 0x00; /* no action */ idata[2] = 30; /* pretimeout: 30 sec (disabled anyway) */ idata[3] = 0x02; /* clear FRB2*/ idata[4] = 0xB0; idata[5] = 0x04; ret = ipmi_cmd(WATCHDOG_SET, idata, 6, rdata, &rlen, &ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; return(ret); } /*end clear_wdt()*/ char *usedesc[6] = {"reserved", "BIOS FRB2", "BIOS/POST", "OS Load", "SMS/OS", "OEM" }; void show_wdt(uchar *wdt) { uchar use; char *pstr; char *pstr2; int i,j; if (!fcanonical) { printf("wdt data: "); for (i=0; i<8; i++) printf("%02x ",wdt[i]); printf("\n"); } use = wdt[0] & 0x07; if (use > 5) use = 0; if ((wdt[0] & 0x40) == 0x40) pstr = "started"; else pstr = "stopped"; if ((wdt[0] & 0x80) == 0x80) pstr2 = "DontLog"; else pstr2 = "Logging"; if (fcanonical) { printf("Watchdog timer state\t%c %s\n",bdelim,pstr); printf(" Use with \t\t%c %s\n", bdelim,usedesc[use]); printf(" Log mode \t\t%c %s\n", bdelim,pstr2); } else { printf("Watchdog timer is %s for use with %s. %s\n",pstr,usedesc[use],pstr2); } switch (wdt[1] & 0x70) { case 0x10: pstr = "SMI"; break; case 0x20: pstr = "NMI"; break; case 0x30: pstr = "MsgInt"; break; default: pstr = "None"; } if (fcanonical) { printf(" Pretimeout\t\t%c %d seconds\n", bdelim,wdt[2]); printf(" Pre-action\t\t%c %s\n", bdelim,pstr); } else { printf(" pretimeout is %d seconds, pre-action is %s\n", wdt[2],pstr); } /* wdt[3] is the TimerUseExpFlags */ i = (wdt[4] + (wdt[5] << 8)) / 10; j = (wdt[6] + (wdt[7] << 8)) / 10; if (fcanonical) { printf(" Timeout \t\t%c %d seconds\n", bdelim,i); printf(" Counter \t\t%c %d seconds\n", bdelim,j); } else { printf(" timeout is %d seconds, counter is %d seconds\n",i,j); } switch (wdt[1] & 0x07) { case 0: pstr = "No action"; break; case 1: pstr = "Hard Reset"; break; case 2: pstr = "Power down"; break; case 3: pstr = "Power cycle"; break; default: pstr = "Reserved"; } if (fcanonical) { printf(" Action \t\t%c %s\n", bdelim,pstr); } else { printf(" action is %s\n",pstr); } } #ifdef METACOMMAND int i_wdt(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int ret = 0; int rv = 0; int c; uchar freadonly = 1; uchar freset = 0; uchar fdisable = 0; uchar wdtbuf[8]; uchar devrec[16]; int t = 0; int a; #if defined (EFI) InitializeLib(_LIBC_EFIImageHandle, _LIBC_EFISystemTable); #else printf("%s ver %s\n", progname,progver); #endif parse_lan_options('V',"4",0); /*default to admin priv*/ while ((c = getopt(argc,argv,"cdelra:p:q:t:T:V:J:EYF:P:N:R:U:Z:x?")) != EOF ) switch(c) { case 'r': freset = 1; break; /* reset watchdog timer */ case 'l': fdontlog = 1; break; /* dont log the wdt events */ case 'a': a = atoi(optarg); /* set wd action */ if (a >= 0 && a < 4) action = (uchar)a; freadonly = 0; break; case 'p': a = atoi(optarg); /* set wd preaction */ if (a >= 0 && a < 4) preaction = (uchar)a; freadonly = 0; break; case 'q': a = atoi(optarg); /* set wd pretimeout */ if (a > 255) pretime = 255; else if (a >= 5) pretime = (uchar)a; /* else arg is out of bounds */ freadonly = 0; break; case 'c': fcanonical = 1; break; /* canonical output */ case 'd': fdisable = 1; break; /* disable wdt */ case 'e': freadonly = 0; break; /* enable wdt */ case 't': t = atoi(optarg); freadonly = 0; break; /*timeout*/ case 'x': fdebug = 1; break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: printf("Usage: %s [-acdelpqrx -t sec -NUPRETVF]\n", progname); printf(" where -r reset watchdog timer\n"); printf(" -a N set watchdog Action (N=0,1,2,3)\n"); printf(" -c canonical output format\n"); printf(" -d disable watchdog timer\n"); printf(" -e enable watchdog timer\n"); printf(" -l don't Log watchdog events\n"); printf(" -p N set watchdog Preaction (N=0,1,2,3)\n"); printf(" -q N set watchdog pretimeout to N sec\n"); printf(" -t N set timeout to N seconds\n"); printf(" -x show eXtra debug messages\n"); print_lan_opt_usage(0); ret = ERR_USAGE; goto do_exit; } if (t == 0) t = 120; /* default timeout, 120 seconds*/ if ((pretime != 0) && (preaction == 0)) preaction = 2; /*default is NMI*/ if (preaction != 0) { if (pretime == 0) { if (t >= 280) { pretime = 255; } else { a = t * 10; /* t is in sec, make timeout(a) in 100msec */ pretime = (a - t)/10; /*90% of timeout, in seconds*/ } } if ((t - pretime) < 5) { /*if not enough difference*/ /* (timeout - pretimeout) must be >= 5 sec */ /* if val < 50 sec, 10% diff < 5 */ if (t < 20) pretime = 0; /* not enough headroom */ else pretime = t - 5; } } ret = ipmi_getdeviceid(devrec,16,fdebug); if (ret != 0) { goto do_exit; } else { ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; #ifndef EFI show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); #endif } ret = get_wdt(&wdtbuf[0],8); if (ret != 0) { printf("get_wdt error: ret = %x\n",ret); goto do_exit; } show_wdt(wdtbuf); if (fdisable) { printf("Disabling watchdog timer ...\n"); ret = clear_wdt(); if (ret != 0) printf("clear_wdt error: ret = %x\n",ret); ret = get_wdt(wdtbuf,8); show_wdt(wdtbuf); } else if (!freadonly) { printf("Setting watchdog timer to %d seconds ...\n",t); ret = set_wdt(t); if (ret != 0) printf("set_wdt error: ret = %x\n",ret); rv = get_wdt(wdtbuf,8); show_wdt(wdtbuf); /* * If we set the wd timer, we need to set up a cron job, daemon, * or script to reset the timer also. (e.g.: "sleep 1; wdt -r") */ } if (freset && !fdisable) { printf("Resetting watchdog timer ...\n"); ret = reset_wdt(); if (ret == 0xC0) /*node busy*/ printf("Node busy: set the timeout longer.\n"); #ifndef EFI printf("reset_wdt: ret = %d\n",ret); rv = get_wdt(wdtbuf,8); show_wdt(wdtbuf); #endif } #ifndef EFI printf("\n"); #endif do_exit: ipmi_close_(); // show_outcome(progname,ret); return (ret); } /* end main()*/ /* end wdt.c */ ipmiutil-3.1.5/util/oem_asus.c0000644000076400007640000002062713566765324016421 0ustar mgportalloggers/* * oem_asus.c * Handle ASUS OEM command functions * * Author: Andy Cress arcress at users.sourceforge.net * Change history: * 01/23/2017 ARCress - created * *--------------------------------------------------------------------- */ /*M* Copyright (c) 2016 Andy Cress All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of the copyright holder nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ #ifdef WIN32 #include #include "getopt.h" #else #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #include #else #include #endif #endif #include #include #include #include #include "ipmicmd.h" #include "ievents.h" extern uchar bitnum(ushort value); /*isensor.c*/ extern char fdebug; /*ipmicmd.c*/ void set_loglevel(int level); /*prototype */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil asusoem"; #else static char * progver = "3.08"; static char * progname = "iasusoem"; #endif static int verbose = 0; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static int vend_id = 0; static int prod_id = 0; /* * decode_sensor_asus * inputs: * sdr = the SDR buffer * reading = the 3 or 4 bytes of data from GetSensorReading * pstring = points to the output string buffer * slen = size of the output buffer * outputs: * rv = 0 if this sensor was successfully interpreted here, * non-zero otherwise, to use default interpretations. * pstring = contains the sensor reading interpretation string (if rv==0) */ int decode_sensor_asus(uchar *sdr,uchar *reading,char *pstring, int slen) { int rv = -1; uchar stype, etype, entity; uchar bval; ushort rval; char *pstr = NULL; int b; if (sdr == NULL || reading == NULL) return(rv); if (pstring == NULL || slen == 0) return(rv); /* sdr[3] is 0x01 for Full, 0x02 for Compact */ bval = reading[2]; if (sdr[3] == 0x01) return(rv); /*skip if full sensor*/ entity = sdr[8]; stype = sdr[12]; etype = sdr[13]; rval = reading[2] | ((reading[3] & 0x7f) << 8); b = bitnum(rval); if (fdebug) printf("oem_asus: sensor type=%x evt=%x entity=%x rval=%04x\n", stype,etype,entity,rval); switch(stype) { case 0xC5: /* OEM for Memory_Train_Err */ if (etype == 0x6F) { switch(bval) { case 0x00: pstr = "OK"; break; default: pstr = "Error"; break; } snprintf(pstring,slen,"%s",pstr); rv = 0; } break; default: break; } return(rv); } /* * decode_sel_asus * inputs: * evt = the 16-byte IPMI SEL event * outbuf = points to the output string buffer * outsz = size of the output buffer * outputs: * rv = 0 if this event was successfully interpreted here, * non-zero otherwise, to use default interpretations. * outbuf = will contain the interpreted event text string (if rv==0) */ int decode_sel_asus(uchar *evt, char *outbuf, int outsz, char fdesc, char fdbg) { int rv = -1; ushort id; uchar rectype; ulong timestamp; char mybuf[64]; char *type_str = ""; char *pstr = NULL; int sevid; ushort genid; uchar snum; uchar data1, data2, data3; fdebug = fdbg; sevid = SEV_INFO; id = evt[0] + (evt[1] << 8); rectype = evt[2]; snum = evt[11]; timestamp = evt[3] + (evt[4] << 8) + (evt[5] << 16) + (evt[6] << 24); genid = evt[7] | (evt[8] << 8); data1 = evt[13]; data2 = evt[14]; data3 = evt[15]; if (rectype == 0x02) { sprintf(mybuf,"%02x [%02x %02x %02x]", evt[12],data1,data2,data3); switch(evt[10]) { /*sensor type*/ case 0xC0: /* OEM type */ type_str = "OEM_type"; pstr = "OEM Sensor "; sevid = SEV_MAJ; rv = -1; break; default: /*other sensor types*/ break; } } if (rv == 0) { format_event(id,timestamp, sevid, genid, type_str, snum,NULL,pstr,mybuf,outbuf,outsz); } return(rv); } static void usage(void) { printf("Usage: %s [arg]\n",progname); printf("These commands may not work on all Lenovo systems\n"); } static int ipmi_oemasus_main(int argc, char **argv) { int rv = 0; if (strncmp(argv[0],"other",9) == 0) { usage(); rv = ERR_USAGE; } else { usage(); rv = ERR_USAGE; } return(rv); } #ifdef METACOMMAND int i_oemasus(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int rv = 0; uchar devrec[16]; int c, i; char *s1; printf("%s ver %s\n", progname,progver); set_loglevel(LOG_NOTICE); parse_lan_options('V',"4",0); /*default to admin priv*/ while ( (c = getopt( argc, argv,"m:xzEF:J:N:P:R:T:U:V:YZ:?")) != EOF ) switch(c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'x': fdebug = 2; /* normal (dbglog if isol) */ verbose = 1; break; case 'z': fdebug = 3; /*full debug (for isol)*/ verbose = 1; break; case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: usage(); return(ERR_USAGE); break; } for (i = 0; i < optind; i++) { argv++; argc--; } if (argc == 0) { usage(); return(ERR_USAGE); } rv = ipmi_getdeviceid(devrec,16,fdebug); if (rv == 0) { char ipmi_maj, ipmi_min; ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16); prod_id = devrec[9] + (devrec[10] << 8); show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); } rv = ipmi_oemasus_main(argc, argv); ipmi_close_(); return(rv); } /* end oem_asus.c */ ipmiutil-3.1.5/util/isel.c0000644000076400007640000007545213566765324015550 0ustar mgportalloggers/* * isel.c (was showsel.c) * * This tool reads the firmware System Event Log records via IPMI commands. * It can use either the Intel /dev/imb driver or VALinux /dev/ipmikcs. * * Author: Andy Cress arcress at users.sourceforge.net * * Copyright (c) 2001-2005 Intel Corporation. * Copyright (c) 2009 Kontron America, Inc. * Copyright (c) 2013 Andy Cress * * 10/16/01 Andy Cress - created * 10/19/01 Andy Cress - added text for Sensor Types from Table 36-3 * 10/24/01 Andy Cress - added panic string display for OS Crit Stop * 11/01/01 Andy Cress - added logic to write SEL records to syslog * 11/15/01 Andy Cress - added logic for more description strings * 01/31/02 Andy Cress - isolated dependencies on /dev/imb to ipmi_cmd_ia(), * added ipmi_cmd_va() for va ipmi driver also, * added posterrs array for more descriptions. * 02/06/02 Andy Cress - fixed bug 279 (extra debug msg at EOF). * 03/25/02 Andy Cress - show free space, add -c to clear SEL. * 04/11/02 Andy Cress - decode timestamp into readable form * 06/14/02 Andy Cress - also show status error in ClearSEL * 07/02/02 Andy Cress v1.3 add more Usage text * 08/02/02 Andy Cress v1.4 moved common ipmi_cmd() code to ipmicmd.c * 10/07/02 Andy Cress v1.5 added -v option with BMC version too * 01/16/03 Andy Cress v1.6 Handle new OS crit stop format with die code * 01/29/03 Andy Cress v1.7 added MV OpenIPMI support * 02/05/03 Andy Cress v1.8 show better message if empty SEL (cc=0xCB), * show an additional warning if free space is low. * 02/18/03 Andy Cress v1.9 trim out some fields so it fits on 1 line, * decode Boot Event subcodes * 02/27/03 Andy Cress v1.10 change OS Crit Stop decoding to handle new types * 03/20/03 Andy Cress v1.11 for -w, save id also, so we don't have to start * over at the beginning each time. * 04/30/03 Andy Cress v1.12 changed display ordering. * 06/23/03 Andy Cress v1.13 fix -w if log gets cleared * 08/19/03 Andy Cress v1.14 handle OEM/other record types * 09/16/03 Andy Cress v1.15 added more sens_desc strings * 10/03/03 Andy Cress v1.16 added more sens_desc strings (for boot) * 01/19/04 Andy Cress v1.17 added more sens_desc for Fans * 01/30/04 Andy Cress v1.18 added WIN32 flags, and sens_desc for Voltage * 03/12/04 Andy Cress v1.19 ClockSync description changed * 03/29/04 Andy Cress v1.20 change pattern matching for thresholds, * added sens_desc for ID Button * check either time or record_id if fwritesel * show warning if <20% free also * added sens_desc for System Events, HSC, Power, Int * 04/13/04 Andy Cress v1.21 added threshold OK descriptions, * change header (time is local, not GMT) * 05/05/04 Andy Cress v1.22 call ipmi_close before exit, * include ReportEvent code for WIN32 * 06/10/04 Andy Cress v1.23 use gmtime instead of localtime for WIN32 * 08/16/04 Andy Cress v1.24 added more decoding for Power events * 09/20/04 Andy Cress v1.25 added 2 event descriptors for ia64 platforms * 11/01/04 Andy Cress v1.26 add -N / -R for remote nodes * 11/16/04 Andy Cress v1.27 add -U for username, * added more decoding for mBMC watchdog events * 11/19/04 Andy Cress v1.28 added more decoding for crit_int, slots, etc. * changed firmware error decoding. * 02/17/05 Andy Cress v1.29 made decode_sel_entry() a subroutine, * added logic for OEM 0xc0 record types. * 05/24/05 Andy Cress v1.30 fixed SegFault with StartWriting/fscanf * 05/26/05 Andy Cress v1.31 moved decode_sel_entry to events.c * 08/01/05 Andy Cress v1.32 updated events.c for PowerUnit & Battery * 09/12/05 Andy Cress v1.33 dont check superuser for fipmi_lan * 06/29/06 Andy Cress v1.34 added -l option * 02/06/08 Andy Cress v2.8 make sure savid for -w is unsigned */ /*M* Copyright (c) 2002-2005, Intel Corporation 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 Corporation 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 #ifdef WIN32 #include #include #include #include "getopt.h" #elif defined(DOS) #include #include #include #include "getopt.h" #else #include #include #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include #include "ipmicmd.h" #define SELprintf printf #define ETYPE_CRITSTOP 0x20 #define RTYPE_OEM2 0xe0 /* 2nd OEM type (range) */ #pragma pack(1) typedef struct { ushort record_id; uchar record_type; uint timestamp; ushort generator_id; /*slave_addr/channel*/ uchar evm_rev; //event message revision uchar sensor_type; uchar sensor_number; uchar event_trigger; uchar event_data1; uchar event_data2; uchar event_data3; } SEL_RECORD; #pragma pack() #define MIN_FREE 128 /*=8*16, minimal bytes of free SEL space */ #define REC_SIZE 16 /*SEL Record Size, see IPMI 1.5 Table 26-1 */ #define RECORD_BASE 2 //base value to the SEL record in IMB resp data #define RID_OFFSET 0 //byte offset to the record id #define RTYPE_OFFSET 2 //byte offset to the record type #define RTS_OFFSET 3 //byte offset to the record timestamp #define RGID_OFFSET 7 //byte offset to the record generator id #define REREV_OFFSET 9 //byte offset to the record event message rev #define RSTYPE_OFFSET 10 //byte offset to the record sensor type #define RSN_OFFSET 11 //byte offset to the record sensor number #define RET_OFFSET 12 //byte offset to the record event trigger #define RDATA_OFFSET 13 //byte offset to the record event data #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil sel"; #else static char * progver = "3.08"; static char * progname = "isel"; #endif #ifdef WIN32 #define IDXFILE "sel.idx" static char idxfile[80] = IDXFILE; static char idxfile2[80] = "%ipmiutildir%\\sel.idx"; #else static char idxfile[80] = "/var/lib/ipmiutil/sel.idx"; static char idxfile2[80] = "/usr/share/ipmiutil/sel.idx"; /*old location*/ #endif static char fdebug = 0; static char fall = 1; static char futc = 0; static char fwritesel = 0; static char fshowraw = 0; static char fdecoderaw = 0; static char fdecodebin = 0; static char fclearsel = 0; static char faddsel = 0; static char fonlyver = 0; static char flastrecs = 0; static char fremote = 0; static char fsensdesc = 0; static char fcanonical = 0; static char fset_mc = 0; static uchar min_sev = 0; /*only show sev >= this value [0,1,2,3]*/ static char *addstr = NULL; static char *addhex = NULL; static uint savtime = 0; static ushort savid = 0; static int nlast = 20; static ushort idinc = REC_SIZE; static char *rawfile = NULL; static int vend_id, prod_id; static uchar *sdrs = NULL; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; /*------------------------------------------------------------------------ * decode_sel_entry * Parse and decode the SEL record into readable format. * See ievents.c *------------------------------------------------------------------------*/ extern char *evt_hdr; extern char *evt_hdr2; extern int decode_sel_entry( uchar *psel, char *outbuf, int sz); extern int decode_raw_sel( char *raw_file, int mode); extern void set_sel_opts(int sensdsc, int canon, void *sdrs, char fdbg, char u); extern int get_sdr_cache( uchar **sdrs); extern void free_sdr_cache( uchar *sdrs); extern uchar find_msg_sev(char *msgbuf); /* subs.c*/ extern int OpenSyslog(char *tag); /*see subs.c*/ extern void CloseSyslog(void); /*see subs.c*/ extern void WriteSyslog(char *msgbuf); /*see subs.c*/ extern int write_syslog(char *msg); /*see subs.c*/ /*F* //////////////////////////////////////////////////////////////////////////////// // GetSelEntry //////////////////////////////////////////////////////////////////////////////// // Name : GetSelEntry // // Purpose : This routine gets the next SEL record // // Parameters : // pRecordID : input/output pointer to next Record ID // selRecord : output pointer to the sel record // // Returns : 0 if success // -1 if last record. // -2 if completion code error. // -3 if null buffer on input. // -4 if record id mismatch. // // Notes : uses ipmi_cmd() // *F*/ int GetSelEntry(ushort *pRecordID, SEL_RECORD *selRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar inputData[6]; uchar completionCode; char* cpRecordID; //for next record id ushort inRecordID; //save the input record id inRecordID = *pRecordID; if (!selRecord) { if (fdebug) SELprintf("GetSelEntry: error, output buffer is NULL\n"); return -3; } //set the reservation id to zero inputData[0] = 0; inputData[1] = 0; //set the record id to get cpRecordID = (char*) pRecordID; inputData[2] = cpRecordID[0]; inputData[3] = cpRecordID[1]; //set the offset to the record to value zero inputData[4] = 0; //set the number of byte to read. 0xFF means read the entire record inputData[5] = (char) 0xFF; status = ipmi_cmd(GET_SEL_ENTRY, inputData, 6, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { if (completionCode == 0xCB && inRecordID == 0) SELprintf("Firmware Log (SEL) is empty\n"); else SELprintf("GetSelEntry[%x]: completion code=%x\n", inRecordID,completionCode); // responseData[0]); } else { //successful, done //save the next SEL record id cpRecordID[0] = responseData[0]; cpRecordID[1] = responseData[1]; //save the SEL record content //(note that selRecord structure must be pragma_pack'd) memcpy(selRecord,&responseData[RECORD_BASE],16); if (inRecordID == 0 || inRecordID == selRecord->record_id) { /* We return success if the input record is begin-of-SEL (value 0), or input and output record id matches. */ return 0; } else { /* If last record, inRecordID will be -1 from response data, so return -1 as normal EOF. (fix to bug 279) */ if (inRecordID == 0xFFFF) return(-1); /* If not last record, this is an error. */ if (fdebug) SELprintf("GetSelEntry: input id %d != output id %d \n", inRecordID, selRecord->record_id); *pRecordID = inRecordID; //restore the input record id return -4; } } } // we are here because after the retry, completionCode is not COMPLETION_CODE_OK if (fdebug) SELprintf("GetSelEntry: ipmi_cmd error %d completion code, code=%d\n", status,completionCode); return -2; } /* end GetSelEntry() */ int AddSelEntry(uchar *selrec, int ilen) { uchar rdata[MAX_BUFFER_SIZE]; int rlen = MAX_BUFFER_SIZE; uchar idata[16]; uchar ccode; int rv; /* Do not use AddSelEntry unless there is a legitimate hardware-related event. */ memset(idata,0,16); if (ilen > 16) ilen = 16; memcpy(idata,selrec,ilen); rv = ipmi_cmdraw(0x44, NETFN_STOR, g_sa, g_bus, g_lun, idata, 16, rdata, &rlen, &ccode, fdebug); return (rv); } int get_sel_time_utc_offset(short *offset) { uchar rdata[MAX_BUFFER_SIZE]; int rlen = MAX_BUFFER_SIZE; uchar idata[16]; uchar ccode; int rv; if (offset == NULL) return(-1); *offset = 0; rv = ipmi_cmdraw(0x5C, NETFN_STOR, g_sa, g_bus, g_lun, idata, 0, rdata, &rlen, &ccode, fdebug); if (rv == 0) rv = ccode; if (rv == 0) *offset = rdata[0] + (rdata[1] << 8); return (rv); } void StartWriting(uint *plasttime, ushort *plastid) { FILE *fd; uint lasttime; uint lastid; int ret = -1; lasttime = 0; lastid = 0; // Open the index file fd = fopen(idxfile,"r"); if (fd == NULL) fd = fopen(idxfile2,"r"); if (fd != NULL) { // Read the file, get savtime & savid ret = fscanf(fd,"%x %x",&lasttime,&lastid); fclose(fd); } else printf("StartWriting: cannot open %s\n",idxfile); if (fdebug) printf("StartWriting: idx fd=%p, savtime=%x, savid=%x\n", fd,lasttime,(ushort)lastid); *plasttime = lasttime; *plastid = (ushort)lastid; ret = OpenSyslog("SEL"); if (fdebug) printf("StartWriting: ret = %d\n",ret); return; } void StopWriting(uint lasttime, ushort lastid) { FILE *fd; // Rewrite the saved time & record id fd = fopen(idxfile,"w"); if (fd != NULL) { fprintf(fd,"%x %x\n",lasttime,lastid); fclose(fd); } else printf("StopWriting: cannot open %s\n",idxfile); CloseSyslog(); return; } int ClearSEL(void) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar inputData[6]; uchar completionCode; ushort cmd; cmd = RESERVE_SEL; /*0x0A42*/ status = ipmi_cmd(cmd, inputData, 0, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK && completionCode == 0) { cmd = CLEAR_SEL; /*0x0A47*/ inputData[0] = responseData[0]; /*Reservation ID [0]*/ inputData[1] = responseData[1]; /*Reservation ID [1]*/ inputData[2] = 'C'; inputData[3] = 'L'; inputData[4] = 'R'; inputData[5] = 0xAA; /* initiate erase */ status = ipmi_cmd(cmd, inputData, 6, responseData, &responseLength, &completionCode, fdebug); /* The reservation is cancelled by the CLEAR_SEL cmd */ } if (status == ACCESS_OK) { if( completionCode ) { SELprintf("ClearSEL: cmd = %x, completion code=%x\n", cmd,completionCode); status = completionCode; } else { /* Successful, done. */ SELprintf("ClearSEL: Log Cleared successfully\n"); } } else { SELprintf("ClearSEL: cmd = %x, error status = %d\n", cmd,status); } if (fwritesel) { /* this won't always be enough, but try */ StartWriting(&savtime,&savid); savid = 0; StopWriting(savtime,savid); } return(status); } /* ClearSEL()*/ void ReadSEL(uchar mytype, char fwriteit) { ushort RecordID = 0; /* 0 = first record, 0xFFFF = end */ SEL_RECORD selRecord; SEL_RECORD *pSelRecord = &selRecord; char output[160]; int rc = 0; int ilast = 0; short recid0; uchar *bsel; uchar sev; char fskipit = 0; if (fwriteit) { StartWriting(&savtime,&savid); RecordID = savid; } memset(pSelRecord, 0, sizeof(SEL_RECORD)); if (flastrecs) { /* read the first two records to get the record id increment */ RecordID = 0; rc = GetSelEntry( &RecordID, pSelRecord); recid0 = pSelRecord->record_id; rc = GetSelEntry( &RecordID, pSelRecord); if (rc == 0) idinc = pSelRecord->record_id - recid0; else { idinc = recid0; rc = 0; } RecordID = 0xFFFF; /* -1=0xFFFF; * get last record */ if (fdebug) printf("recid inc = 0x%02x (%x - %x)\n",idinc, pSelRecord->record_id,recid0); } set_sel_opts(fsensdesc, fcanonical, sdrs, fdebug,futc); if (futc) { /*Try to get the UTC offset*/ short utc_off; printf("Showing SEL Time as UTC\n"); rc = get_sel_time_utc_offset(&utc_off); if (rc == 0) { printf("SEL Time UTC Offset = %d\n",utc_off); } else rc = 0; /*may fail if not supported, but ok*/ } /* show header for the SEL records */ if (fcanonical) printf("%s",evt_hdr2); /*RecId | Date/Time */ else printf("%s",evt_hdr); /*RecId Date/Time_______ */ while( rc == 0 ) { rc = GetSelEntry( &RecordID, pSelRecord); if (fwriteit && (rc != 0) && (RecordID == savid)) { /* If here, log was probably cleared, so try * again from the log start. */ RecordID = 0; rc = GetSelEntry( &RecordID, pSelRecord); } if (fdebug) printf("rc = %d, recid = %04x, next = %04x\n", rc, pSelRecord->record_id, RecordID); if (flastrecs && (ilast == 0) && (rc == -1)) rc = 0; if (rc != 0) { /* EOF or error */ break; } if (fshowraw) { bsel = (uchar *)&selRecord; sprintf(output,"%02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x\n", bsel[0], bsel[1], bsel[2], bsel[3], bsel[4], bsel[5], bsel[6], bsel[7], bsel[8], bsel[9], bsel[10], bsel[11], bsel[12], bsel[13], bsel[14], bsel[15]); printf("%s", output); } else { if (mytype == 0xff || pSelRecord->sensor_type == mytype) { /* show all records, or type matches */ decode_sel_entry((uchar *)pSelRecord,output, sizeof(output)); fskipit = 0; if (min_sev > 0) { sev = find_msg_sev(output); if (fdebug) printf("min_sev=%d, sev=%d\n",min_sev,sev); if (sev < min_sev) fskipit = 1; } if (!fskipit) printf("%s", output); } else if ((mytype == ETYPE_CRITSTOP) && (pSelRecord->record_type >= RTYPE_OEM2)) { /* if showing panics only, also show its oem records */ decode_sel_entry((uchar *)pSelRecord,output,sizeof(output)); printf("%s", output); } else { if (fdebug) printf("decoding error, mytype = %d\n",mytype); output[0] = 0; } } if (fwriteit) { /* Only write newer records to syslog */ if (pSelRecord->record_type == 0x02) { if ((pSelRecord->timestamp > savtime) || (pSelRecord->record_id > savid)) { WriteSyslog(output); savid = pSelRecord->record_id; savtime = pSelRecord->timestamp; } } else { /* no timestamp */ if (pSelRecord->record_id > savid) { WriteSyslog(output); savid = pSelRecord->record_id; } } } /*endif writeit*/ if( pSelRecord->record_id == 0xFFFF ) break; if( RecordID == pSelRecord->record_id ) break; if (flastrecs) { ++ilast; if (fdebug) printf("ilast = %d, next = %x, id = %x\n", ilast,RecordID,pSelRecord->record_id); if (ilast >= nlast) break; RecordID = pSelRecord->record_id - idinc; if (RecordID > pSelRecord->record_id) break; if (RecordID == 0) break; } memset(pSelRecord, 0, sizeof(SEL_RECORD)); } /*endwhile*/ if (fwriteit) StopWriting(savtime,savid); } /* end ReadSEL()*/ static uint vfree = 0; static uint vused = 0; static uint vtotal = 0; static uint vsize = REC_SIZE; static int ReadSELinfo() { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar completionCode; uchar inputData[6]; uchar b; char *strb; status = ipmi_cmd(GET_SEL_INFO, inputData, 0, responseData, &responseLength, &completionCode, fdebug); if (fdebug) printf("GetSelInfo status = %x, cc = %x\n", status,completionCode); if ((status == ACCESS_OK) && (completionCode == 0)) { vfree = responseData[3] + (responseData[4] << 8); // in Bytes vused = responseData[1] + (responseData[2] << 8); // in Entries/Allocation Units vtotal = vused + (vfree/vsize); // vsize from AllocationInfo b = responseData[13]; if (b & 0x80) strb = " overflow"; /*SEL overflow occurred*/ else strb = ""; if (b & 0x1) { // Get SEL Allocation Info supported status = ipmi_cmd(GET_SEL_ALLOCATION_INFO, inputData, 0, responseData, &responseLength, &completionCode, fdebug); if (fdebug) printf("GetSelInfo status = %x, cc = %x\n", status,completionCode); if ((status == ACCESS_OK) && (completionCode == 0)) { vsize = responseData[2] + (responseData[3] << 8); if (vsize == 0) vsize = REC_SIZE; vtotal = responseData[0] + (responseData[1] << 8); } } if (fcanonical) SELprintf("SEL %s Size = %d records (Used=%d, Free=%d)\n", strb, vtotal, vused, vfree/vsize ); else SELprintf("SEL Ver %x Support %02x%s, Size = %d records (Used=%d, Free=%d)\n", responseData[0], b, strb, vtotal, vused, vfree/vsize ); //successful, done return(0); } else { vfree = MIN_FREE * 2; /*sane values to avoid SEL full warning*/ vused = 0; vtotal = vused + (vfree/vsize); return(1); } } /*end ReadSELinfo()*/ #ifdef ALONE #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #else /* METACOMMAND */ int i_sel(int argc, char **argv) #endif { int ret = -1; char DevRecord[16]; int c; char *s1; char *vend_param = NULL; printf("%s version %s\n",progname,progver); while ((c = getopt(argc,argv,"a:b:cdef:h:i:l:m:np:rs:uwvxM:T:V:J:EYF:P:N:U:R:Z:?")) != EOF) switch(c) { case 'a': faddsel = 1; /*undocumented option, to prevent misuse*/ addstr = optarg; /*text string, max 13 bytes, no date*/ break; case 'h': faddsel = 3; /*undocumented option, to prevent misuse*/ addhex = optarg; /*string of 16 hex characters, no spaces*/ break; case 'i': faddsel = 2; /*undocumented option, to prevent misuse*/ addstr = optarg; /*text string, max 9 bytes, with date*/ break; case 'b': fdecodebin = 1; rawfile = optarg; break; case 'd': fclearsel = 1; break; /*delete/clear SEL*/ case 'e': fsensdesc = 1; break; /*extended sensor descriptions*/ case 'f': fdecoderaw = 1; rawfile = optarg; break; case 'l': flastrecs = 1; nlast = atoi(optarg); break; 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 'c': case 'n': fcanonical = 1; /*parse easier, canonical*/ fsensdesc = 1; /*extended sensor descriptions*/ /* Note that this option does not show event data bytes */ break; // case 'p': fall = 0; break; /*crit stop (panic) only*/ case 'r': fshowraw = 1; break; case 's': min_sev = atob(optarg); break; /*show sev >= value*/ case 'u': futc = 1; break; case 'v': fonlyver = 1; break; case 'w': fwritesel = 1; break; case 'x': fdebug = 1; break; case 'M': /* Manufacturing VendorId */ vend_param = optarg; break; case 'p': /* port */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: printf("Usage: %s [-bcdefmnprsuvwx] [-l 5] [-NUPREFTVYZ]\n", progname); printf(" -b interpret Binary file with raw SEL data\n"); printf(" -c Show canonical output with delimiters\n"); printf(" -d Delete, Clears all SEL records\n"); printf(" -e shows Extended sensor description if run locally\n"); printf(" -f interpret File with ascii hex SEL data\n"); printf(" -l5 Show last 5 SEL records (reverse order)\n"); printf(" -r Show uninterpreted raw SEL records in ascii hex\n"); printf(" -n Show nominal/canonical output (same as -c)\n"); //printf(" -p Show only Panic/Critical Stop records\n"); printf(" -s1 Show only Severity >= value (0,1,2,3)\n"); printf(" -u use raw UTC time\n"); printf(" -v Only show version information\n"); printf(" -w Writes new SEL records to syslog\n"); printf(" -x Display extra debug messages\n"); print_lan_opt_usage(1); ret = ERR_USAGE; goto do_exit; } if (fwritesel && flastrecs) { printf("Error: Options -l and -w are incompatible\n"); ret = ERR_BAD_PARAM; goto do_exit; } /* Handle simple decoding options -f, -b */ if (fdecoderaw) { /* -f */ ret = decode_raw_sel(rawfile,1); goto do_exit; } else if (fdecodebin) { /* -b */ ret = decode_raw_sel(rawfile,2); goto do_exit; } // if (fwrite) fall = 1; // would we ever set fwrite without fall?? #ifdef WIN32 fremote = is_remote(); if (fwritesel) { /*resolve path of idxfile*/ char *ipath; ipath = getenv("ipmiutildir"); /*ipmiutil directory path*/ if (ipath != NULL) { if (strlen(ipath)+8 < sizeof(idxfile)) { sprintf(idxfile,"%s\\%s",ipath,"\\",IDXFILE); } } } #elif defined(DOS) fremote = 0; #else /* Linux, BSD, Solaris */ fremote = is_remote(); if (fremote == 0) { //uchar guid[16]; //char gstr[36]; /* only run this as superuser */ ret = geteuid(); if (ret > 1) { printf("Not superuser (%d)\n", ret); /* Show warning, but could be ok if /dev/ipmi0 is accessible */ //ret = ERR_NOT_ALLOWED; //goto do_exit; } } #endif if (fremote) { /*remote, ipmi lan, any OS*/ char *node; node = get_nodename(); strcat(idxfile,"-"); strcat(idxfile,node); strcat(idxfile2,"-"); strcat(idxfile2,node); } #ifdef REMOVABLE else { // if removable media, may need to add uniqueness to local file. ret = get_SystemGuid(guid); if (ret == 0) { sprintf(gstr,"%02X%02X%02X%02X%02X%02X%02X%02X", guid[8], guid[9], guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]); strcat(idxfile,"-"); strcat(idxfile,gstr); strcat(idxfile2,"-"); strcat(idxfile2,gstr); } } #endif if (fremote) { if (faddsel || fclearsel) parse_lan_options('V',"4",0); /*admin priv to clear*/ } if (faddsel) { /* -a, Add a custom SEL record */ /* use this sparingly, only for hardware-related events. */ char buf[16]; int i, len = 0; memset(&buf[0],0,16); if (addstr != NULL) { /*ASCII text string*/ if (faddsel == 1) { /* -a, Add a custom SEL record */ buf[2] = 0xf1; /*use SEL type OEM 0xF1*/ len = strlen_(addstr); if (len > 13) len = 13; if (len <= 0) ret = LAN_ERR_TOO_SHORT; else memcpy(&buf[3],addstr,len); len += 3; } if (faddsel == 2) { /* -i, Add a custom SEL record with date*/ buf[2] = RT_OEMIU; /*use SEL type OEM 0xDB*/ memset(&buf[3],0,4); len = strlen_(addstr); if (len > 9) len = 9; if (len <= 0) ret = LAN_ERR_TOO_SHORT; else memcpy(&buf[7],addstr,len); len += 7; } } if (addhex != NULL) { /*string of hex characters, no spaces*/ len = strlen_(addhex); if (len < 32) ret = LAN_ERR_TOO_SHORT; else { for (i=2; i<16; i++) buf[i] = htoi(&addhex[i*2]); } len = 16; } if (fdebug) { printf("Ready to AddSelEntry: "); for (i=0; i<16; i++) printf("%02x ",buf[i]); printf("\n"); } if (ret == 0) ret = AddSelEntry(buf, len); printf("AddSelEntry ret = %d\n",ret); goto do_exit; } ret = ipmi_getdeviceid( DevRecord, sizeof(DevRecord),fdebug); if (ret == 0) { uchar ipmi_maj, ipmi_min; ipmi_maj = DevRecord[4] & 0x0f; ipmi_min = DevRecord[4] >> 4; show_devid( DevRecord[2], DevRecord[3], ipmi_maj, ipmi_min); prod_id = DevRecord[9] + (DevRecord[10] << 8); vend_id = DevRecord[6] + (DevRecord[7] << 8) + (DevRecord[8] << 16); if (vend_id == VENDOR_INTEL) { if (prod_id == 0x003E) /*Urbanna NSN2U or CG2100*/ set_max_kcs_loops(URNLOOPS); /*longer KCS timeout*/ } } else { goto do_exit; } if (vend_param != NULL) set_iana(atoi(vend_param)); ret = ReadSELinfo(); if (ret == 0 && !fonlyver) { if (fclearsel) { ret = ClearSEL(); } else { if (fsensdesc) { if (fdebug) printf("%s: fetching SDRs ...\n",progname); ret = get_sdr_cache(&sdrs); if (fdebug) printf("%s: get_sdr_cache ret = %d\n",progname,ret); ret = 0; /*if error, keep going anyway*/ } if (fdebug) printf("%s: starting ReadSEL ...\n",progname); if (fall) ReadSEL(0xff,fwritesel); /* show all SEL records */ else ReadSEL(ETYPE_CRITSTOP,fwritesel); /* only show OS Crit Stops*/ /* PEF alerts and other log messages fail if low free space, so show a warning. */ if (vfree < MIN_FREE) { printf("WARNING: free space is very low (=%d), need to clear with -d\n", vfree); } else if ((vfree/vsize) < ((vtotal * 20)/100)) { printf("WARNING: free space is low (=%d), need to clear with -d\n", vfree); } } } do_exit: free_sdr_cache(sdrs); ipmi_close_(); // show_outcome(progname,ret); return(ret); } /* end isel.c */ ipmiutil-3.1.5/util/oem_intel.h0000644000076400007640000000676713566765324016577 0ustar mgportalloggers/* * oem_intel.h * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2010 Kontron America, Inc. * * 09/02/10 Andy Cress - separated from ialaems.c */ /*M* Copyright (c) 2010 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 Kontron 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*/ #define PRIVATE_BUS_ID 0x03 // w Sahalee, the 8574 is on Private Bus 1 #define PRIVATE_BUS_ID5 0x05 // for Intel TIGI2U #define PRIVATE_BUS_ID7 0x07 // for Intel S5000 #define PERIPHERAL_BUS_ID 0x24 // w mBMC, the 8574 is on the Peripheral Bus #define ALARMS_PANEL_WRITE 0x40 #define ALARMS_PANEL_READ 0x41 #define DISK_LED_WRITE 0x44 // only used for Chesnee mBMC #define DISK_LED_READ 0x45 // only used for Chesnee mBMC #define HAS_ALARMS_MASK 0x0001 #define HAS_BMCTAM_MASK 0x0002 #define HAS_ENCL_MASK 0x0004 #define HAS_PICMG_MASK 0x0008 #define HAS_NSC_MASK 0x0010 #define HAS_ROMLEY_MASK 0x0020 #define HAS_GRANTLEY_MASK 0x0040 uchar get_nsc_diskleds(uchar busid); int set_nsc_diskleds(uchar val, uchar busid); void show_nsc_diskleds(uchar val); uchar get_alarms_intel(uchar busid); int set_alarms_intel(uchar val, uchar busid); void show_alarms_intel(uchar val); int check_bmctam_intel(void); int detect_capab_intel(int vend_id,int prod_id, int *cap, int *ndsk,char fdbg); int get_led_status_intel(uchar *pstate); int is_lan2intel(int vend, int prod); int decode_sensor_intel(uchar *sdr,uchar *reading,char *pstring, int slen); int decode_sensor_intel_nm(uchar *sdr,uchar *reading,char *pstring, int slen); void show_oemsdr_intel(uchar *sdr); void show_oemsdr_nm(uchar *sdr); int is_romley(int vend, int prod); int is_thurley(int vend, int prod); int get_enc_leds_intel(uchar *val); int set_enc_leds_intel(uchar val); void show_enc_leds_intel(uchar val, int numd); int lan_failover_intel(uchar func, uchar *mode); int intel_romley_desc(int vend, int prod, char **pdesc); int get_power_restore_delay_intel(int *delay); int get_hsbp_version_intel(uchar *maj, uchar *min); int is_grantley(int vend, int prod); int intel_grantley_desc(int vend, int prod, char **pdesc); /* end oem_intel.h */ ipmiutil-3.1.5/util/ipmilan2.c0000644000076400007640000000374213566765324016320 0ustar mgportalloggers/* * ipmilan2.c * * Interface to call libintf_lanplus from ipmitool to do RMCP+ protocol. * * 01/09/07 Andy Cress - created * 02/22/07 Andy Cress - initialize cipher_suite to 3 (was 0) */ #include #include #include #include #if defined(LINUX) || defined(BSD) #include #endif #undef HAVE_LANPLUS // #define DEBUG 1 #ifndef HAVE_LANPLUS /* No lanplus, so stub these functions returning errors. */ #define uchar unsigned char #define ushort unsigned short #define LAN_ERR_INVPARAM -8 #define LOG_WARN 4 #define LOG_MSG_LENGTH 1024 /*usu. ipmicmd.h*/ int verbose = 0; char fdbglog = 0; void set_loglevel(int level); void lprintf(int level, const char * format, ...); int ipmi_open_lan2(char *node, char *user, char *pswd, int fdebugcmd) { if (fdebugcmd) verbose = 1; return(LAN_ERR_INVPARAM); } int ipmi_close_lan2(char *node) { return(LAN_ERR_INVPARAM); } int ipmi_cmdraw_lan2(char *node, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { return(LAN_ERR_INVPARAM); } int ipmi_cmd_lan2(char *node, ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { return(LAN_ERR_INVPARAM); } int lan2_send_sol( uchar *payload, int len, void *rsp) { return(LAN_ERR_INVPARAM); } int lan2_recv_sol( void *rsp ) { return(LAN_ERR_INVPARAM); } int lan2_keepalive(int type, void *rsp) { return(LAN_ERR_INVPARAM); } void lan2_recv_handler( void *rs ) { return; } void lan2_set_sol_data(int insize, int outsize, int port, void *handler, char esc_char) { return; } int lan2_get_fd(void) { return(1); } void lanplus_set_recvdelay( int delay ) { return; } long lan2_get_latency( void ) { return(1); } int lan2_send_break( void *rsp) { return(LAN_ERR_INVPARAM); } int lan2_send_ctlaltdel( void *rsp) { return(LAN_ERR_INVPARAM); } #else /* else HAVE_LANPLUS is defined */ #endif /* end ipmilan2.c */ ipmiutil-3.1.5/util/Makefile.sample0000644000076400007640000000146413566765324017360 0ustar mgportalloggers# Makefile for ipmi_sample program # TARGETS = ipmi_sample ipmi_sample_evt incl_dir = /usr/include CFLAGS_SAM = -O2 -g -I. -DLINUX LDFLAGS = -lpthread # if building without lanplus, comment out these two lines CFLAGS_SAM += -DHAVE_LANPLUS LDFLAGS += -lcrypto # see /usr/lib/libipmiutil.a LDFLAGS += -lipmiutil all: $(TARGETS) ipmi_sample: ipmi_sample.c $(incl_dir)/ipmicmd.h $(CC) $(CFLAGS_SAM) -c ipmi_sample.c $(CC) -g -O2 -o ipmi_sample ipmi_sample.o $(LDFLAGS) ipmi_sample_evt: ipmi_sample_evt.c isensor.c ievents.c $(CC) $(CFLAGS_SAM) -c ipmi_sample_evt.c $(CC) $(CFLAGS_SAM) -o isensor2.o -c isensor.c $(CC) $(CFLAGS_SAM) -DSENSORS_OK -o ievents2.o -c ievents.c $(CC) -g -O2 -o ipmi_sample_evt ipmi_sample_evt.o isensor2.o ievents2.o $(LDFLAGS) clean-generic: rm -f $(TARGETS) *.o *.tmp ipmiutil-3.1.5/util/ipmiutil.h0000644000076400007640000000552413566765324016446 0ustar mgportalloggers/*********************************************** * ipmiutil.h * * Definitions for ipmiutil.c * ***********************************************/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 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 Corporation 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. *----------------------------------------------------------------------*/ #ifndef IPMIUTIL_H_ #define IPMIUTIL_H_ int i_alarms(int argc, char **argv); int i_health(int argc, char **argv); int i_fru(int argc, char **argv); int i_getevt(int argc, char **argv); int i_reset(int argc, char **argv); int i_cmd(int argc, char **argv); int i_lan(int argc, char **argv); int i_serial(int argc, char **argv); int i_sensor(int argc, char **argv); int i_sel(int argc, char **argv); int i_wdt(int argc, char **argv); int i_sol(int argc, char **argv); int i_discover(int argc, char **argv); int i_config(int argc, char **argv); int i_events(int argc, char **argv); int i_picmg(int argc, char **argv); int i_firewall(int argc, char **argv); int i_fwum(int argc, char **argv); int i_hpm(int argc, char **argv); int i_sunoem(int argc, char **argv); int i_delloem(int argc, char **argv); int i_ekanalyzer(int argc, char **argv); int i_tsol(int argc, char **argv); int i_dcmi(int argc, char **argv); int i_smcoem(int argc, char **argv); int i_user(int argc, char **argv); #endif // IPMIUTIL_H_ ipmiutil-3.1.5/util/ifruset.c0000644000076400007640000015075713566765324016277 0ustar mgportalloggers/* * ifruset (copy of ifru.c with extended FRU writing) * * This tool reads the FRU configuration, and optionally sets the asset * tag field in the FRU data. See IPMI v1.5 spec section 28. * It can use either the Intel /dev/imb driver or VALinux /dev/ipmikcs. * * Author: Andy Cress arcress at users.sourceforge.net * * Copyright (c) 2009 Kontron America, Inc. * * 04/01/10 Andy Cress - created from ifru.c 2.6.1 */ /*M* 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 Kontron 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*/ #ifdef WIN32 #include #include #include #include #include "getopt.h" #elif defined(DOS) #include #include #include #include #include "getopt.h" #else #include #include #include #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include #include "ipmicmd.h" #include "ipicmg.h" // #define OEM_PICMG 12634 extern int get_LastError( void ); /* ipmilan.c */ extern int get_BiosVersion(char *str); extern int get_SystemGuid(uchar *str); extern void fmt_time(time_t etime, char *buf, int bufsz); /*see ievents.c*/ #define FIELD_LEN 24 #define NUM_BOARD_FIELDS 6 #define NUM_PRODUCT_FIELDS 8 #define NUM_CHASSIS_FIELDS 3 #define ERR_LENMAX -7 /*same as LAN_ERR_BADLENGTH */ #define ERR_LENMIN -10 /*same as LAN_ERR_TOO_SHORT */ #define ERR_OTHER -13 /*same as LAN_ERR_OTHER */ #define STRING_DATA_TYPE_BINARY 0x00 #define STRING_DATA_TYPE_BCD_PLUS 0x01 #define STRING_DATA_TYPE_SIX_BIT_ASCII 0x02 #define STRING_DATA_TYPE_LANG_DEPENDENT 0x03 #define FRUCHUNK_SZ 16 #define FRU_END 0xC1 #define FRU_EMPTY_FIELD 0xC0 #define FRU_TYPE_MASK 0xC0 #define FRU_LEN_MASK 0x3F #define IPROD_MANUF 0 #define IPROD_NAME 1 #define IPROD_PART 2 #define IPROD_VERS 3 #define IPROD_SERNUM 4 #define IPROD_ASSET 5 #define IPROD_FRUID 6 #define IPROD_OEM 7 #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char *progname = "ipmiutil fruset"; #else static char * progver = "3.12"; static char *progname = "ifruset"; #endif static char fdebug = 0; static char fpicmg = 0; static char fonlybase = 0; static char fonlyhsc = 0; static char fdevsdrs = 0; static char fshowlen = 0; static char fgetfru = 0; static char fdoanyway = 0; static char fset_mc = 0; static char fcanonical = 0; static char fdump = 0; static char frestore = 0; static int fwritefru = 0; static int prod_id, vend_id = 0; static char bdelim = ':'; static char *binfile = NULL; static uchar bmc_sa = BMC_SA; /*defaults to 0x20*/ static uchar guid[17] = ""; static uchar *frubuf = NULL; static uchar *newdata = NULL; /* new FRU data, including the product area */ /* usually 4*64 + 3 = 259 bytes */ static int sfru = 0; static int chassis_offset = -1; static int chassis_len = 0; static char chassis_name[FIELD_LEN] = {0}; static int product_num = NUM_PRODUCT_FIELDS; typedef struct { int offset; int len; char tag[FIELD_LEN]; } FIELDTYPE; static FIELDTYPE prodarea[NUM_PRODUCT_FIELDS] = { -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0} }; static FIELDTYPE prodnew[NUM_PRODUCT_FIELDS] = { -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0} }; static int maxprod = 0; static int ctype; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = 0; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static uchar g_fruid = 0; /* default to fruid 0 */ static uchar g_frutype = 0; /* g_frutype values (detected), see also FruTypeString * --TAG---- FRU IPMB * Baseboard = 0x0c 0x07 * PowerSply = 0x0a * PowerCage = 0x15 * DIMM = 0x20 * HotSwapCt = 0x0f * ME = 0x2e * Component = * * (all others) */ #define MAX_CTYPE 26 char *ctypes[MAX_CTYPE] = { "", "Other", "Unknown", "Desktop", "Low Profile Desktop", "Pizza Box", "Mini-Tower", "Tower", "Portable", "Laptop", "Notebook", "Handheld", "Docking Station", "All-in-One", "Sub-Notebook", "Space-saving", "Lunch Box", "Main Server Chassis", "Expansion Chassis", "SubChassis", "Bus Expansion Chassis", "Peripheral Chassis", "RAID Chassis", /*0x17=23.*/ "Rack-Mount Chassis", "New24" , "New25"}; /* what about bladed chassies? */ char *ctype_hdr = "Chassis Type "; char *chassis[NUM_CHASSIS_FIELDS] = { "Chassis Part Number ", "Chassis Serial Num ", "Chassis OEM Field " }; char *board[NUM_BOARD_FIELDS] = { "Board Manufacturer ", "Board Product Name ", "Board Serial Number ", "Board Part Number ", "Board FRU File ID ", "Board OEM Field " }; char *product[NUM_PRODUCT_FIELDS] = { "Product Manufacturer", "Product Name ", "Product Part Number ", "Product Version ", "Product Serial Num ", "Product Asset Tag ", "Product FRU File ID ", "Product OEM Field " }; char *asset_hdr = " Asset Tag Length "; #if 0 typedef struct { uchar len :6; uchar type:2; } TYPE_LEN; /*old, assumes lo-hi byte order*/ #else typedef struct { uchar len; uchar type; } TYPE_LEN; #endif void free_fru(void) { if (frubuf != NULL) { free(frubuf); frubuf = NULL; } if (newdata != NULL) { free(newdata); newdata = NULL; } return; } int load_fru(uchar sa, uchar frudev, uchar frutype) { int ret = 0; uchar indata[FRUCHUNK_SZ]; uchar resp[18]; int sresp; uchar cc; int sz; char fwords; ushort fruoff = 0; int i; int chunk; memset(indata, 0, sizeof(indata)); indata[0] = frudev; sresp = sizeof(resp); if (fdebug) printf("load_fru: sa = %02x, frudev = %02x\n",sa,frudev); ret = ipmi_cmd_mc(GET_FRU_INV_AREA,indata,1,resp,&sresp,&cc,fdebug); if (fdebug) printf("load_fru: inv ret = %d, cc = %x\n",ret,cc); if (ret != 0) return(ret); if (cc != 0) { ret = (cc & 0x00ff); return(ret); } sz = resp[0] + (resp[1] << 8); if (resp[2] & 0x01) { fwords = 1; sz = sz * 2; } else fwords = 0; frubuf = malloc(sz); if (frubuf == NULL) return(get_errno()); sfru = sz; /* Loop on READ_FRU_DATA */ for (i = 0, chunk=FRUCHUNK_SZ; i < sz; i+=chunk) { if ((i+chunk) >= sz) chunk = sz - i; indata[0] = frudev; /* FRU Device ID */ if (fwords) { indata[3] = chunk / 2; fruoff = (i/2); } else { indata[3] = chunk; fruoff = i; } indata[1] = fruoff & 0x00FF; indata[2] = (fruoff & 0xFF00) >> 8; sresp = sizeof(resp); ret = ipmi_cmd_mc(READ_FRU_DATA,indata,4,resp,&sresp,&cc,fdebug); if (ret != 0) break; else if (cc != 0) { if (i == 0) ret = cc & 0x00ff; if (fdebug) printf("read_fru[%d]: ret = %d cc = %x\n",i,ret,cc); break; } memcpy(&frubuf[i],&resp[1],chunk); } if ((frudev == 0) && (sa == bmc_sa)) { /*main system fru*/ sresp = sizeof(resp); ret = ipmi_cmd_mc(GET_SYSTEM_GUID,indata,0,resp,&sresp,&cc,fdebug); if ((ret != 0) && !is_remote()) { /* get UUID from SMBIOS */ cc = 0; sresp = 16; ret = get_SystemGuid(resp); } if (fdebug) printf("system_guid: ret = %d, cc = %x\n",ret,cc); if (ret == 0 && cc == 0) { if (fdebug) { printf("system guid (%d): ",sresp); for (i=0; i<16; i++) printf("%02x ",resp[i]); printf("\n"); } memcpy(&guid,&resp,16); guid[16] = 0; } } /*endif*/ return(ret); } static void decode_string(unsigned char type, unsigned char language_code, unsigned char *source, int slen, char *target, int tsize) { static const char bcd_plus[] = "0123456789 -.:,_"; unsigned char *s = &source[0]; unsigned char *d = &target[0]; int len, i, j, k; union { uint32_t bits; char chars[4]; } u; if (slen == 0 || slen == 1) return; switch(type) { case STRING_DATA_TYPE_BINARY: /* 00: binary/unspecified */ len = (slen*2); break; /* hex dump -> 2x length */ case STRING_DATA_TYPE_SIX_BIT_ASCII: /*type 2 6-bit ASCII*/ /* 4 chars per group of 1-3 bytes */ len = ((((slen+2)*4)/3) & ~3); break; case STRING_DATA_TYPE_LANG_DEPENDENT: /* 03 language dependent */ case STRING_DATA_TYPE_BCD_PLUS: /* 01b: BCD plus */ default: len = slen; break; } if (len >= tsize) len = tsize - 1; memset(target, 0, len); if (type == STRING_DATA_TYPE_BCD_PLUS) { /*type 1 BCD plus*/ for (k=0; k 1 ? s[i+1] : 0); u.chars[1] = (k > 2 ? s[i+2] : 0); #define CHAR_IDX 3 #else memcpy((void *)&u.bits, &s[i], k); #define CHAR_IDX 0 #endif for (k=0; k<4; k++) { target[j++] = ((u.chars[CHAR_IDX] & 0x3f) + 0x20); u.bits >>= 6; } } target[j] = '\0'; } else if (type == STRING_DATA_TYPE_LANG_DEPENDENT) { /*type 3*/ if ((language_code == 0x00) || (language_code == 0x25) || (language_code == 0x19)) { memcpy(target, source, len); target[len] = 0x0; } else { printf("Language 0x%x dependent decode not supported\n",language_code); } } else if (type == STRING_DATA_TYPE_BINARY) { /* 00: binary/unspecified */ strncpy(target, buf2str(s, slen), len); } else { /* other */ printf("Unable to decode type 0x%.2x\n",type); } return; } uchar calc_cksum(uchar *pbuf,int len) { int i; uchar cksum; uchar sum = 0; for (i = 0; i < len; i++) sum += pbuf[i]; cksum = 0 - sum; return(cksum); } static void dumpbuf(uchar *pbuf,int sz) { uchar line[17]; uchar a; int i, j; line[0] = 0; line[16] = 0; j = 0; for (i = 0; i < sz; i++) { if (i % 16 == 0) { j = 0; printf("%s\n %04d: ",line,i); } a = pbuf[i]; if (a < 0x20 || a > 0x7f) a = '.'; line[j++] = a; printf("%02x ",pbuf[i]); } line[j] = 0; printf("%s\n",line); return; } #define NSPDMFG 7 static struct { uchar id; char *str; } spd_mfg[NSPDMFG] = { /* see JEDEC JEP106 doc */ { 0x2c, "Micron" }, { 0x15, "Philips Semi" }, { 0x1c, "Mitsubishi" }, { 0xce, "Samsung" }, { 0xc1, "Infineon" }, { 0x98, "Kingston" }, { 0x89, "Intel" } }; int ValidTL(uchar typelen) { if (vend_id != VENDOR_INTEL) return 1; if ((typelen & 0xC0) == 0xC0) return 1; else return 0; } char * FruTypeString(uchar frutype) { char *pstr; switch (frutype) { case 0x07: pstr = "Baseboard"; break; /*IPMB*/ case 0x0c: pstr = "Baseboard"; break; /*FRU*/ case 0x0a: pstr = "PowerSply"; break; /*FRU*/ case 0x15: pstr = "PowerCage"; break; /*FRU*/ case 0x20: pstr = "DIMM "; break; /*FRU*/ case 0x0f: pstr = "HotSwapCt"; break; /*IPMB*/ case 0x2e: pstr = "ME "; break; /*IPMB*/ default: pstr = "Component"; break; } return(pstr); } static void show_spd(uchar *spd, int lenspd, uchar frudev, uchar frutype) { int sz; char *pstr; uchar mrev; int i; char devstr[20]; sz = spd[0]; /* sz should == lenspd */ if (fcanonical) devstr[0] = 0; /*default is empty string*/ else sprintf(devstr,"[%s,%02x] ",FruTypeString(frutype),frudev); printf("%sMemory SPD Size %c %d\n", devstr,bdelim,lenspd); if (spd[2] == 0x07) pstr = "DDR"; else /* usu 0x04 */ pstr = "SDRAM"; printf("%sMemory Type %c %s\n", devstr,bdelim,pstr); printf("%sModule Density %c %d MB per bank\n", devstr,bdelim, (spd[31] * 4)); printf("%sModule Banks %c %d banks\n", devstr,bdelim,spd[5]); printf("%sModule Rows, Cols %c %d rows, %d cols\n", devstr,bdelim, spd[3], spd[4]); if (spd[11] == 0x00) pstr = "Non-parity"; else /* usu 0x02 */ pstr = "ECC"; printf("%sDIMM Config Type %c %s\n",devstr,bdelim,pstr); for (i = 0; i < NSPDMFG; i++) if (spd_mfg[i].id == spd[64]) break; if (i == NSPDMFG) pstr = ""; /* not found, use null string */ else pstr = spd_mfg[i].str; printf("%sManufacturer ID %c %s (0x%02x)\n", devstr,bdelim, pstr, spd[64]); mrev = spd[91]; /* save this byte for later */ spd[91] = 0; /*stringify part number */ printf("%sManufacturer Part# %c %s\n", devstr,bdelim,&spd[73]); printf("%sManufacturer Rev %c %02x %02x\n", devstr,bdelim,mrev,spd[92]); printf("%sManufacturer Date %c year=%02d week=%02d\n", devstr,bdelim,spd[93],spd[94]); printf("%sAssembly Serial Num %c %02x%02x%02x%02x\n", devstr,bdelim,spd[95], spd[96], spd[97], spd[98]); spd[91] = mrev; /* restore byte, so ok to repeat later */ return; } void show_guid(uchar *pguid) { char *s; int i; for (i=0; i<16; i++) { if ((i == 4) || (i == 6) || (i == 8) || (i == 10)) s = "-"; else s = ""; printf("%s%02x",s,pguid[i]); } } static char *volt_desc(uchar b) { char *s; switch(b) { case 0x03: s = "5V"; break; case 0x02: s = "3.3V"; break; case 0x01: s = "-12V"; break; case 0x00: default: s = "12V"; break; } return(s); } static char *mgt_type(uchar b) { char *s; switch(b) { case 0x01: s = "SysMgt_URL"; break; case 0x02: s = "SystemName"; break; case 0x03: s = "SysPingAddr"; break; case 0x04: s = "Compon_URL"; break; case 0x05: s = "ComponName"; break; case 0x06: s = "ComponPing"; break; case 0x07: default: s = "SysGUID"; break; } return(s); } static void show_fru_multi(char *tag, int midx, uchar mtype, uchar *pdata, int dlen) { int vend, i; char mystr[256]; char *s1, *s2; int v1, v2, v3, v4, v5, v6, v7, v8; uchar b1, b2; if (fdebug) dumpbuf(pdata,dlen); /*multi-record area dump*/ sprintf(mystr,"%sMulti[%d] ",tag,midx); i = strlen(mystr); switch(mtype) { case 0x00: /*Power Supply*/ printf("%sPower Supply Record %c \n",mystr,bdelim); v1 = pdata[0] + ((pdata[1] & 0x0f) << 8); printf("\t Capacity \t%c %d W\n",bdelim, v1); v2 = pdata[2] + (pdata[3] << 8); printf("\t Peak VA \t%c %d VA\n",bdelim, v2); printf("\t Inrush Current\t%c %d A\n",bdelim, pdata[4]); printf("\t Inrush Interval\t%c %d ms\n",bdelim, pdata[5]); v3 = pdata[6] + (pdata[7] << 8); v4 = pdata[8] + (pdata[9] << 8); printf("\t Input Voltage Range1\t%c %d-%d V\n", bdelim,v3/100,v4/100); v3 = pdata[10] + (pdata[11] << 8); v4 = pdata[12] + (pdata[13] << 8); printf("\t Input Voltage Range2\t%c %d-%d V\n", bdelim,v3/100,v4/100); printf("\t Input Frequency Range\t%c %d-%d Hz\n", bdelim,pdata[14],pdata[15]); printf("\t AC Dropout Tolerance\t%c %d ms\n",bdelim, pdata[16]); b1 = pdata[17]; b2 = (b1 & 0x01); if (b2) { /*predictive fail*/ if (b1 & 0x10 != 0) s1 = "DeassertFail "; else s1 = "AssertFail "; } else { if (b1 & 0x10 != 0) s1 = "2pulses/rot "; else s1 = "1pulse/rot "; } printf("\t Flags \t%c %s%s%s%s%s\n",bdelim, (b2 ? "PredictFail " : ""), ((b1 & 0x02 == 0) ? "" : "PowerFactorCorrect "), ((b1 & 0x04 == 0) ? "" : "AutoswitchVolt "), ((b1 & 0x08 == 0) ? "" : "Hotswap "), s1); v5 = pdata[18] + ((pdata[19] & 0x0f) << 8); v6 = (pdata[19] & 0xf0) >> 4; printf("\t Peak Capacity \t%c %d W for %d s\n",bdelim, v5,v6); if (pdata[20] == 0) { printf("\t Combined Capacity\t%c not specified\n",bdelim); } else { b1 = pdata[20] & 0x0f; b2 = (pdata[20] & 0xf0) >> 4; v7 = pdata[21] + (pdata[22] << 8); printf("\t Combined Capacity\t%c %d W (%s and %s)\n", bdelim, v7,volt_desc(b1),volt_desc(b2)); } if (b2) /*predictive fail*/ printf("\t Fan low threshold\t%c %d RPS\n",bdelim,pdata[23]); break; case 0x01: /*DC Output*/ b1 = pdata[0] & 0x0f; b2 = (pdata[0] & 0x80 != 0); printf("%sDC Output %c number %d\n",mystr,bdelim,b1); printf("\t Standby power \t%c %s\n", bdelim, (b2 ? "Yes" : "No")); v1 = pdata[1] + (pdata[2] << 8); printf("\t Nominal voltage \t%c %.2f V\n", bdelim, v1 / 100); v2 = pdata[3] + (pdata[4] << 8); v3 = pdata[5] + (pdata[6] << 8); printf("\t Voltage deviation \t%c + %.2f V / - %.2f V\n", bdelim, v3/100, v2/100); v4 = pdata[7] + (pdata[8] << 8); printf("\t Ripple and noise pk-pk \t%c %d mV\n", bdelim, v4); v5 = pdata[9] + (pdata[10] << 8); printf("\t Min current draw \t%c %.3f A\n", bdelim, v5/1000); v6 = pdata[11] + (pdata[12] << 8); printf("\t Max current draw \t%c %.3f A\n", bdelim, v6/1000); break; case 0x02: /*DC Load*/ b1 = pdata[0] & 0x0f; printf("%sDC Load %c number %d\n",mystr,bdelim,b1); v1 = pdata[1] + (pdata[2] << 8); printf("\t Nominal voltage \t%c %.2f V\n", bdelim, v1 / 100); v2 = pdata[3] + (pdata[4] << 8); v3 = pdata[5] + (pdata[6] << 8); printf("\t Min voltage allowed \t%c %.2f A\n", bdelim, v2); printf("\t Max voltage allowed \t%c %.2f A\n", bdelim, v3); v4 = pdata[7] + (pdata[8] << 8); printf("\t Ripple and noise pk-pk \t%c %d mV\n", bdelim, v4); v5 = pdata[9] + (pdata[10] << 8); printf("\t Min current load \t%c %.3f A\n", bdelim, v5/1000); v6 = pdata[11] + (pdata[12] << 8); printf("\t Max current load \t%c %.3f A\n", bdelim, v6/1000); break; case 0x03: /*Management Access*/ b1 = pdata[0]; printf("%sManagemt Access %c %s ",mystr,bdelim,mgt_type(b1)); memcpy(mystr,&pdata[1],dlen-1); mystr[dlen-1] = 0; printf("%s\n",mystr); break; case 0x04: /*Base Compatibility*/ vend = pdata[0] + (pdata[1] << 8) + (pdata[2] << 16); printf("%sBasic Compat %c %06x\n",mystr,bdelim,vend); break; case 0x05: /*Extended Compatibility*/ vend = pdata[0] + (pdata[1] << 8) + (pdata[2] << 16); printf("%sExtended Compat %c %06x\n",mystr,bdelim,vend); break; case 0xC0: /*OEM Extension*/ vend = pdata[0] + (pdata[1] << 8) + (pdata[2] << 16); if (vend == OEM_PICMG) { printf("%sOEM PICMG %c \n", mystr,bdelim); show_fru_picmg(pdata,dlen); } else printf("%sOEM Ext %c %06x %02x\n", mystr,bdelim, vend, pdata[3]); break; default: printf("%s %02x %c %02x\n", mystr,mtype,bdelim, pdata[0]); break; } } int show_fru(uchar sa, uchar frudev, uchar frutype) { int ret = 0; int i, j, n, sz; uchar *pfru; uchar lang; TYPE_LEN tl; char newstr[64]; int iaoff, ialen, bdoff, bdlen; int proff, prlen, choff, chlen; int moff, mlen; char devstr[24]; char *pstr; int extra = 0; if (frubuf[0] == 0x80) { /* 0x80 = type for DIMMs (SPD) */ /* FRU Header: 80 08 07 0c 0a 01 48 00 (DIMM) */ sz = frubuf[0]; if (fdebug) { printf("DIMM SPD Body (size=%d/%d): ",sz,sfru); dumpbuf(frubuf,sfru); } show_spd(frubuf,sfru, frudev,frutype); return(ret); } pstr = FruTypeString(frutype); if (fcanonical) devstr[0] = 0; /*default is empty string*/ else sprintf(devstr,"[%s,%02x] ",pstr,frudev); printf("%s%s FRU Size %c %d\n",devstr,pstr,bdelim,sfru); /* * FRU header: * 0 = format_ver (01 is std, usu 0x80 if DIMM) * 1 = internal_use offset * 2 = chassis_info offset * 3 = board_info offset (usu 6 fields) * 4 = product_info offset (usu 8 fields) * 5 = multirecord offset * 6 = pad (00) * 7 = header checksum (zero checksum) * FRU Header: 01 01 02 09 13 00 00 e0 (BMC) * FRU Header: 01 00 00 00 01 07 00 f7 (Power Cage) */ pfru = &frubuf[0]; sz = 8; /*minimum for common header*/ for (i = 1; i < 6; i++) { /* walk thru offsets */ if (frubuf[i] != 0) sz = frubuf[i] * 8; } if (sz > 8) { /* if have at least one section */ if (frubuf[5] != 0) j = 5 + frubuf[sz+2]; /*if multi-record area*/ else j = frubuf[sz+1] * 8; /* else add length of last section */ sz += j; } /* Now, sz = size used, sfru = total available size */ if (sz > sfru) { if (fdebug) { printf("FRU Header: "); for (i = 0; i < 8; i++) printf("%02x ",frubuf[i]); printf("\n"); } printf("FRU size out of bounds: available=%d used=%d\n",sfru,sz); printf("Please apply the correct FRU/SDR diskette\n"); if (fdoanyway) { extra = sz - sfru; sz = sfru; } else return(ERR_OTHER); } /* internal area offset, length */ iaoff = frubuf[1] * 8; ialen = frubuf[iaoff + 1] * 8; /* chassis area offset, length */ choff = frubuf[2] * 8; chlen = frubuf[choff + 1] * 8; /* board area offset, length */ bdoff = frubuf[3] * 8; bdlen = frubuf[bdoff + 1] * 8; /* product area offset, length */ proff = frubuf[4] * 8; prlen = frubuf[proff + 1] * 8; if (extra > 0) { /*do fixup of extra in product area*/ prlen -= extra; j = prlen / 8; prlen = j * 8; /*resolve to 8-byte bound*/ frubuf[proff + 1] = j; } /* multi-record area offset, length */ moff = frubuf[5] * 8; mlen = 0; if (moff > 0) { for (i = moff; i < sfru; ) { if (frubuf[i] == 0 && frubuf[i+2] == 0) break; /*type/len invalid*/ j = 5 + frubuf[i+2]; mlen += j; if (frubuf[i+1] & 0x80) break; i += j; } } if (fdebug) { printf("FRU Header: "); for (i = 0; i < 8; i++) printf("%02x ",frubuf[i]); printf("\n"); printf("FRU Body (size=%d/%d): ",sz,sfru); dumpbuf(frubuf,sfru); printf("header, len=%d, cksum0 = %02x, cksum1 = %02x\n", 8,frubuf[7],calc_cksum(&frubuf[0],7)); printf("internal off=%d, len=%d, cksum = %02x\n", iaoff,ialen,calc_cksum(&frubuf[iaoff],ialen-1)); printf("chassis off=%d, len=%d, cksum = %02x\n", choff,chlen,calc_cksum(&frubuf[choff],chlen-1)); printf("board off=%d, len=%d, cksum = %02x\n", bdoff,bdlen,calc_cksum(&frubuf[bdoff],bdlen-1)); printf("prod off=%d, len=%d, cksum = %02x\n", proff,prlen,calc_cksum(&frubuf[proff],prlen-1)); /* Multi-record area */ printf("multi off=%d, len=%d, fru sz=%d\n", moff,mlen,sz); } /*endif fdebug, show header*/ if (choff != 0) { /* show Chassis area fields */ pfru = &frubuf[choff]; lang = 25; /* English */ ctype = pfru[2]; /*chassis type*/ if (fdebug) printf("ctype=%x\n",ctype); if (ctype >= MAX_CTYPE) ctype = MAX_CTYPE - 1; printf("%s%s%c %s\n",devstr, ctype_hdr,bdelim,ctypes[ctype]); pfru += 3; /* skip chassis header */ for (i = 0; i < NUM_CHASSIS_FIELDS; i++) { if (pfru[0] == FRU_END) break; /*0xC1 = end of FRU area*/ if (!ValidTL(pfru[0])) printf(" ERROR - Invalid Type/Length %02x for %s\n", pfru[0],chassis[i]); tl.type = (pfru[0] & FRU_TYPE_MASK) >> 6; tl.len = pfru[0] & FRU_LEN_MASK; if (i == 2) { /* OEM field for chassis_name */ chassis_offset = (int)(pfru - frubuf); chassis_len = tl.len; if (fdebug) printf("chassis oem dtype=%d lang=%d len=%d\n", tl.type,lang,tl.len); } pfru++; { newstr[0] = 0; decode_string(tl.type,lang,pfru,tl.len,newstr,sizeof(newstr)); printf("%s%s%c %s\n",devstr, chassis[i],bdelim,newstr); } pfru += tl.len; } if (fdebug) printf("num Chassis fields = %d\n",i); } if (bdoff != 0) { long nMin, nSec; time_t tsec; /* show Board area fields */ pfru = &frubuf[bdoff]; lang = pfru[2]; /* Decode board mfg date-time (num minutes since 1/1/96) */ nMin = pfru[3] + (pfru[4] << 8) + (pfru[5] << 16); /* 13674540 min from 1/1/70 to 1/1/96 */ nSec = (nMin + 13674540) * 60; tsec = (time_t)(nSec & 0x0ffffffff); // fmt_time(tsec,newstr,sizeof(newstr)); printf("%sBoard Mfg DateTime %c %s",devstr,bdelim,ctime(&tsec)); pfru += 6; /* skip board header */ for (i = 0; i < NUM_BOARD_FIELDS; i++) { if (pfru[0] == FRU_END) break; /*0xC1 = end*/ if (!ValidTL(pfru[0])) printf(" ERROR - Invalid Type/Length %02x for %s\n", pfru[0],board[i]); tl.type = (pfru[0] & FRU_TYPE_MASK) >> 6; tl.len = pfru[0] & FRU_LEN_MASK; pfru++; { newstr[0] = 0; decode_string(tl.type,lang,pfru,tl.len,newstr,sizeof(newstr)); printf("%s%s%c %s\n",devstr, board[i],bdelim,newstr); } pfru += tl.len; } if (fdebug) printf("num Board fields = %d\n",i); } if (proff != 0) { /* show Product area fields */ pfru = &frubuf[proff]; maxprod = pfru[1] * 8; lang = pfru[2]; pfru += 3; /* skip product header */ for (i = 0; i < NUM_PRODUCT_FIELDS; i++) { if (*pfru == FRU_END) { /*0xC1 = end*/ /* Wart for known Kontron 1-byte Product Version anomaly. */ if ((vend_id == VENDOR_KONTRON) && (i == 3)) ; else break; } if (*pfru == 0) *pfru = FRU_EMPTY_FIELD; /* fix a broken table */ if (!ValidTL(pfru[0])) printf(" ERROR - Invalid Type/Length %02x for %s\n", pfru[0],product[i]); tl.type = (pfru[0] & FRU_TYPE_MASK) >> 6; tl.len = pfru[0] & FRU_LEN_MASK; n = (int)(pfru - frubuf); prodarea[i].offset = n; prodarea[i].len = tl.len; memcpy(prodarea[i].tag, &frubuf[n+1] ,tl.len); pfru++; { newstr[0] = 0; decode_string(tl.type,lang,pfru,tl.len,newstr,sizeof(newstr)); printf("%s%s%c %s\n",devstr, product[i],bdelim,newstr); } pfru += tl.len; } if (fdebug) printf("num Product fields = %d, last=%x, max = %d\n", i,*pfru,maxprod ); product_num = i; /*save number of existing product fields*/ if (*pfru == 0x00) *pfru = FRU_END; /* insert end char if broken */ } if (moff != 0) { /* multi-record area may contain several record headers * 0 = record type id * 1 = 0x02 or 0x80 if End-of-List * 2 = record len * 3 = record chksum * 4 = header chksum */ pfru = &frubuf[moff]; j = moff; for (i = 0; j < sz; i++) { if (pfru[0] == 0 && pfru[2] == 0) break; /*type/len invalid*/ n = pfru[2]; /* len of this record */ show_fru_multi(devstr,i,pfru[0],&pfru[5],n); j += (5 + n); if (pfru[1] & 0x80) j = sz; /*0x80 = end of list*/ pfru += (5 + n); } } if ((frudev == 0) && (sa == bmc_sa)) { char *s; printf("%sSystem GUID %c ",devstr,bdelim); for (i=0; i<16; i++) { if ((i == 4) || (i == 6) || (i == 8) || (i == 10)) s = "-"; else s = ""; printf("%s%02x",s,guid[i]); } printf("\n"); } return(ret); } static int write_fru_data(uchar id, ushort offset, uchar *data, int dlen, char fdebug) { int ret = -1; int chunk; ushort fruoff; uchar req[FRUCHUNK_SZ+9]; uchar resp[16]; int sresp; uchar cc; int i, j; /* Write the buffer in small 16-byte (FRUCHUNK_SZ) chunks */ req[0] = id; /* FRU Device ID (fruid) */ fruoff = offset; chunk = FRUCHUNK_SZ; for (i = 0; i < dlen; i += chunk) { req[1] = fruoff & 0x00ff; req[2] = (fruoff & 0xff00) >> 8; if ((i + chunk) > dlen) chunk = dlen - i; memcpy(&req[3],&data[i],chunk); if (fdebug) { printf("write_fru_data[%d] (len=%d): ",i,chunk+3); for (j = 0; j < chunk+3; j++) printf("%02x ",req[j]); printf("\n"); } sresp = sizeof(resp); ret = ipmi_cmd_mc(WRITE_FRU_DATA,req,(uchar)(chunk+3),resp,&sresp, &cc,fdebug); if ((ret == 0) && (cc != 0)) ret = cc & 0x00ff; if (fdebug && ret == 0) printf("write_fru_data[%d]: %d bytes written\n",i,resp[0]); if (ret != 0) break; fruoff += chunk; } return(ret); } /* * write_product * Updates the FRU Product area only. * Note that this function will always provide >=8 product fields, * even if the original had less than 8. * inputs: prodnew = array of new strings to write * frubuf = contains existing FRU data * newdata = new product area buffer, malloc'd * outputs: returns 0 if successful */ int write_product(void) { int ret = -1; uchar req[25]; uchar resp[16]; int sresp; uchar cc; ushort fruoff; int alen, clen; int snlen, verlen; uchar *pfru0; uchar *pfru; uchar *pnew; int i, j, k, n, plen, newlen, max, plimit; int chas_offset; int prod_offset; int mult_offset, mult_len; uchar chksum; int chunk; chas_offset = frubuf[2] * 8; // offset of chassis data prod_offset = frubuf[4] * 8; // offset of product data plen = frubuf[prod_offset+1] * 8; // length of product data mult_offset = frubuf[5] * 8; mult_len = 0; if (mult_offset > 0) { for (i = mult_offset; i < sfru; ) { mult_len += (5 + frubuf[i+2]); if (frubuf[i+1] & 0x80) break; i = mult_len; } } /* Check if asset tag will fit in product data area of FRU. */ if (fdebug) printf("write_product: fru[4,p]=[%02x,%02x] prod_off=%d, plen=%d\n", frubuf[4],frubuf[prod_offset+1],prod_offset,plen); if (plen > sfru) return ERR_LENMAX; // product bigger than buffer if (prodnew[IPROD_ASSET].len > plen) return ERR_LENMAX; /* if asset bigger than product data, error. */ /* asset comes after sernum, so this check works for both */ newdata = malloc(sfru); /* but should not need more than plen bytes */ if (newdata == NULL) return(get_errno()); memset(newdata,0,sfru); pnew = &newdata[0]; /* Set pointer to start of chassis area */ pfru = &frubuf[chas_offset]; /* Product Area Header (3 bytes): [0] = 0x01; * format ver 1 * [1] = 0x0a; *product area size (in 8-byte mult)* [2] = 0x00; *lang=english * Usually max product area is 3 + 8*32 = 259 mod 8 = 264. */ pfru0 = &frubuf[prod_offset]; pfru = &frubuf[prod_offset]; j = 3; memcpy(pnew,pfru,j); pfru += j; pnew += j; n = j; if (mult_offset > 0) plimit = plen; else plimit = sfru - prod_offset; /*plen can expand*/ for (i = 0; i < NUM_PRODUCT_FIELDS; i++) { j = prodarea[i].len; /*new len*/ k = pfru[0] & FRU_LEN_MASK; /*old len*/ if (k == 1) { /*was 0xC1 FRU_END*/ if ((vend_id == VENDOR_KONTRON) && (i == 3) && (j == 1)) { /* fix Kontron 1-byte Version */ prodarea[i].tag[1] = ' '; j++; } else k = 0; } /* check for product area overflow */ if (n + 2 >= plimit) { if (fdebug) printf("Field %d is at %d, beyond product area size %d\n", i+1,n+2,plimit); break; } else if ((n + 1 + j) >= plimit) { if (fdebug) printf("Field %d at %d + %d, truncated, product size %d\n", i+1,n+1,j,plimit); j = 0; } pnew[0] = (j | FRU_TYPE_MASK); /*add type=3 to len*/ memcpy(&pnew[1],prodarea[i].tag,j); if (fdebug) { printf("i=%d frubuf[%d]: %02x %02x %02x, j=%d k=%d n=%d\n", i,(pfru-frubuf),pfru[0],pfru[1],pfru[2],j,k,n); if (i >= product_num) printf("Field %d is beyond existing %d fields\n",i+1,product_num); } pnew += j + 1; pfru += k + 1; n += j + 1; } // n = (int)(pnew - newdata); /*new product area index*/ k = (int)(pfru - pfru0); /*old product area index*/ if (mult_offset > 0) /* do not expand if multi-record area there */ max = plen - k; else /* nothing else, can expand product area, up to sfru */ max = sfru - (k + prod_offset); if (fdebug) printf("frubuf[%d]: %02x %02x %02x, j=%d k=%d n=%d remainder=%d\n", (pfru-frubuf),pfru[0],pfru[1],pfru[2],j,k,n,max); if (max < 0) max = 0; /* copy trailing fru data from saved copy */ for (i = 0; i < max; i++) { pnew[i] = pfru[i]; if (pfru[i] == FRU_END) { i++; break; } /*0xC1*/ } if (i == max) { /*never found 0xC1 FRU_END*/ pnew[0] = FRU_END; /*mark this trailing field as empty*/ i = 1; } newlen = n + i; if (fdebug) printf("newbuf[%d]: %02x %02x %02x, j=%d newlen=%d plen=%d\n", n,pnew[0],pnew[1],pnew[2],j,newlen,plen); /* round up to next 8-byte boundary */ /* need one more byte for checksum, so if j=0, add 8 anyway */ j = 8 - (newlen % 8); for (i = 0; i < j; i++) newdata[newlen++] = 0; if (newlen < plen) newlen = plen; /* don't shrink the product area */ newdata[1] = newlen / 8; // set length of product data /* include new checksum (calc over Product area) */ chksum = calc_cksum(&newdata[0],newlen-1); newdata[newlen-1] = chksum; if (fdebug) { printf("old prod_area buffer (%d):",plen); dumpbuf(&frubuf[prod_offset],plen); printf("new prod_area buffer (%d):",newlen); dumpbuf(newdata,newlen); } if (prod_offset + newlen >= sfru) return ERR_LENMAX; if ((mult_offset > 0) && (newlen > plen)) return ERR_LENMAX; #ifdef TEST newlen = 0; /*don't actually write the new data, if testing*/ #endif ret = write_fru_data(g_fruid, prod_offset, newdata, newlen, fdebug); return(ret); } #define CHUNKSZ 16 #define LAST_REC 0xffff #define STR_OFF 16 int get_sdr(ushort recid, ushort resid, ushort *recnext, uchar *sdr, int *slen, uchar *pcc) { uchar idata[6]; uchar rdata[64]; int sresp; ushort cmd; uchar cc = 0; int len = 0; int rc; idata[0] = resid & 0x00ff; idata[1] = (resid & 0xff00) >> 8; idata[2] = recid & 0x00ff; idata[3] = (recid & 0xff00) >> 8; idata[4] = 0; /*offset*/ idata[5] = CHUNKSZ; /*bytes to read*/ if (fdevsdrs) cmd = GET_DEVICE_SDR; else cmd = GET_SDR; sresp = sizeof(rdata); rc = ipmi_cmd_mc(cmd, idata, 6, rdata, &sresp,&cc, fdebug); if (fdebug) printf("get_sdr[%x] ret = %d cc = %x sresp = %d\n", recid,rc,cc,sresp); if (rc == 0 && cc == 0xCA) { idata[5] = 8; /*bytes to read*/ sresp = sizeof(rdata); rc = ipmi_cmd_mc(cmd, idata, 6, rdata, &sresp,&cc, fdebug); if (fdebug) printf("get_sdr[%x] ret = %d cc = %x sresp = %d\n", recid,rc,cc,sresp); } *pcc = cc; if (rc == 0 && cc == 0) { *recnext = rdata[0] + (rdata[1] << 8); memcpy(sdr,&rdata[2],sresp-2); *slen = sdr[6] + 5; /*get actual SDR size*/ len = sresp-2; /* if an SDR locator record, get the rest of it. */ if (sdr [3] == 0x11 || sdr[3] == 0x12) if (*slen > CHUNKSZ) { idata[0] = resid & 0x00ff; idata[1] = (resid & 0xff00) >> 8; idata[2] = recid & 0x00ff; idata[3] = (recid & 0xff00) >> 8; idata[4] = CHUNKSZ; /*offset*/ idata[5] = *slen - CHUNKSZ; /*bytes to read*/ sresp = sizeof(rdata); rc = ipmi_cmd_mc(cmd, idata, 6, rdata, &sresp,&cc, fdebug); if (fdebug) printf("get_sdr[%x] 2nd ret=%d cc=%x sresp=%d\n", recid,rc,cc,sresp); if (rc == 0 && cc == 0) { sresp -= 2; memcpy(&sdr[len],&rdata[2],sresp); len += sresp; } } *slen = len; } return(rc); } void show_loadfru_error(uchar sa, uchar fruid, int ret) { if (ret == 0) return; switch(ret) { case 0x081: printf("\tFRU(%x,%x) device busy\n",sa,fruid); break; case 0x0C3: printf("\tFRU(%x,%x) timeout, not found\n",sa,fruid); break; case 0x0CB: printf("\tFRU(%x,%x) not present\n",sa,fruid); break; default: printf("load_fru(%x,%x) error = %d (0x%x)\n", sa,fruid,ret,ret); break; } return; } #ifdef METACOMMAND int i_ifruset(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int ret; int c; char DevRecord[16]; ushort recid; ushort nextid; ushort rsvid; uchar sdr[40]; char biosver[80]; uchar cc; uchar sa; uchar fruid = 0; uchar frutype = 0; int len, i; char *s1; FILE *fp; printf("%s version %s\n",progname,progver); parse_lan_options('V',"4",0); /*request admin priv by default*/ while ( (c = getopt( argc, argv,"a:bcd:h:i:f:m:n:o:p:r:s:u:v:xyz:T:V:J:EYF:P:N:R:U:Z:?")) != EOF ) switch(c) { case 'x': fdebug = 1; break; case 'y': fdoanyway = 1; break; case 'b': fonlybase = 1; g_frutype = 0x07; break; case 'c': fcanonical = 1; bdelim = BDELIM; break; #ifdef TEST case 'h': if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; strncpy(chassis_name,optarg,len); if (len == 1) { /* add a space */ chassis_name[1] = ' '; chassis_name[2] = 0; } } break; #else case 'h': fonlyhsc = 1; /* can use -m00c000s instead */ g_frutype = 0x0f; break; #endif case 'a': fwritefru |= 0x01; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_ASSET].tag,optarg,len); prodnew[IPROD_ASSET].len = len; } break; case 'f': fwritefru |= 0x04; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_FRUID].tag,optarg,len); prodnew[IPROD_FRUID].len = len; } break; case 'n': fwritefru |= 0x20; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_NAME].tag,optarg,len); prodnew[IPROD_NAME].len = len; } break; case 'o': fwritefru |= 0x10; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_OEM].tag,optarg,len); prodnew[IPROD_OEM].len = len; } break; case 'p': fwritefru |= 0x40; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_PART].tag,optarg,len); prodnew[IPROD_PART].len = len; } break; case 'u': fwritefru |= 0x80; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_MANUF].tag,optarg,len); prodnew[IPROD_MANUF].len = len; } break; case 's': fwritefru |= 0x02; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_SERNUM].tag,optarg,len); prodnew[IPROD_SERNUM].len = len; } break; case 'v': fwritefru |= 0x08; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_VERS].tag,optarg,len); prodnew[IPROD_VERS].len = len; } break; case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } fset_mc = 1; printf("set MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'z': /* set local IPMB MC sa */ sa = htoi(&optarg[0]); /*device slave address*/ ipmi_set_mymc(g_bus, sa, g_lun,ADDR_IPMB); bmc_sa = sa; case 'i': fonlybase = 1; /*specify a fru id*/ if (strncmp(optarg,"0x",2) == 0) g_fruid = htoi(&optarg[2]); else g_fruid = htoi(optarg); printf("Using FRU ID 0x%02x\n",g_fruid); break; case 'd': fdump = 1; /*dump fru to a file*/ binfile = optarg; break; case 'r': frestore = 1; /*restore fru from a file*/ fwritefru = 0x100; binfile = optarg; break; case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ parse_lan_options(c,optarg,fdebug); break; default: printf("Usage: %s [-bcimxy -unpvsafo -NUPREFTVY]\n",progname); printf(" -u manu Sets Product Manufacturer (0)\n"); printf(" -n name Sets Product Name (1)\n"); printf(" -p part Sets Product Part Number (2)\n"); printf(" -v vers Sets Product Version (3)\n"); printf(" -s snum Sets Product Serial Num (4)\n"); printf(" -a tag Sets Product Asset Tag (5)\n"); printf(" -f fru Sets Product FRU File ID (6)\n"); printf(" -o oem Sets Product OEM Field (7)\n"); // printf(" -h chname Sets the Chassis Name \n"); printf(" -b Only show Baseboard FRU data\n"); printf(" -c show Canonical, delimited output\n"); printf(" -d Dump FRU to a file\n"); printf(" -r Restore FRU from a file\n"); printf(" -i 00 Get/Set a specific FRU ID\n"); printf(" -m002000 specific MC (bus 00,sa 20,lun 00)\n"); printf(" -x Display extra debug messages\n"); printf(" -y Ignore the check for FRU size overflow\n"); print_lan_opt_usage(0); ret = ERR_USAGE; goto do_exit; } // if (is_remote() && fwritefru) parse_lan_options('V',"4",0); ret = ipmi_getdeviceid( DevRecord, sizeof(DevRecord),fdebug); if (ret == 0) { uchar ipmi_maj, ipmi_min; ipmi_maj = DevRecord[4] & 0x0f; ipmi_min = DevRecord[4] >> 4; vend_id = DevRecord[6] + (DevRecord[7] << 8) + (DevRecord[8] << 16); prod_id = DevRecord[9] + (DevRecord[10] << 8); show_devid( DevRecord[2], DevRecord[3], ipmi_maj, ipmi_min); if ((DevRecord[1] & 0x80) == 0x80) fdevsdrs = 1; if (vend_id == VENDOR_NEC) fdevsdrs = 0; else if (vend_id == VENDOR_INTEL) { if (prod_id == 0x003E) { set_max_kcs_loops(URNLOOPS); /*longer for cmds (default 300)*/ } } } else { goto do_exit; } ret = ipmi_getpicmg( DevRecord, sizeof(DevRecord),fdebug); if (ret == 0) fpicmg = 1; if ((vend_id == VENDOR_INTEL) && (!fpicmg)) fdevsdrs = 0; /* override, use SDR repository*/ if (fdebug) printf("bmc_sa = %02x fdevsdrs = %d\n",bmc_sa,fdevsdrs); if (fset_mc) { /* target a specific MC via IPMB (usu a picmg blade) */ if (fdebug) printf("set_mc: %02x:%02x:%02x type=%d\n", g_bus,g_sa,g_lun,g_addrtype); ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); fonlybase = 1; /*only show this MC*/ } else { g_sa = bmc_sa; /* BMC_SA = 0x20 */ } if (g_frutype == 0) { g_frutype = 0x01; /* other = "Component" */ } if (!fonlybase && !fonlyhsc) { /* loop thru SDRs to find FRU devices */ #ifdef NOT_YET { /* get SDR Repository Info (needs to be copied here)*/ ret = GetSDRRepositoryInfo(&j,&fdevsdrs); if (fdebug) printf("GetSDRRepositoryInfo: ret=%x nSDRs=%d\n",ret,j); } #endif { /* reserve the SDR repository */ uchar resp[16]; int sresp; uchar cc; ushort cmd; sresp = sizeof(resp); if (fdevsdrs) cmd = RESERVE_DEVSDR_REP; else cmd = RESERVE_SDR_REP; ret = ipmi_cmd_mc(cmd, NULL, 0, resp, &sresp, &cc, 0); if (fdebug) printf("ipmi_cmd RESERVE status = %d, cc = %x\n",ret,cc); rsvid = resp[0] + (resp[1] << 8); } recid = 0; while (recid != LAST_REC) { char idstr[32]; int ilen; len = sizeof(sdr); /*sizeof(sdr); get 32 sdr bytes*/ ret = get_sdr(recid,rsvid,&nextid,sdr,&len,&cc); if ((ret != 0) || (cc != 0)) { printf("SDR[%04x] error %d ccode = %x\n",recid,ret,cc); break; } fgetfru = 0; if ((sdr[3] == 0x11) || (sdr[3] == 0x12)) /* SDR FRU or IPMB type */ { if (len > STR_OFF) { ilen = len - STR_OFF; if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; memcpy(idstr,&sdr[STR_OFF],ilen); idstr[ilen] = 0; } else idstr[0] = 0; sa = sdr[5]; /* usu 0x20 for bmc_sa */ /* Get its FRU data */ if ((sdr[3] == 0x11) && (sdr[7] & 0x80)) { /* FRU SDRs */ /* It is a logical FRU device */ if (fcanonical) printf("SDR[%04x] FRU %c %s\n", recid, bdelim, idstr); else printf("SDR[%04x] FRU %02x %02x %02x %02x %s\n", recid, sdr[5],sdr[6],sdr[12],sdr[13],idstr); fruid = sdr[6]; frutype = sdr[12]; if (sa == bmc_sa && fruid == 0) /*do this below*/; else switch(sdr[12]) /*FRU entity id*/ { case 0x0a: /*Power Supply*/ case 0x20: /*DIMM*/ case 0x15: /*Power Cage*/ default: fgetfru = 1; break; } } else if (sdr[3] == 0x12) { /* IPMB SDRs (DLRs for MCs) */ if (fcanonical) printf("SDR[%04x] IPMB %c %s\n", recid, bdelim, idstr); else printf("SDR[%04x] IPMB %02x %02x %02x %02x %s\n", recid, sdr[5],sdr[6],sdr[12],sdr[13],idstr); fruid = 0; /*every MC must have fruid 0*/ frutype = sdr[12]; if (sa == bmc_sa && fruid == 0) { /*do bmc_sa,0 below*/ if (fdebug) printf("do bmc_sa %02x below\n",sa); g_frutype = frutype; } else if (frutype == 0x2e) { /*skip ME*/ if (fdebug) printf("skipping ME sa %02x, %02x\n",sa,fruid); } else if (sa == 0x28) { /*do nothing for Bridge Ctlr sa=0x28*/ if (fdebug) printf("skipping IPMB sa %02x, %02x\n",sa,fruid); } else if (sa == 0xC0) { /* HotSwap Backplane (sa=0xC0) */ /* Note: Loading sa 0xC0 over ipmi lan gives a timeout * error, but it works locally. */ fgetfru = 1; } else { /* other misc sa,fruid */ fgetfru = 1; } } if (fgetfru) { uchar adrtype; adrtype = g_addrtype; if (fdebug) printf("set_mc %02x:%02x:%02x type=%d fruid=%02x\n", g_bus,sa,g_lun,adrtype,fruid); ipmi_set_mc(g_bus, sa, g_lun,adrtype); ret = load_fru(sa,fruid,frutype); if (ret != 0) { show_loadfru_error(sa,fruid,ret); free_fru(); } else { ret = show_fru(sa,fruid,frutype); if (ret != 0) printf("show_fru error = %d\n",ret); free_fru(); } ipmi_restore_mc(); } } /*endif FRU/IPMB SDR */ recid = nextid; } /*end while sdrs*/ } /*endif not fonlybase*/ /* load the FRU data for Baseboard (address 0x20) */ printf("\n"); sa = g_sa; /* bmc_sa = BMC_SA = 0x20 */ if (fonlyhsc) { sa = 0xC0; g_addrtype = ADDR_SMI; ipmi_set_mc(g_bus,sa,g_lun,g_addrtype); } if (g_addrtype == ADDR_IPMB) ipmi_set_mc(g_bus,sa,g_lun,g_addrtype); ret = load_fru(sa,g_fruid,g_frutype); if (ret != 0) { show_loadfru_error(sa,g_fruid,ret); free_fru(); goto do_exit; } /* display the Baseboard FRU data */ ret = show_fru(sa,g_fruid,g_frutype); if (ret != 0) printf("show_fru error = %d\n",ret); if (!is_remote()) { char devstr[24]; if (fcanonical) devstr[0] = 0; /*default is empty string*/ else sprintf(devstr,"[%s,%02x] ",FruTypeString(g_frutype),g_fruid); i = get_BiosVersion(biosver); if (i == 0) printf("%sBIOS Version %c %s\n",devstr,bdelim,biosver); } if (fdump && ret == 0) { /* Dump FRU to a binary file */ #ifdef WIN32 fp = fopen(binfile,"wb"); #else fp = fopen(binfile,"w"); #endif if (fp == NULL) { ret = get_LastError(); printf("Cannot open file %s, error %d\n",binfile,ret); } else { printf("Writing FRU size %d to %s ...\n",sfru,binfile); len = fwrite(frubuf, 1, sfru, fp); fclose(fp); if (len <= 0) { ret = get_LastError(); printf("Error %d writing file %s\n",ret,binfile); } else ret = 0; } } else if (frestore) { uchar cksum; /* Restore FRU from a binary file */ #ifdef WIN32 fp = fopen(binfile,"rb"); #else fp = fopen(binfile,"r"); #endif if (fp == NULL) { ret = get_LastError(); printf("Cannot open file %s, error %d\n",binfile,ret); } else { ret = 0; /* sfru and frubuf were set from load_fru above. */ len = fread(frubuf, 1, sfru, fp); if (len <= 0) { ret = get_LastError(); printf("Error %d reading file %s\n",ret,binfile); sfru = 0; /*for safety*/ } fclose(fp); if (fdebug) { printf("FRU buffer from file (%d):",sfru); dumpbuf(frubuf,sfru); } /* Do some validation of the FRU buffer header */ cksum = calc_cksum(&frubuf[0],7); if (fdebug) printf("header, len=8, cksum0 = %02x, cksum1 = %02x\n", frubuf[7],cksum); if (frubuf[7] != cksum) { printf("Not a valid FRU file\n"); ret = ERR_BAD_FORMAT; free_fru(); } if (ret == 0) { /*successfully read data*/ printf("Writing FRU size %d from %s ...\n",sfru,binfile); ret = write_fru_data(g_fruid, 0, frubuf, sfru, fdebug); free_fru(); if (ret != 0) printf("write_fru error %d (0x%02x)\n",ret,ret); else { /* successful, show new data */ ret = load_fru(sa,g_fruid,g_frutype); if (ret != 0) show_loadfru_error(sa,g_fruid,ret); else ret = show_fru(sa,g_fruid,g_frutype); free_fru(); } } } } /*end-else frestore */ else if ((fwritefru != 0) && ret == 0) { printf("\nWriting new product data (%s,%s,%s,%s,%s,%s,%s,%s) ...\n", prodnew[0].tag, prodnew[1].tag, prodnew[2].tag, prodnew[3].tag, prodnew[4].tag, prodnew[5].tag, prodnew[6].tag, prodnew[7].tag); for (i = 0; i < NUM_PRODUCT_FIELDS; i++) { len = prodnew[i].len; if (len > 0) { if (len >= FIELD_LEN) len = FIELD_LEN - 1; if (len == 1) { prodnew[i].tag[1] = ' '; len++; } prodarea[i].len = len; memcpy(prodarea[i].tag,prodnew[i].tag,len); } } ret = write_product(); free_fru(); if (ret != 0) printf("write_product error %d (0x%02x)\n",ret,ret); else { /* successful, show new data */ ret = load_fru(sa,g_fruid,g_frutype); if (ret != 0) show_loadfru_error(sa,g_fruid,ret); else ret = show_fru(sa,g_fruid,g_frutype); free_fru(); } } else free_fru(); do_exit: ipmi_close_(); show_outcome(progname,ret); return(ret); } /* end ifruset.c */ ipmiutil-3.1.5/util/ipmiutil.c0000644000076400007640000001750513566765324016443 0ustar mgportalloggers/*********************************************** * ipmiutil.c * * This is a meta-command utility to invoke each of the * other sub-commands in a consolidated interface. * To build this, compile with -DMETACOMMAND. * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2006-2007 Intel Corporation. * Copyright (c) 2009 Kontron America, Inc. * * 01/03/07 ARCress - created * 01/05/07 ARCress - version 1.0 * 01/10/07 ARCress - version 1.1 * 02/07/07 ARCress - version 1.3 adding isolconsole * 02/26/07 ARCress - updated sub-command names * 08/31/07 ARCress - added "leds" subcommand * ***********************************************/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2007, Intel Corporation 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 Corporation 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. *----------------------------------------------------------------------*/ #include #include #include #include #include #include #include "ipmicmd.h" #include "ipmiutil.h" static char *progname = "ipmiutil"; char *progver = "3.15"; // static char fdebug = 0; /*int ipmiutil(int argc, char **argv); */ #define NSUBCMDS 29 static struct { int idx; char tag[16]; int (*rtn)(int argc, char **argv); char desc[64]; } subcmds[NSUBCMDS] = { { 0, "alarms", i_alarms, "show/set the front panel alarm LEDs and relays" }, { 1, "leds", i_alarms, "show/set the front panel alarm LEDs and relays" }, { 2, "discover", i_discover, "discover all IPMI servers on this LAN" }, { 3, "cmd", i_cmd , "send a specified raw IPMI command to the BMC" }, { 4, "config", i_config, "list/save/restore BMC configuration parameters" }, { 26, "dcmi", i_dcmi, "get/set DCMI parameters" }, { 5, "ekanalyzer", i_ekanalyzer, "run EKeying analyzer on FRU files (deprecated, see fru)" }, { 6, "events", i_events, "decode IPMI events and display them" }, { 7, "firewall", i_firewall, "show/set firmware firewall functions" }, { 8, "fru", i_fru, "show decoded FRU inventory data, write asset tag"}, { 9, "fwum", i_fwum, "OEM firmware update manager extensions" }, { 10, "getevt", i_getevt, "get IPMI events and display them, event daemon" }, { 11, "getevent", i_getevt, "get IPMI events and display them, event daemon" }, { 12, "health", i_health, "check and show the basic health of the IPMI BMC"}, { 13, "hpm", i_hpm, "HPM firmware update manager extensions" }, { 14, "lan", i_lan, "show/set IPMI LAN parameters, users, PEF rules"}, { 15, "picmg", i_picmg, "show/set picmg extended functions" }, { 25, "power", i_reset, "issue IPMI reset or power control to the system"}, { 16, "reset", i_reset, "issue IPMI reset or power control to the system"}, { 17, "sel", i_sel, "show/clear firmware System Event Log records" }, { 18, "sensor", i_sensor, "show Sensor Data Records, readings, thresholds" }, { 19, "serial", i_serial, "show/set IPMI Serial & Terminal Mode parameters"}, { 20, "sol", i_sol, "start/stop an SOL console session" }, { 21, "smcoem", i_smcoem, "SuperMicro OEM functions" }, { 22, "sunoem", i_sunoem, "Sun OEM functions" }, { 23, "delloem",i_delloem, "Dell OEM functions" }, { 24, "tsol", i_tsol, "Tyan SOL console start/stop session" }, { 28, "user", i_user, "list or modify IPMI LAN users" }, { 27, "wdt", i_wdt, "show/set/reset the watchdog timer" } }; static char usagemsg[] = "Usage: ipmiutil [other options]\n" " where is one of the following:\n"; static char helpmsg[] = "For help on each command (e.g. 'sel'), enter:\n" " ipmiutil sel -?\n"; static void show_usage() { int i; printf("%s", usagemsg); for (i=0; i= NSUBCMDS) { #ifdef LINUX if ((strcmp(argv[1],"svc") == 0) && (argc >= 3)) { char mycmd[80]; char *pfunc; char *psvc; char fchkok; /* undocumented: start a given service, only works locally */ psvc = "ipmi_port"; if (argc > 2) pfunc = argv[2]; else pfunc = "on"; ret = system("ls /sbin/chkconfig >/dev/null 2>&1"); if (ret == 0) fchkok = 1; else fchkok = 0; if (strcmp(pfunc,"off") == 0) { sprintf(mycmd,"service %s stop\n",psvc); printf("%s\n",mycmd); ret = system(mycmd); if (fchkok) { sprintf(mycmd,"/sbin/chkconfig --del %s\n",psvc); printf("%s\n",mycmd); ret = system(mycmd); } } else { if (fchkok) { sprintf(mycmd,"/sbin/chkconfig --add %s\n",psvc); printf("%s\n",mycmd); ret = system(mycmd); sprintf(mycmd,"/sbin/chkconfig --level 345 %s on\n",psvc); // printf("%s\n",mycmd); ret = system(mycmd); } sprintf(mycmd,"service %s start\n",psvc); printf("%s\n",mycmd); ret = system(mycmd); } } else #endif { show_usage(); ret = ERR_USAGE; } } do_exit: { char tag[30]; sprintf(tag,"%s %s",progname,psubcmd); show_outcome(tag,ret); } return(ret); } #endif /*end ipmiutil.c*/ ipmiutil-3.1.5/util/ipmiutil.mak0000644000076400007640000003431013566765324016762 0ustar mgportalloggers# This makefile will build the ipmiutil util directory (x32) # # First download getopt.c getopt.h # Then download and build openssl for Windows # LIBC_RT=libcmt.lib /NODEFAULTLIB:"msvcirt.lib" # LIBC_RT=msvcrt.lib /NODEFAULTLIB:"msvcirt.lib" #MARCH=X64 MARCH=IX86 # The ipmiutil directory SRC_D=. LIB_D=..\lib L2_D=$(LIB_D)\lanplus L3_D=$(LIB_D)\lanplus\inc INSTALLTOP=install TMP_D=tmp INC=/I$(SRC_D) /I$(L2_D) /I$(L3_D) CMD_OBJ = getopt.obj ipmicmd.obj imbapi.obj md5.obj md2.obj \ ipmilan.obj ipmims.obj subs.obj CMD_OBJ = $(CMD_OBJ) ipmilanplus.obj # To remove lanplus support use the empty LANPLUS variables # L2_OBJ= # LF_LANPLUS= # CF_LANPLUS= L2_OBJ = $(L2_D)\helper.obj $(L2_D)\ipmi_strings.obj $(L2_D)\lanplus.obj \ $(L2_D)\lanplus_crypt_impl.obj $(L2_D)\lanplus_dump.obj \ $(L2_D)\lanplus_strings.obj $(L2_D)\lanplus_crypt.obj LF_LANPLUS=/LIBPATH:$(LIB_D) /LIBPATH:$(L2_D) $(L2_OBJ) ssleay32.lib libeay32.lib CF_LANPLUS=/DHAVE_LANPLUS /DHAVE_IPV6 # Set your compiler options # To remove any GPL dependencies, use the CF_EX line with NON_GPL # CFLAGS_O=/W3 /O2 /Zi /MD /GF /Gy /nologo # CFLAGS_O=/W3 /O2 /Zi /MD /nologo # CFLAGS_O=/W3 /O2 /Zi /MT /nologo CFLAGS_O=/W3 /O2 /Zi /MT /nologo CF_EX=/DWIN32 $(CF_LANPLUS) $(INC) /D_CONSOLE /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DHAVE_STRING_H CF_SAM=/DWIN32 $(INC) /D_CONSOLE /D_CRT_SECURE_NO_DEPRECATE /DHAVE_STRING_H $(CF_LANPLUS) CFLAGS=$(CFLAGS_O) $(CF_EX) /DSKIP_MD2 CFLAGS_M=$(CFLAGS_O) $(CF_EX) /DSKIP_MD2 /DMETACOMMAND CFLAGS_SAM=$(CFLAGS_O) $(CF_SAM) LFLAGS=/nologo /subsystem:console /machine:$(MARCH) /opt:ref #LFLAGS=/nologo /subsystem:console /machine:IX86 /opt:ref #LFLAGS=/nologo /subsystem:console /machine:IX86 /opt:ref /debug # LFLAGS_D=/nologo /subsystem:console /machine:I386 /opt:ref /dll # CFLAGS_W=/O2 /D_CONSOLE /D_MBCS /EHsc /ML /W3 /Zi /TP CFLAGS_W=/TP /EHsc $(CFLAGS) LFLAGS_W=/nologo /subsystem:console /machine:$(MARCH) /opt:ref LIBS_W=comsuppw.lib wbemuuid.lib # gdi32.lib comdlg32.lib shell32.lib uuid.lib CC=cl LINK=link MKDIR=-mkdir MKLIB=lib RM=del CP=copy LIBS_EX = advapi32.lib kernel32.lib wsock32.lib ws2_32.lib $(LIBS_W) $(LIBC_RT) LIBS_PEF = /LIBPATH:$(LIB_D) iphlpapi.lib # LIBS_EX+=wsock32.lib user32.lib gdi32.lib HEADER=ipmicmd.h imb_api.h ipmilan.h ipmidir.h ipmilanplus.h \ ipmiutil.h SHOWSEL = showsel TARG_EXE=ievents.exe $(SHOWSEL)msg.dll ipmi_sample.exe ipmi_sample2.exe ipmi_sample_evt.exe $(SAMP_DLL) # alarms.exe ihealth.exe $(SHOWSEL).exe $(SHOWSEL)msg.dll \ # ireset.exe ifru.exe ilan.exe iserial.exe wdt.exe \ # getevent.exe sensor.exe icmd.exe isolconsole.exe idiscover.exe \ # ievents.exe SAMP_LIB = ipmiutil.lib SAMP_DLL = ipmiutillib.dll E_EXE=ipmiutil.exe E_OBJ=$(TMP_D)\ipmiutil.obj \ $(TMP_D)\ialarms.obj $(TMP_D)\ihealth.obj $(TMP_D)\iwdt.obj \ $(TMP_D)\ireset.obj $(TMP_D)\ifru.obj $(TMP_D)\ilan.obj \ $(TMP_D)\iserial.obj $(TMP_D)\icmd.obj $(TMP_D)\isol.obj \ $(TMP_D)\isolwin.obj $(TMP_D)\AnsiTerm.obj $(TMP_D)\idiscover.obj \ $(TMP_D)\iconfig.obj $(TMP_D)\igetevent.obj $(TMP_D)\isensor.obj \ $(TMP_D)\isel.obj $(TMP_D)\ievents.obj \ $(TMP_D)\ipicmg.obj $(TMP_D)\ifirewall.obj \ $(TMP_D)\iekanalyzer.obj $(TMP_D)\ifru_picmg.obj \ $(TMP_D)\oem_kontron.obj $(TMP_D)\ihpm.obj $(TMP_D)\ifwum.obj \ $(TMP_D)\oem_fujitsu.obj $(TMP_D)\oem_intel.obj $(TMP_D)\oem_lenovo.obj \ $(TMP_D)\oem_asus.obj $(TMP_D)\iuser.obj \ $(TMP_D)\oem_sun.obj $(TMP_D)\oem_dell.obj $(TMP_D)\oem_hp.obj \ $(TMP_D)\oem_supermicro.obj $(TMP_D)\itsol.obj $(TMP_D)\idcmi.obj \ $(TMP_D)\oem_quanta.obj $(TMP_D)\oem_newisys.obj $(CMD_OBJ) mem_if.obj ################################################################### all: banner $(TMP_D) exe banner: @echo Building ipmiutil $(TMP_D): $(MKDIR) $(TMP_D) @echo created $(TMP_D) lib: $(L2_OBJ) cd $(LIB_D) nmake /nologo -f ipmilib.mak cd ../util exe: $(E_EXE) $(TARG_EXE) install: $(MKDIR) $(INSTALLTOP) $(MKDIR) $(INSTALLTOP)\bin $(CP) $(E_EXE) $(INSTALLTOP)\bin xcopy $(TARG_EXE) $(INSTALLTOP)\bin xcopy *.dll $(INSTALLTOP)\bin clean: $(RM) *.obj 2>NUL $(RM) $(TARG_EXE) 2>NUL $(RM) *.exe 2>NUL -$(RM) $(TMP_D)\*.obj 2>NUL distclean: $(RM) *.obj 2>NUL $(RM) $(TARG_EXE) 2>NUL $(RM) *.exe 2>NUL -$(RM) $(TMP_D)\*.* 2>NUL rmdir $(TMP_D) 2>NUL $(RM) *.rc 2>NUL $(RM) *.bin 2>NUL $(RM) *.RES 2>NUL $(RM) getopt.* 2>NUL getopt.obj: getopt.c $(CC) /c $(CFLAGS) getopt.c imbapi.obj: imbapi.c $(CC) /c $(CFLAGS_M) imbapi.c ipmicmd.obj: ipmicmd.c $(CC) /c $(CFLAGS) ipmicmd.c ipmilan.obj: ipmilan.c $(CC) /c $(CFLAGS) ipmilan.c ipmilanplus.obj: ipmilanplus.c $(CC) /c $(CFLAGS_M) ipmilanplus.c md5.obj: md5.c $(CC) /c $(CFLAGS) md5.c md2.obj: md2.c $(CC) /c $(CFLAGS) md2.c ievents.obj: ievents.c $(CC) /c $(CFLAGS) ievents.c ialarms.obj: ialarms.c $(CC) /c $(CFLAGS) ialarms.c ihealth.obj: ihealth.c $(CC) /c $(CFLAGS) ihealth.c igetevent.obj: igetevent.c $(CC) /c $(CFLAGS) igetevent.c mem_if.obj: mem_if.c $(CC) /c $(CFLAGS_W) mem_if.c ipmims.obj: ipmims.cpp $(CC) /c $(CFLAGS_W) ipmims.cpp isel.obj: isel.c $(CC) /c $(CFLAGS) isel.c ireset.obj: ireset.c $(CC) /c $(CFLAGS) ireset.c ireset.exe: ireset.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ireset.exe ireset.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) ifru.obj: ifru.c $(CC) /c $(CFLAGS) ifru.c ifru.exe: ifru.obj mem_if.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ifru.exe ifru.obj mem_if.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) ilan.obj: ilan.c $(CC) /c $(CFLAGS) ilan.c ilan.exe: ilan.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ilan.exe ilan.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_PEF) $(LIBS_EX) iserial.obj: iserial.c $(CC) /c $(CFLAGS) iserial.c iserial.exe: iserial.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:iserial.exe iserial.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) isensor.obj: isensor.c $(CC) /c $(CFLAGS) isensor.c isensor.exe: isensor.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:isensor.exe isensor.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) iwdt.obj: iwdt.c $(CC) /c $(CFLAGS) iwdt.c iwdt.exe: iwdt.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:iwdt.exe iwdt.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) isol.obj: isol.c $(CC) /c $(CFLAGS) isol.c isolwin.obj: isolwin.c $(CC) /c $(CFLAGS) isolwin.c isol.exe: isol.obj isolwin.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:isol.exe isol.obj isolwin.obj \ $(CMD_OBJ) $(LF_LANPLUS) $(LIBS_EX) icmd.obj: icmd.c $(CC) /c $(CFLAGS) icmd.c icmd.exe: icmd.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:icmd.exe icmd.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) idiscover.obj: idiscover.c $(CC) /c $(CFLAGS) idiscover.c idiscover.exe: idiscover.obj getopt.obj $(LINK) $(LFLAGS) /OUT:idiscover.exe idiscover.obj getopt.obj \ $(LF_LANPLUS) $(LIBS_EX) ialarms.exe: ialarms.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ialarms.exe ialarms.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) ihealth.exe: ihealth.obj mem_if.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:ihealth.exe ihealth.obj mem_if.obj $(CMD_OBJ) \ $(LF_LANPLUS) $(LIBS_EX) igetevent.exe: igetevent.obj ievents.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:igetevent.exe igetevent.obj ievents.obj \ $(CMD_OBJ) $(LF_LANPLUS) $(LIBS_EX) isel.exe: isel.obj ievents.obj $(CMD_OBJ) $(LINK) $(LFLAGS) /OUT:isel.exe isel.obj ievents.obj \ $(CMD_OBJ) $(LF_LANPLUS) $(LIBS_EX) $(SHOWSEL).mc: $(CP) ..\scripts\$(SHOWSEL).mc . $(SHOWSEL)msg.dll: $(SHOWSEL).mc mc -U $(SHOWSEL).mc rc -r $(SHOWSEL).rc $(LINK) /machine:$(MARCH) -dll -noentry -out:$(SHOWSEL)msg.dll $(SHOWSEL).res mem_if.exe: $(TMP_D)\mem_if.obj $(LINK) $(LFLAGS_W) /OUT:mem_if.exe $(TMP_D)\mem_if.obj $(LIBS_EX) $(TMP_D)\mem_if.obj: mem_if.c $(CC) /c $(CFLAGS_W) /DCOMP_BIN /Fo$(TMP_D)\mem_if.obj mem_if.c ievents.exe: ievents.c $(CC) /c $(CFLAGS) /DALONE ievents.c $(LINK) $(LFLAGS) /OUT:ievents.exe ievents.obj $(LIBS_EX) $(RM) ievents.obj ipmims.exe: ipmims.cpp $(CC) /c $(CFLAGS_W) /DALONE /DTEST_BIN ipmims.cpp $(LINK) $(LFLAGS_W) /OUT:ipmims.exe ipmims.obj $(LIBS_EX) $(RM) ipmims.obj $(TMP_D)\ievents.obj: ievents.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ievents.obj ievents.c $(TMP_D)\ipmiutil.obj: ipmiutil.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ipmiutil.obj ipmiutil.c $(TMP_D)\ialarms.obj: ialarms.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ialarms.obj ialarms.c $(TMP_D)\ihealth.obj: ihealth.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ihealth.obj ihealth.c $(TMP_D)\iconfig.obj: iconfig.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iconfig.obj iconfig.c $(TMP_D)\ipicmg.obj: ipicmg.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ipicmg.obj ipicmg.c $(TMP_D)\ifirewall.obj: ifirewall.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifirewall.obj ifirewall.c $(TMP_D)\ifwum.obj: ifwum.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifwum.obj ifwum.c $(TMP_D)\ihpm.obj: ihpm.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ihpm.obj ihpm.c $(TMP_D)\idcmi.obj: idcmi.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\idcmi.obj idcmi.c $(TMP_D)\iuser.obj: iuser.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iuser.obj iuser.c $(TMP_D)\oem_fujitsu.obj: oem_fujitsu.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_fujitsu.obj oem_fujitsu.c $(TMP_D)\oem_kontron.obj: oem_kontron.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_kontron.obj oem_kontron.c $(TMP_D)\oem_intel.obj: oem_intel.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_intel.obj oem_intel.c $(TMP_D)\oem_sun.obj: oem_sun.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_sun.obj oem_sun.c $(TMP_D)\oem_dell.obj: oem_dell.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_dell.obj oem_dell.c $(TMP_D)\oem_hp.obj: oem_hp.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_hp.obj oem_hp.c $(TMP_D)\oem_supermicro.obj: oem_supermicro.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_supermicro.obj oem_supermicro.c $(TMP_D)\oem_lenovo.obj: oem_lenovo.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_lenovo.obj oem_lenovo.c $(TMP_D)\oem_asus.obj: oem_asus.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_asus.obj oem_asus.c $(TMP_D)\oem_quanta.obj: oem_quanta.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_quanta.obj oem_quanta.c $(TMP_D)\oem_newisys.obj: oem_newisys.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\oem_newisys.obj oem_newisys.c $(TMP_D)\iekanalyzer.obj: iekanalyzer.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iekanalyzer.obj iekanalyzer.c $(TMP_D)\ifru_picmg.obj: ifru_picmg.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifru_picmg.obj ifru_picmg.c $(TMP_D)\ifru.obj: ifru.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ifru.obj ifru.c $(TMP_D)\ireset.obj: ireset.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ireset.obj ireset.c $(TMP_D)\ilan.obj: ilan.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\ilan.obj ilan.c $(TMP_D)\iserial.obj: iserial.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iserial.obj iserial.c $(TMP_D)\isensor.obj: isensor.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isensor.obj isensor.c $(TMP_D)\icmd.obj: icmd.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\icmd.obj icmd.c $(TMP_D)\igetevent.obj: igetevent.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\igetevent.obj igetevent.c $(TMP_D)\isel.obj: isel.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isel.obj isel.c $(TMP_D)\isol.obj: isol.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isol.obj isol.c $(TMP_D)\isolwin.obj: isolwin.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\isolwin.obj isolwin.c $(TMP_D)\itsol.obj: itsol.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\itsol.obj itsol.c $(TMP_D)\AnsiTerm.obj: AnsiTerm.cpp $(CC) /c $(CFLAGS_W) /Fo$(TMP_D)\AnsiTerm.obj AnsiTerm.cpp $(TMP_D)\idiscover.obj: idiscover.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\idiscover.obj idiscover.c $(TMP_D)\iwdt.obj: iwdt.c $(CC) /c $(CFLAGS_M) /Fo$(TMP_D)\iwdt.obj iwdt.c $(E_EXE): $(E_OBJ) $(LINK) $(LFLAGS) /OUT:$(E_EXE) $(E_OBJ) $(LF_LANPLUS) $(LIBS_PEF) $(LIBS_EX) ipmi_sample.obj: ipmi_sample.c $(CC) /c $(CFLAGS_SAM) ipmi_sample.c $(SAMP_LIB): $(CMD_OBJ) mem_if.obj $(CC) /c $(CFLAGS_SAM) ipmilanplus.c $(MKLIB) /OUT:$(SAMP_LIB) /nologo $(CMD_OBJ) mem_if.obj del ipmilanplus.obj $(SAMP_DLL): $(CMD_OBJ) mem_if.obj $(CC) /D_WINDLL /D_USRDLL /c $(CFLAGS_SAM) ipmilanplus.c $(LINK) /DLL $(LFLAGS) /OUT:$(SAMP_DLL) /def:ipmiutillib.def $(CMD_OBJ) mem_if.obj $(LIBS_PEF) $(LF_LANPLUS) $(LIBS_EX) del ipmilanplus.obj ipmi_sample.exe: $(SAMP_LIB) ipmi_sample.obj $(LINK) $(LFLAGS) /OUT:ipmi_sample.exe ipmi_sample.obj $(SAMP_LIB) $(LIBS_PEF) $(LF_LANPLUS) $(LIBS_EX) ipmi_sample2.exe: $(SAMP_LIB) ipmi_sample.c isensor.c ievents.c $(CC) /c $(CFLAGS_SAM) /DGET_SENSORS ipmi_sample.c $(CC) /c $(CFLAGS_SAM) isensor.c $(CC) /c $(CFLAGS_SAM) ievents.c $(LINK) $(LFLAGS) /OUT:ipmi_sample2.exe ipmi_sample.obj isensor.obj ievents.obj $(SAMP_LIB) $(LIBS_PEF) $(LF_LANPLUS) $(LIBS_EX) del isensor.obj ievents.obj ipmi_sample.obj ifruset.obj: ifruset.c $(CC) /c $(CFLAGS_SAM) ifruset.c ifruset.exe: $(SAMP_LIB) ifruset.obj ifru_picmg.obj $(LINK) $(LFLAGS) /OUT:ifruset.exe ifruset.obj ifru_picmg.obj $(SAMP_LIB) $(LIBS_PEF) $(LF_LANPLUS) $(LIBS_EX) ipmi_sample_evt.obj: ipmi_sample_evt.c $(HEADER) $(CC) /c $(CFLAGS_SAM) ipmi_sample_evt.c isensor2.obj: isensor.c isensor.h $(HEADER) $(CC) /c /Foisensor2.obj $(CFLAGS_SAM) isensor.c ievents2.obj: ievents.c ievents.h $(HEADER) $(CC) /c /Foievents2.obj $(CFLAGS_SAM) /DSENSORS_OK ievents.c ipmi_sample_evt.exe: $(SAMP_LIB) ipmi_sample_evt.obj ievents2.obj isensor2.obj $(LINK) $(LFLAGS) $(LF_LANPLUS) /OUT:ipmi_sample_evt.exe ipmi_sample_evt.obj ievents2.obj isensor2.obj $(SAMP_LIB) $(LIBS_PEF) $(LIBS_EX) ipmiutil-3.1.5/util/iekanalyzer.h0000644000076400007640000003455213566765324017133 0ustar mgportalloggers/* * Copyright (c) 2007 Kontron Canada, Inc. All Rights Reserved. * * Base on code from * Copyright (c) 2003 Sun Microsystems, 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: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution 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. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #ifndef IPMI_EKANALYZER_H #define IPMI_EKANALYZER_H #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int #if __WORDSIZE == 64 #define uint64_t unsigned long int #else #define uint64_t unsigned long long #endif #define TRUE 1 #define FALSE 0 #ifndef tboolean #define tboolean int #endif // struct ipmi_intf; #define RTM_FRU_FILE 0x00 #define A1_AMC_FRU_FILE 0x01 #define A2_AMC_FRU_FILE 0x02 #define A3_AMC_FRU_FILE 0x03 #define A4_AMC_FRU_FILE 0x04 #define B1_AMC_FRU_FILE 0x05 #define B2_AMC_FRU_FILE 0x06 #define B3_AMC_FRU_FILE 0x07 #define B4_AMC_FRU_FILE 0x08 #define ON_CARRIER_FRU_FILE 0x09 #define CONFIG_FILE 0x0A #define SHELF_MANAGER_FRU_FILE 0x0B #define MIN_ARGUMENT 0x02 #define RTM_IPMB_L 0x90 #define MAX_FILE_NUMBER 8 /* this voltag is specified in AMC.0 specification Table 3-10 */ #define AMC_VOLTAGE 12 /*volts*/ #define SIZE_OF_GUID 16 #define FRU_RADIAL_IPMB0_LINK_MAPPING 0x15 //struct valstr { // uint16_t val; // const char * str; //}; //const char * val2str(ushort val, const struct valstr *vs); #ifndef OEM_FRU_H #define OEM_FRU_H #define GET_FRU_INFO 0x10 #define GET_FRU_DATA 0x11 #define SET_FRU_DATA 0x12 enum { FRU_CHASSIS_PARTNO, FRU_CHASSIS_SERIAL, FRU_BOARD_MANUF, FRU_BOARD_PRODUCT, FRU_BOARD_SERIAL, FRU_BOARD_PARTNO, FRU_PRODUCT_MANUF, FRU_PRODUCT_NAME, FRU_PRODUCT_PARTNO, FRU_PRODUCT_VERSION, FRU_PRODUCT_SERIAL, FRU_PRODUCT_ASSET, }; struct fru_area_chassis { uint8_t area_ver; uint8_t type; uint16_t area_len; char * part; char * serial; }; struct fru_area_board { uint8_t area_ver; uint8_t lang; uint16_t area_len; uint32_t mfg_date_time; char * mfg; char * prod; char * serial; char * part; char * fru; }; struct fru_area_product { uint8_t area_ver; uint8_t lang; uint16_t area_len; char * mfg; char * name; char * part; char * version; char * serial; char * asset; char * fru; }; #pragma pack(1) struct fru_info { uint16_t size; uint8_t access:1; }; //__attribute__ ((packed)); struct fru_header { uint8_t version; struct { uint8_t internal; uint8_t chassis; uint8_t board; uint8_t product; uint8_t multi; } offset; uint8_t pad; uint8_t checksum; }; //__attribute__ ((packed)); struct fru_multirec_header { #define FRU_RECORD_TYPE_POWER_SUPPLY_INFORMATION 0x00 #define FRU_RECORD_TYPE_DC_OUTPUT 0x01 #define FRU_RECORD_TYPE_DC_LOAD 0x02 #define FRU_RECORD_TYPE_MANAGEMENT_ACCESS 0x03 #define FRU_RECORD_TYPE_BASE_COMPATIBILITY 0x04 #define FRU_RECORD_TYPE_EXTENDED_COMPATIBILITY 0x05 #define FRU_RECORD_TYPE_OEM_EXTENSION 0xc0 uint8_t type; uint8_t format; uint8_t len; uint8_t record_checksum; uint8_t header_checksum; }; //__attribute__ ((packed)); struct fru_multirec_powersupply { #if WORDS_BIGENDIAN uint16_t capacity; #else uint16_t capacity:12; uint16_t __reserved1:4; #endif uint16_t peak_va; uint8_t inrush_current; uint8_t inrush_interval; uint16_t lowend_input1; uint16_t highend_input1; uint16_t lowend_input2; uint16_t highend_input2; uint8_t lowend_freq; uint8_t highend_freq; uint8_t dropout_tolerance; #if WORDS_BIGENDIAN uint8_t __reserved2:3; uint8_t tach:1; uint8_t hotswap:1; uint8_t autoswitch:1; uint8_t pfc:1; uint8_t predictive_fail:1; #else uint8_t predictive_fail:1; uint8_t pfc:1; uint8_t autoswitch:1; uint8_t hotswap:1; uint8_t tach:1; uint8_t __reserved2:3; #endif uint16_t peak_cap_ht; #if WORDS_BIGENDIAN uint8_t combined_voltage1:4; uint8_t combined_voltage2:4; #else uint8_t combined_voltage2:4; uint8_t combined_voltage1:4; #endif uint16_t combined_capacity; uint8_t rps_threshold; }; //__attribute__ ((packed)); struct fru_multirec_dcoutput { #if WORDS_BIGENDIAN uint8_t standby:1; uint8_t __reserved:3; uint8_t output_number:4; #else uint8_t output_number:4; uint8_t __reserved:3; uint8_t standby:1; #endif short nominal_voltage; short max_neg_dev; short max_pos_dev; uint16_t ripple_and_noise; uint16_t min_current; uint16_t max_current; }; //__attribute__ ((packed)); struct fru_multirec_dcload { #if WORDS_BIGENDIAN uint8_t __reserved:4; uint8_t output_number:4; #else uint8_t output_number:4; uint8_t __reserved:4; #endif short nominal_voltage; short min_voltage; short max_voltage; uint16_t ripple_and_noise; uint16_t min_current; uint16_t max_current; }; //__attribute__ ((packed)); struct fru_multirec_oem_header { unsigned char mfg_id[3]; #define FRU_PICMG_BACKPLANE_P2P 0x04 #define FRU_PICMG_ADDRESS_TABLE 0x10 #define FRU_PICMG_SHELF_POWER_DIST 0x11 #define FRU_PICMG_SHELF_ACTIVATION 0x12 #define FRU_PICMG_SHMC_IP_CONN 0x13 #define FRU_PICMG_BOARD_P2P 0x14 #define FRU_AMC_CURRENT 0x16 #define FRU_AMC_ACTIVATION 0x17 #define FRU_AMC_CARRIER_P2P 0x18 #define FRU_AMC_P2P 0x19 #define FRU_AMC_CARRIER_INFO 0x1a #define FRU_UTCA_FRU_INFO_TABLE 0x20 #define FRU_UTCA_CARRIER_MNG_IP 0x21 #define FRU_UTCA_CARRIER_INFO 0x22 #define FRU_UTCA_CARRIER_LOCATION 0x23 #define FRU_UTCA_SHMC_IP_LINK 0x24 #define FRU_UTCA_POWER_POLICY 0x25 #define FRU_UTCA_ACTIVATION 0x26 #define FRU_UTCA_PM_CAPABILTY 0x27 #define FRU_UTCA_FAN_GEOGRAPHY 0x28 #define FRU_UTCA_CLOCK_MAPPING 0x29 #define FRU_UTCA_MSG_BRIDGE_POLICY 0x2A #define FRU_UTCA_OEM_MODULE_DESC 0x2B #define FRU_PICMG_CLK_CARRIER_P2P 0x2C #define FRU_PICMG_CLK_CONFIG 0x2D unsigned char record_id; unsigned char record_version; }; //__attribute__ ((packed)); struct fru_picmgext_guid { unsigned char guid[16]; }; //__attribute__ ((packed)); #ifndef HAVE_FRU_PICMG_EXT #define HAVE_FRU_PICMG_EXT struct fru_picmgext_link_desc { #ifndef WORDS_BIGENDIAN unsigned int desig_channel:6; unsigned int desig_if:2; unsigned int desig_port:4; #define FRU_PICMGEXT_LINK_TYPE_BASE 0x01 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET 0x02 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND 0x03 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR 0x04 #define FRU_PICMGEXT_LINK_TYPE_PCIE 0x05 unsigned int type:8; unsigned int ext:4; unsigned int grouping:8; #else unsigned int grouping:8; unsigned int ext:4; #define FRU_PICMGEXT_LINK_TYPE_BASE 0x01 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET 0x02 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND 0x03 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR 0x04 #define FRU_PICMGEXT_LINK_TYPE_PCIE 0x05 unsigned int type:8; unsigned int desig_port:4; unsigned int desig_if:2; unsigned int desig_channel:6; #endif }; //__attribute__ ((packed)); #define FRU_PICMGEXT_AMC_LINK_TYPE_RESERVED 0x00 #define FRU_PICMGEXT_AMC_LINK_TYPE_RESERVED1 0x01 #define FRU_PICMGEXT_AMC_LINK_TYPE_PCI_EXPRESS 0x02 #define FRU_PICMGEXT_AMC_LINK_TYPE_ADVANCED_SWITCHING1 0x03 #define FRU_PICMGEXT_AMC_LINK_TYPE_ADVANCED_SWITCHING2 0x04 #define FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET 0x05 #define FRU_PICMGEXT_AMC_LINK_TYPE_RAPIDIO 0x06 #define FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE 0x07 /* This is used in command, not in FRU */ struct fru_picmgext_amc_link_info { unsigned char linkInfo[3]; }; //__attribute__ ((packed)); #endif struct fru_picmgext_amc_link_desc_core { #ifndef WORDS_BIGENDIAN unsigned int designator:12; unsigned int type:8; unsigned int ext:4; unsigned int grouping:8; #else unsigned int grouping:8; unsigned int ext:4; unsigned int type:8; unsigned int designator:12; #endif }; //__attribute__ ((packed)); struct fru_picmgext_amc_link_desc_extra { #ifndef WORDS_BIGENDIAN unsigned char asymetricMatch:2; unsigned char reserved:6; #else unsigned char reserved:6; unsigned char asymetricMatch:2; #endif }; //__attribute__ ((packed)); struct fru_picmgext_amc_link_desc { #ifndef WORDS_BIGENDIAN struct fru_picmgext_amc_link_desc_core core;/* lsb */ struct fru_picmgext_amc_link_desc_extra extra; #else struct fru_picmgext_amc_link_desc_extra extra; struct fru_picmgext_amc_link_desc_core core;/* lsb */ #endif }; //__attribute__ ((packed)); #define FRU_PICMGEXT_OEM_SWFW 0x03 #define OEM_SWFW_NBLOCK_OFFSET 0x05 #define OEM_SWFW_FIELD_START_OFFSET 0x06 struct fru_picmgext_chn_desc { #ifndef WORDS_BIGENDIAN unsigned char remote_slot:8; unsigned char remote_chn:5; unsigned char local_chn:5; unsigned char:6; #else unsigned char:6; unsigned char local_chn:5; unsigned char remote_chn:5; unsigned char remote_slot:8; #endif }; //__attribute__ ((packed)); struct fru_picmgext_slot_desc { unsigned char chan_type; unsigned char slot_addr; unsigned char chn_count; }; //__attribute__ ((packed)); #define FRU_PICMGEXT_DESIGN_IF_BASE 0x00 #define FRU_PICMGEXT_DESIGN_IF_FABRIC 0x01 #define FRU_PICMGEXT_DESIGN_IF_UPDATE_CHANNEL 0x02 #define FRU_PICMGEXT_DESIGN_IF_RESERVED 0x03 struct fru_picmgext_carrier_activation_record { unsigned short max_internal_curr; unsigned char allowance_for_readiness; unsigned char module_activation_record_count; }; //__attribute__ ((packed)); struct fru_picmgext_activation_record { unsigned char ibmb_addr; unsigned char max_module_curr; unsigned char reserved; }; //__attribute__ ((packed)); struct fru_picmgext_carrier_p2p_record { unsigned char resource_id; unsigned char p2p_count; }; //__attribute__ ((packed)); struct fru_picmgext_carrier_p2p_descriptor { #ifndef WORDS_BIGENDIAN unsigned char remote_resource_id; unsigned short remote_port:5; unsigned short local_port:5; unsigned short reserved:6; #else unsigned short reserved:6; unsigned short local_port:5; unsigned short remote_port:5; unsigned char remote_resource_id; #endif }; //__attribute__ ((packed)); struct fru_picmgext_amc_p2p_record { #ifndef WORDS_BIGENDIAN unsigned char resource_id :4; unsigned char /* reserved */ :3; unsigned char record_type :1; #else unsigned char record_type :1; unsigned char /* reserved */ :3; unsigned char resource_id :4; #endif }; //__attribute__ ((packed)); struct fru_picmgext_amc_channel_desc_record { #ifndef WORDS_BIGENDIAN unsigned char lane0port :5; unsigned char lane1port :5; unsigned char lane2port :5; unsigned char lane3port :5; unsigned char /*reserved */ :4; #else unsigned char /*reserved */ :4; unsigned char lane3port :5; unsigned char lane2port :5; unsigned char lane1port :5; unsigned char lane0port :5; #endif }; //__attribute__ ((packed)); struct fru_picmgext_amc_link_desc_record { #define FRU_PICMGEXT_AMC_LINK_TYPE_PCIE 0x02 #define FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS1 0x03 #define FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS2 0x04 #define FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET 0x05 #define FRU_PICMGEXT_AMC_LINK_TYPE_RAPIDIO 0x06 #define FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE 0x07 #define AMC_LINK_TYPE_EXT_PCIE_G1_NSSC 0x00 #define AMC_LINK_TYPE_EXT_PCIE_G1_SSC 0x01 #define AMC_LINK_TYPE_EXT_PCIE_G2_NSSC 0x02 #define AMC_LINK_TYPE_EXT_PCIE_G2_SSC 0x03 #define AMC_LINK_TYPE_EXT_ETH_1000_BX 0x00 #define AMC_LINK_TYPE_EXT_ETH_10G_XAUI 0x01 #define AMC_LINK_TYPE_EXT_STORAGE_FC 0x00 #define AMC_LINK_TYPE_EXT_STORAGE_SATA 0x01 #define AMC_LINK_TYPE_EXT_STORAGE_SAS 0x02 #ifndef WORDS_BIGENDIAN unsigned short channel_id :8; unsigned short port_flag_0 :1; unsigned short port_flag_1 :1; unsigned short port_flag_2 :1; unsigned short port_flag_3 :1; unsigned short type :8; unsigned short type_ext :4; unsigned short group_id :8; unsigned char asym_match :2; unsigned char /* reserved */ :6; #else unsigned char /* reserved */ :6; unsigned char asym_match :2; unsigned short group_id :8; unsigned short type_ext :4; unsigned short type :8; unsigned short port_flag_3 :1; unsigned short port_flag_2 :1; unsigned short port_flag_1 :1; unsigned short port_flag_0 :1; unsigned short channel_id :8; #endif }; //__attribute__ ((packed)); #pragma pack() /* FRU Board manufacturing date */ static const uint64_t secs_from_1970_1996 = 820450800; #ifdef NOT_USED static const char * combined_voltage_desc[] = { //__attribute__((unused)) "12 V", "-12 V", "5 V", "3.3 V"}; static const char * chassis_type_desc[] = { //__attribute__((unused)) "Unspecified", "Other", "Unknown", "Desktop", "Low Profile Desktop", "Pizza Box", "Mini Tower", "Tower", "Portable", "LapTop", "Notebook", "Hand Held", "Docking Station", "All in One", "Sub Notebook", "Space-saving", "Lunch Box", "Main Server Chassis", "Expansion Chassis", "SubChassis", "Bus Expansion Chassis", "Peripheral Chassis", "RAID Chassis", "Rack Mount Chassis"}; #endif #endif /* OEM_FRU_H */ #endif /* IPMI_EKANALYZER_H */ ipmiutil-3.1.5/util/ipmilanplus.h0000644000076400007640000000441413566765324017144 0ustar mgportalloggers/* * ipmilanplus.h: (a copy of ipmitool/ipmi_intf.h) * * Copyright (c) 2003 Sun Microsystems, 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: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution 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. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #ifndef IPMILANPLUS_H #define IPMILANPLUS_H #ifdef WIN32 #include #include typedef unsigned char uint8_t; typedef unsigned short int uint16_t; typedef unsigned int uint32_t; typedef int int32_t; typedef uint32_t socklen_t; #else #include #include #include #endif /**************************************/ #define IPMI_BMC_SLAVE_ADDR 0x20 #define IPMI_BUF_SIZE 1024 #ifdef HAVE_LANPLUS #include "../lib/lanplus/lanplus_defs.h" #endif void lanplus_set_sol_data(int insize, int outsize, int port); #endif /* IPMILANPLUS_H */ ipmiutil-3.1.5/util/md2.h0000644000076400007640000003336713566765324015302 0ustar mgportalloggers/* * md2.h * Used in ipmilan.c * * 05/26/2006 ARCress - copied from freeipmi ipmi-md2.c, * added md2_sum() subroutine, added WIN32 flag * 08/14/2008 ARCress - moved md2 routines from md2.c to md2.h */ /* * (c) (C) 2003 FreeIPMI Core Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and * NON-INFRINGEMENT. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. If you * do not wish to do so, delete this exception statement from your * version. If you delete this exception statement from all source * files in the program, then also delete it here. */ /* ==================================================================== * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. 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. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED 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 OpenSSL PROJECT OR * ITS 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. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* only include this file if MD2OK was defined */ #ifdef WIN32 #define u_int32_t unsigned int #define u_int8_t unsigned char #endif /* start ipmi-md2.h */ #define IPMI_MD2_BLOCK_LEN 16 #define IPMI_MD2_BUFFER_LEN 48 #define IPMI_MD2_CHKSUM_LEN 16 #define IPMI_MD2_DIGEST_LEN 16 #define IPMI_MD2_PADDING_LEN 16 #define IPMI_MD2_ROUNDS_LEN 18 typedef struct __md2 { u_int32_t magic; u_int8_t l; unsigned int mlen; u_int8_t x[IPMI_MD2_BUFFER_LEN]; u_int8_t c[IPMI_MD2_CHKSUM_LEN]; u_int8_t m[IPMI_MD2_BLOCK_LEN]; } ipmi_md2_t; int ipmi_md2_init(ipmi_md2_t *ctx); int ipmi_md2_update_data(ipmi_md2_t *ctx, u_int8_t *buf, unsigned int buflen); int ipmi_md2_finish(ipmi_md2_t *ctx, u_int8_t *digest, unsigned int digestlen); /* end ipmi-md2.h */ static char padding[16][16] = { {0x01}, {0x02,0x02}, {0x03,0x03,0x03}, {0x04,0x04,0x04,0x04}, {0x05,0x05,0x05,0x05,0x05}, {0x06,0x06,0x06,0x06,0x06,0x06}, {0x07,0x07,0x07,0x07,0x07,0x07,0x07}, {0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08}, {0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09}, {0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A}, {0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B}, {0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C}, {0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D}, {0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E}, {0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F}, {0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10} }; static unsigned char S[256] = { 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 }; #define L ctx->l #define X ctx->x #define C ctx->c #define M ctx->m #define Mlen ctx->mlen #define IPMI_MD2_MAGIC 0xf00fd00d int ipmi_md2_init(ipmi_md2_t *ctx) { if (ctx == NULL) { errno = EINVAL; return -1; } ctx->magic = IPMI_MD2_MAGIC; L = 0; Mlen = 0; memset(X, '\0', IPMI_MD2_BUFFER_LEN); memset(C, '\0', IPMI_MD2_CHKSUM_LEN); memset(M, '\0', IPMI_MD2_BLOCK_LEN); return 0; } static void _ipmi_md2_update_digest_and_checksum(ipmi_md2_t *ctx) { int j, k; u_int8_t c, t; /* Update X */ for (j = 0; j < IPMI_MD2_BLOCK_LEN; j++) { X[16+j] = M[j]; X[32+j] = (X[16+j] ^ X[j]); } t = 0; for (j = 0; j < IPMI_MD2_ROUNDS_LEN; j++) { for (k = 0; k < IPMI_MD2_BUFFER_LEN; k++) { t = X[k] = (X[k] ^ S[t]); } t = (t + j) % 256; } /* Update C and L */ /* achu: Note that there is a typo in the RFC 1319 specification. * In section 3.2, the line: * * Set C[j] to S[c xor L] * * should read: * * Set C[j] to C[j] xor S[c xor L]. */ for (j = 0; j < IPMI_MD2_BLOCK_LEN; j++) { c = M[j]; C[j] = C[j] ^ S[c ^ L]; L = C[j]; } } int ipmi_md2_update_data(ipmi_md2_t *ctx, u_int8_t *buf, unsigned int buflen) { if (ctx == NULL || ctx->magic != IPMI_MD2_MAGIC || buf == NULL) { errno = EINVAL; return -1; } if (buflen == 0) return 0; if ((Mlen + buflen) >= IPMI_MD2_BLOCK_LEN) { unsigned int bufcount; bufcount = (IPMI_MD2_BLOCK_LEN - Mlen); memcpy(M + Mlen, buf, bufcount); _ipmi_md2_update_digest_and_checksum(ctx); while ((buflen - bufcount) >= IPMI_MD2_BLOCK_LEN) { memcpy(M, buf + bufcount, IPMI_MD2_BLOCK_LEN); bufcount += IPMI_MD2_BLOCK_LEN; _ipmi_md2_update_digest_and_checksum(ctx); } Mlen = buflen - bufcount; if (Mlen > 0) memcpy(M, buf + bufcount, Mlen); } else { /* Not enough data to update X and C, just copy in data */ memcpy(M + Mlen, buf, buflen); Mlen += buflen; } return buflen; } static void _ipmi_md2_append_padding_and_checksum(ipmi_md2_t *ctx) { unsigned int padlen; int padindex; padlen = IPMI_MD2_PADDING_LEN - Mlen; padindex = padlen - 1; ipmi_md2_update_data(ctx, padding[padindex], padlen); ipmi_md2_update_data(ctx, C, IPMI_MD2_CHKSUM_LEN); } int ipmi_md2_finish(ipmi_md2_t *ctx, u_int8_t *digest, unsigned int digestlen) { if (ctx == NULL || ctx->magic != IPMI_MD2_MAGIC || digest == NULL || digestlen < IPMI_MD2_DIGEST_LEN) { errno = EINVAL; return -1; } _ipmi_md2_append_padding_and_checksum(ctx); memcpy(digest, X, IPMI_MD2_DIGEST_LEN); return IPMI_MD2_DIGEST_LEN; } /* added - ARCress */ void md2_sum(unsigned char *pdata, int sdata, unsigned char *digest) { ipmi_md2_t ctx; ipmi_md2_init(&ctx); ipmi_md2_update_data(&ctx, pdata, sdata); ipmi_md2_finish(&ctx, digest, 16); } /*end md2.h */ ipmiutil-3.1.5/util/oem_sun.h0000644000076400007640000001074613566765324016261 0ustar mgportalloggers/* * oem_sun.h * Handle Sun OEM command functions * * Change history: * 09/02/2010 ARCress - included in source tree * *--------------------------------------------------------------------- */ /* * Copyright (c) 2003 Sun Microsystems, 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: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution 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. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #ifndef IPMI_SUNOEM_H #define IPMI_SUNOEM_H #define IPMI_NETFN_SUNOEM 0x2e #define IPMI_SUNOEM_SET_SSH_KEY 0x01 #define IPMI_SUNOEM_DEL_SSH_KEY 0x02 #define IPMI_SUNOEM_GET_HEALTH_STATUS 0x10 #define IPMI_SUNOEM_SET_FAN_SPEED 0x20 #define IPMI_SUNOEM_LED_GET 0x21 #define IPMI_SUNOEM_LED_SET 0x22 #define SDR_RECORD_TYPE_ENTITY_ASSOC 0x08 #define SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR 0x10 //struct valstr { //uint16_t val; //const char * str; //}; // const char * val2str(ushort val, const struct valstr *vs); ushort str2val(const char *str, const struct valstr *vs); #pragma pack(1) struct entity_id { uint8_t id; /* physical entity id */ #if WORDS_BIGENDIAN uint8_t logical : 1; /* physical/logical */ uint8_t instance : 7; /* instance number */ #else uint8_t instance : 7; /* instance number */ uint8_t logical : 1; /* physical/logical */ #endif }; // __attribute__ ((packed)); struct sdr_record_generic_locator { uint8_t dev_access_addr; uint8_t dev_slave_addr; #if WORDS_BIGENDIAN uint8_t channel_num:3; uint8_t lun:2; uint8_t bus:3; #else uint8_t bus:3; uint8_t lun:2; uint8_t channel_num:3; #endif #if WORDS_BIGENDIAN uint8_t addr_span:3; uint8_t __reserved1:5; #else uint8_t __reserved1:5; uint8_t addr_span:3; #endif uint8_t __reserved2; uint8_t dev_type; uint8_t dev_type_modifier; struct entity_id entity; uint8_t oem; uint8_t id_code; uint8_t id_string[16]; }; // __attribute__ ((packed)); struct sdr_record_entity_assoc { struct entity_id entity; /* container entity ID and instance */ struct { #if WORDS_BIGENDIAN uint8_t isrange:1; uint8_t islinked:1; uint8_t isaccessable:1; uint8_t __reserved:5; #else uint8_t __reserved:5; uint8_t isaccessable:1; uint8_t islinked:1; uint8_t isrange:1; #endif } flags; uint8_t entity_id_1; /* entity ID 1 | range 1 entity */ uint8_t entity_inst_1; /* entity inst 1 | range 1 first instance */ uint8_t entity_id_2; /* entity ID 2 | range 1 entity */ uint8_t entity_inst_2; /* entity inst 2 | range 1 last instance */ uint8_t entity_id_3; /* entity ID 3 | range 2 entity */ uint8_t entity_inst_3; /* entity inst 3 | range 2 first instance */ uint8_t entity_id_4; /* entity ID 4 | range 2 entity */ uint8_t entity_inst_4; /* entity inst 4 | range 2 last instance */ }; // __attribute__ ((packed)); #pragma pack() int ipmi_sunoem_main(void *, int, char **); int sunoem_led_get(void * intf, uchar * dev, uchar ledtype, uchar *prsp); int sunoem_led_set(void * intf, uchar * dev, uchar ledtype, uchar ledmode); int decode_sensor_sun(uchar *sdr,uchar *reading,char *pstring, int slen); #endif /*IPMI_SUNOEM_H*/ ipmiutil-3.1.5/util/ievents.h0000644000076400007640000000567713566765324016300 0ustar mgportalloggers/* * ievents.h * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2011 Kontron America, Inc. * * 12/12/11 Andy Cress - created */ /*M* Copyright (c) 2011 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 Kontron 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*/ /* Public routines from ievents.c */ int decode_sel_entry( uchar *psel, char *outbuf, int sz); char *decode_entity_id(int id); char *get_sensor_type_desc(uchar stype); char *get_sev_str(int val); void fmt_time(time_t etime, char *buf, int bufsz); int get_sensor_tag(int isdr, int genid, uchar snum, char *tag, uchar *sdr, int szsdr); void format_event(ushort id, time_t timestamp, int sevid, ushort genid, char *ptype, uchar snum, char *psens, char *pstr, char *more, char *outbuf, int outsz); #define DIMM_UNKNOWN "DIMM_unknown" #define DIMM_NUM "DIMM(%d)" /* * set_sel_opts is used to specify options for showing/decoding SEL events. * sensdesc : 0 = simple, no sensor descriptions * 1 = get sensor descriptions from sdr cache * 2 = get sensor descriptions from sensor file (-s) * canon : 0 = normal output * 1 = canonical, delimited output * sdrs : NULL = no sdr cache, dynamically get sdr cache if sensdesc==1 * ptr = use this pointer as existing sdr cache if sensdesc==1 * fdbg : 0 = normal mode * 1 = debug mode * futc : 0 = normal mode * 1 = show raw UTC time */ void set_sel_opts(int sensdsc, int canon, void *sdrs, char fdbg, char futc); /*end ievents.h*/ ipmiutil-3.1.5/util/md5.c0000644000076400007640000003207513566765324015273 0ustar mgportalloggers/* * md5.c * Used in ipmilan.c * * 05/26/2006 ARCress - copied from sf.net/projects/libmd5-rfc/, * added md5-sum() subroutine. */ /* Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. L. Peter Deutsch ghost@aladdin.com */ /* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ /* Independent implementation of MD5 (RFC 1321). This code implements the MD5 Algorithm defined in RFC 1321, whose text is available at http://www.ietf.org/rfc/rfc1321.txt The code is derived from the text of the RFC, including the test suite (section A.5) but excluding the rest of Appendix A. It does not include any code or documentation that is identified in the RFC as being copyrighted. The original and principal author of md5.c is L. Peter Deutsch . Other authors are noted in the change history that follows (in reverse chronological order): 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order either statically or dynamically; added missing #include in library. 2002-03-11 lpd Corrected argument list for main(), and added int return type, in test program and T value program. 2002-02-21 lpd Added missing #include in test program. 2000-07-03 lpd Patched to eliminate warnings about "constant is unsigned in ANSI C, signed in traditional"; made test program self-checking. 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). 1999-05-03 lpd Original version. */ #include /* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ typedef unsigned char md5_byte_t; /* 8-bit byte */ typedef unsigned int md5_word_t; /* 32-bit word */ /* Define the state of the MD5 Algorithm. */ typedef struct md5_state_s { md5_word_t count[2]; /* message length in bits, lsw first */ md5_word_t abcd[4]; /* digest buffer */ md5_byte_t buf[64]; /* accumulate block */ } md5_state_t; void md5_init(md5_state_t *pms); void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); /* end md5.h */ #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ #ifdef ARCH_IS_BIG_ENDIAN # define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) #else # define BYTE_ORDER 0 #endif #define T_MASK ((md5_word_t)~0) #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) #define T3 0x242070db #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) #define T6 0x4787c62a #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) #define T9 0x698098d8 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) #define T13 0x6b901122 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) #define T16 0x49b40821 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) #define T19 0x265e5a51 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) #define T22 0x02441453 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) #define T25 0x21e1cde6 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) #define T28 0x455a14ed #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) #define T31 0x676f02d9 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) #define T35 0x6d9d6122 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) #define T38 0x4bdecfa9 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) #define T41 0x289b7ec6 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) #define T44 0x04881d05 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) #define T47 0x1fa27cf8 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) #define T50 0x432aff97 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) #define T53 0x655b59c3 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) #define T57 0x6fa87e4f #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) #define T60 0x4e0811a1 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) #define T63 0x2ad7d2bb #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) { md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d = pms->abcd[3]; md5_word_t t; #if BYTE_ORDER > 0 /* Define storage only for big-endian CPUs. */ md5_word_t X[16]; #else /* Define storage for little-endian or both types of CPUs. */ md5_word_t xbuf[16]; const md5_word_t *X = NULL; #endif { #if BYTE_ORDER == 0 /* * Determine dynamically whether this is a big-endian or * little-endian machine, since we can use a more efficient * algorithm on the latter. */ static const int w = 1; if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ #endif #if BYTE_ORDER <= 0 /* little-endian */ { /* * On little-endian machines, we can process properly aligned * data without copying it. */ if (!((data - (const md5_byte_t *)0) & 3)) { /* data are properly aligned */ X = (const md5_word_t *)data; } else { /* not aligned */ memcpy(xbuf, data, 64); X = xbuf; } } #endif #if BYTE_ORDER == 0 else /* dynamic big-endian */ #endif #if BYTE_ORDER >= 0 /* big-endian */ { /* * On big-endian machines, we must arrange the bytes in the * right order. */ const md5_byte_t *xp = data; int i; # if BYTE_ORDER == 0 X = xbuf; /* (dynamic only) */ # else # define xbuf X /* (static only) */ # endif for (i = 0; i < 16; ++i, xp += 4) xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); } #endif } #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) /* Round 1. */ /* Let [abcd k s i] denote the operation a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + F(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 0, 7, T1); SET(d, a, b, c, 1, 12, T2); SET(c, d, a, b, 2, 17, T3); SET(b, c, d, a, 3, 22, T4); SET(a, b, c, d, 4, 7, T5); SET(d, a, b, c, 5, 12, T6); SET(c, d, a, b, 6, 17, T7); SET(b, c, d, a, 7, 22, T8); SET(a, b, c, d, 8, 7, T9); SET(d, a, b, c, 9, 12, T10); SET(c, d, a, b, 10, 17, T11); SET(b, c, d, a, 11, 22, T12); SET(a, b, c, d, 12, 7, T13); SET(d, a, b, c, 13, 12, T14); SET(c, d, a, b, 14, 17, T15); SET(b, c, d, a, 15, 22, T16); #undef SET /* Round 2. */ /* Let [abcd k s i] denote the operation a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + G(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 1, 5, T17); SET(d, a, b, c, 6, 9, T18); SET(c, d, a, b, 11, 14, T19); SET(b, c, d, a, 0, 20, T20); SET(a, b, c, d, 5, 5, T21); SET(d, a, b, c, 10, 9, T22); SET(c, d, a, b, 15, 14, T23); SET(b, c, d, a, 4, 20, T24); SET(a, b, c, d, 9, 5, T25); SET(d, a, b, c, 14, 9, T26); SET(c, d, a, b, 3, 14, T27); SET(b, c, d, a, 8, 20, T28); SET(a, b, c, d, 13, 5, T29); SET(d, a, b, c, 2, 9, T30); SET(c, d, a, b, 7, 14, T31); SET(b, c, d, a, 12, 20, T32); #undef SET /* Round 3. */ /* Let [abcd k s t] denote the operation a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ #define H(x, y, z) ((x) ^ (y) ^ (z)) #define SET(a, b, c, d, k, s, Ti)\ t = a + H(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 5, 4, T33); SET(d, a, b, c, 8, 11, T34); SET(c, d, a, b, 11, 16, T35); SET(b, c, d, a, 14, 23, T36); SET(a, b, c, d, 1, 4, T37); SET(d, a, b, c, 4, 11, T38); SET(c, d, a, b, 7, 16, T39); SET(b, c, d, a, 10, 23, T40); SET(a, b, c, d, 13, 4, T41); SET(d, a, b, c, 0, 11, T42); SET(c, d, a, b, 3, 16, T43); SET(b, c, d, a, 6, 23, T44); SET(a, b, c, d, 9, 4, T45); SET(d, a, b, c, 12, 11, T46); SET(c, d, a, b, 15, 16, T47); SET(b, c, d, a, 2, 23, T48); #undef SET /* Round 4. */ /* Let [abcd k s t] denote the operation a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ #define I(x, y, z) ((y) ^ ((x) | ~(z))) #define SET(a, b, c, d, k, s, Ti)\ t = a + I(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 0, 6, T49); SET(d, a, b, c, 7, 10, T50); SET(c, d, a, b, 14, 15, T51); SET(b, c, d, a, 5, 21, T52); SET(a, b, c, d, 12, 6, T53); SET(d, a, b, c, 3, 10, T54); SET(c, d, a, b, 10, 15, T55); SET(b, c, d, a, 1, 21, T56); SET(a, b, c, d, 8, 6, T57); SET(d, a, b, c, 15, 10, T58); SET(c, d, a, b, 6, 15, T59); SET(b, c, d, a, 13, 21, T60); SET(a, b, c, d, 4, 6, T61); SET(d, a, b, c, 11, 10, T62); SET(c, d, a, b, 2, 15, T63); SET(b, c, d, a, 9, 21, T64); #undef SET /* Then perform the following additions. (That is increment each of the four registers by the value it had before this block was started.) */ pms->abcd[0] += a; pms->abcd[1] += b; pms->abcd[2] += c; pms->abcd[3] += d; } void md5_init(md5_state_t *pms) { pms->count[0] = pms->count[1] = 0; pms->abcd[0] = 0x67452301; pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; pms->abcd[3] = 0x10325476; } void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) { const md5_byte_t *p = data; int left = nbytes; int offset = (pms->count[0] >> 3) & 63; md5_word_t nbits = (md5_word_t)(nbytes << 3); if (nbytes <= 0) return; /* Update the message length. */ pms->count[1] += nbytes >> 29; pms->count[0] += nbits; if (pms->count[0] < nbits) pms->count[1]++; /* Process an initial partial block. */ if (offset) { int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); memcpy(pms->buf + offset, p, copy); if (offset + copy < 64) return; p += copy; left -= copy; md5_process(pms, pms->buf); } /* Process full blocks. */ for (; left >= 64; p += 64, left -= 64) md5_process(pms, p); /* Process a final partial block. */ if (left) memcpy(pms->buf, p, left); } void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) { static const md5_byte_t pad[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; md5_byte_t data[8]; int i; /* Save the length before padding. */ for (i = 0; i < 8; ++i) data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); /* Pad to 56 bytes mod 64. */ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); /* Append the length. */ md5_append(pms, data, 8); for (i = 0; i < 16; ++i) digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); } /* added - ARCress */ void md5_sum(unsigned char *pdata, int sdata, unsigned char *digest) { md5_state_t state; md5_init(&state); md5_append(&state, pdata, sdata); md5_finish(&state, digest); } ipmiutil-3.1.5/util/igetevent.c0000644000076400007640000013070313566765324016575 0ustar mgportalloggers/* * igetevent.c * * This utility waits for IPMI Event Messages. * Some server management functions want to trigger custom actions or * alerts when IPMI hardware-related events occur, but do not want to * track all events, just newly occurring events. * The IPMI events also include BIOS events such as Memory and POST errors, * which would not be captured by reading the IPMI sensors. * This utility waits a specified timeout period for any events, and * returns interpreted output for each event. It is designed as a * scriptable command-line utility, but if the timeout is infinite * (-t 0), then this code could be used for a sample service as well. * * There are several methods to do this which are implemented here. * The SEL method (-s): * This method polls the SEL once a second, keeps track of the last * SEL event read, and only new events are processed. This ensures * that in a series of rapid events, all events are received in order, * however, some transition-to-OK events may not be configured to * write to the SEL on certain platforms. * This method is used if getevent -s is specified. * The ReadEventMessageBuffer method (-m getmessage option): * This uses an IPMI Message Buffer in the BMC firmware to read * each new event. This receives any event, but if two events * occur nearly simultaneously, only the most recent of the two * will be returned with this method. An example of simultaneous * events might be, if a fan stops/fails, both the non-critical * and critical fan threshold events would occur at that time. * This is the default method for getevent. It would be used * locally with the Intel IMB driver or with direct/driverless. * The OpenIPMI custom method (-m getmessage_mv option if DRV_MV): * Different IPMI drivers may have varying behavior. For instance, * the OpenIPMI driver uses the IPMI GetMessage commands internally * and does not allow client programs to use those commands. It has * its own custom mechanism, see getevent_mv(). * This method is used locally if the OpenIPMI driver is detected. * The Async Event method (-a): * This only gets certain Asynchronous events, like a shutdown * request from the BMC to an SMS OS service, and get_software_id. * This is supported for Intel IMB driver and OpenIPMI driver only. * This method is only used locally if getevent option -a is used, * and if either MV (openipmi) or IMB driver is loaded. * The ipmiutil_asy init script controls the getevent -a service. * (see DO_ASYNC compile flag comments) * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2005-2006 Intel Corporation. * Copyright (c) 2009 Kontron America, Inc. * * 02/11/05 Andy Cress - created * 05/18/05 Andy Cress - modified bmc_enable bits * 05/26/05 Andy Cress - added call to decode_sel_entry * 09/09/05 Andy Cress - added sensor_type filtering & return type. * 03/16/05 Andy Cress - added loop, and -o for frunOnce * 06/27/06 Andy Cress 1.1 - specific message for cc=0x80 (no data) * 07/18/06 Andy Cress 1.1 - added getevent_mv, etc. * 07/26/06 Andy Cress 1.1 - added msgout() routine for fflush * 08/08/06 Andy Cress 1.2 - added -s for SEL method * 08/08/06 Andy Cress 1.2 - added -s for SEL method * 08/22/06 Andy Cress 1.3 - direct IOs added with ipmiutil-1.7.5 * 09/13/06 Andy Cress 1.4 - handle empty SEL (0xCB), * call syncevent_sel after every new event. * 09/21/07 Andy Cress 1.21 - implemented IMB Async method for remote * OS shutdown via SMS requests. */ /*M* Copyright (c) 2009 Kontron America, Inc. Copyright (c) 2013 Andy Cress All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Kontron 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*/ #ifdef WIN32 #include #include #include #include "getopt.h" #elif defined(DOS) #include #include #include #include #include #include "getopt.h" #else #include #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #include /* for _SC_OPEN_MAX, usu 1024. */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #include #endif #include #include #endif #include #ifdef SOLARIS /* Solaris */ #define HandleType long #elif WIN32 #include "imb_api.h" #define DO_ASYNC 1 #elif LINUX #define LINUX 1 #include "imb_api.h" #define DO_ASYNC 1 #define DO_MVL 1 #elif BSD #define DO_MVL 1 #define HandleType long #else /* other OS */ #define HandleType long #endif #include "ipmicmd.h" #define THREADS_OK 1 #define IMBPTIMEOUT 200 /*200 ms*/ // #define IPMB_CHANNEL 0x00 // #define LAN_CHANNEL 0x02 #define ulong unsigned long #define uint unsigned int #define ushort unsigned short #define uchar unsigned char #define CMD_GET_SOFTWARE_ID 0x00 #define CMD_SMS_OS_REQUEST 0x10 extern int decode_sel_entry(uchar *evt, char *obuf, int sz); /*see ievents.c*/ extern void set_sel_opts(int sensdesc, int canon, void *sdrs, char fdbg, char utc); /* ievents.c */ extern char *get_sensor_type_desc(uchar stype); /*see ievents.c*/ extern int write_syslog(char *msg); /*see isel.c*/ extern char *show_driver_type(int idx); /*see ipmicmd.h*/ extern int get_sdr_cache(uchar **pret); /*see isensor.c*/ extern void free_sdr_cache(uchar *pret); /*see isensor.c*/ /* * Global variables */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil getevent"; #else static char * progver = "3.08"; static char * progname = "igetevent"; #endif static char fdebug = 0; static char fipmilan = 0; static char frunonce = 0; static char futc = 0; static char fAsync = 0; static char fAsyncOK = 0; /*=1 if drvtype detected for it*/ static char fAsyncNOP = 0; /*=1 if skip Async actions*/ static char fbackground = 0; static char frunscript = 0; static char fcanonical = 0; static char fsettime = 0; /* =1 if timeout is set by -t */ static uchar evt_stype = 0xff; /* event sensor type, 0xff = get any events */ static uchar evt_snum = 0xff; /* event sensor num, 0xff = get any events */ static int timeout = 120; /* 120 seconds default timeout */ static int wait_interval = 1; /* 1 second between calls */ static FILE *fdout = NULL; static char *run_script = NULL; static uchar ipmi_maj = 0; static uchar ipmi_min = 0; static HandleType imb_handle = 0; static int drvtype = 0; /* driver_type from ipmicmd.h: 1=Intel_imb, 3=MV_OpenIPMI */ static int vend_id = 0; static int prod_id = 0; static char fselevts = 0; static char fmsgevts = 0; static ushort sel_recid = 0; static uint sel_time = 0; static uchar sms_sa = 0x81; static uchar *sdrs = NULL; #define LAST_REC 0xFFFF #ifdef WIN32 #define IDXFILE "ipmi_evt.idx" static char idxfile[80] = IDXFILE; static char idxfile2[80] = "c:\\ipmi_evt.idx"; static char outfile[80] = "c:\\ipmiutil_evt.log"; #define SHUTDOWN_CMD "shutdown -s -d p:01:01 -t 10" #define REBOOT_CMD "shutdown -r -d p:01:01 -t 10" #else static char idxfile[80] = "/var/lib/ipmiutil/evt.idx"; static char idxfile2[80] = "/usr/share/ipmiutil/evt.idx"; static char outfile[80] = "/var/log/ipmiutil_evt.log"; #define SHUTDOWN_CMD "init 0" // or shutdown now #define REBOOT_CMD "init 6" #endif #ifdef METACOMMAND extern FILE *fpdbg; /*from ipmicmd.c*/ extern FILE *fperr; /*from ipmicmd.c*/ #endif /* prototypes */ static void iclose(void); static void ievt_siginit(void); static void ievt_cleanup(void); #define METHOD_UNKNOWN 0 #define METHOD_SEL_EVTS 1 #define METHOD_MSG_GET 2 #define METHOD_MSG_MV 3 #define METHOD_ASYNC_MV 4 #define METHOD_ASYNC_IMB 5 static char *methodstr[6] = { "unknown", "SEL_events", "GetMessage", "GetMessage_mv", "Async_mv", "Async_imb" }; static int do_wait(int nsec) { int rv = 0; if (nsec > 0) os_usleep(nsec,0); /*declared in ipmicmd.h*/ return(rv); } static int get_event_receiver(uchar *sa, uchar *lun) { uchar rdata[30]; int rlen; uchar ccode; int ret; rlen = 2; #if 0 ret = ipmi_cmdraw( 0x01,NETFN_SEVT,BMC_SA,PUBLIC_BUS,BMC_LUN, idata,0, rdata,&rlen,&ccode, fdebug); #endif ret = ipmi_cmd(GET_EVENT_RECEIVER,NULL,0, rdata,&rlen,&ccode, 0); if (ret == 0 && ccode != 0) ret = ccode; if (ret == 0) { *sa = rdata[0]; *lun = rdata[1]; } return(ret); } static int get_msg_flags(uchar *flags) { uchar rdata[8]; int rlen = 1; uchar ccode; int ret; ret = ipmi_cmdraw( 0x31,NETFN_APP,BMC_SA,PUBLIC_BUS,BMC_LUN, NULL,0, rdata,&rlen,&ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; if ((ret == 0) && (flags != NULL)) *flags = rdata[0]; return(ret); } static int set_bmc_enables(uchar enab) { uchar idata[8]; uchar rdata[30]; int rlen; uchar ccode; int ret; idata[0] = enab; rlen = 1; ret = ipmi_cmdraw( 0x2E,NETFN_APP,BMC_SA,PUBLIC_BUS,BMC_LUN, idata,1, rdata,&rlen,&ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; return(ret); } static int get_bmc_enables(uchar *enab) { uchar rdata[30]; int rlen; uchar ccode; int ret; rlen = 1; ret = ipmi_cmdraw( 0x2F,NETFN_APP,BMC_SA,PUBLIC_BUS,BMC_LUN, NULL,0, rdata,&rlen,&ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; if (ret == 0) *enab = rdata[0]; return(ret); } /* * msgout * wrapper for printf() to include fflush */ void msgout(char *pattn, ...) { va_list arglist; if (fdout == NULL) return; va_start( arglist, pattn ); vfprintf( fdout, pattn, arglist ); va_end( arglist ); fflush( fdout ); } #ifdef DO_ASYNC /* The DO_ASYNC flag enables the IMB Async Message method via get_imb_event. * This requires the Intel IMB driver, and is used only for remote shutdown * and software ID events. */ /* The LANDesk library has the same function names as the imbapi.c */ #ifdef LINK_LANDESK #define StartAsyncMesgPoll ia_StartAsyncMesgPoll #define SendAsyncImbpRequest ia_SendAsyncImbpRequest #define GetAsyncImbpMessage ia_GetAsyncImbpMessage #define GetAsyncImbpMessage_Ex ia_GetAsyncImbpMessage_Ex #define IsAsyncMessageAvailable ia_IsAsyncMessageAvailable #define RegisterForImbAsyncMessageNotification ia_RegisterForImbAsyncMessageNotification #define UnRegisterForImbAsyncMessageNotification ia_UnRegisterForImbAsyncMessageNotification #define SendTimedLanMessageResponse_Ex ia_SendTimedLanMessageResponse_Ex #define SendTimedEmpMessageResponse_Ex ia_SendTimedEmpMessageResponse_Ex #endif /*endif LINK_LANDESK*/ typedef struct { uchar rsSa; uchar nfLn; uchar cSum1; uchar rqSa; uchar seqLn; uchar cmd; uchar data[1]; } AsyImbPacket; #ifdef THREADS_OK char message[32]; #ifdef WIN32 HANDLE threadid = NULL; #else pthread_t threadid = 0; #endif #endif #ifdef WIN32 #define ThreadRType DWORD ThreadRType WINAPI pollThread( LPVOID p) #else #define ThreadRType void * ThreadRType pollThread(void *p) #endif { int i; int ret, limit; #ifdef THREADS_OK limit = 0; #else limit = 30; #endif for (i = 0; (limit == 0) || (i < limit); i++) { ret = StartAsyncMesgPoll(); if (fdebug && i < 5) msgout("StartAsyncMesgPoll [%d] ret = %d\n",i,ret); // os_usleep(0,5000); /* poll interval 5 msec */ os_usleep(1,0); /* poll interval 1 sec */ } return((ThreadRType)0); } static int GetBmcLanChannel(uchar *chan) { int ret = 0; int j; int rlen; uchar iData[2]; uchar rData[10]; uchar cc; uchar mtype; uchar chn = 1; if (vend_id == VENDOR_INTEL) { if (prod_id == 0x000C || prod_id == 0x001B) { *chan = 7; return(ret); } } for (j = 1; j < 12; j++) { rlen = sizeof(rData); iData[0] = (uchar)j; /*channel #*/ memset(rData,0,9); /*initialize recv data*/ ret = ipmi_cmd(GET_CHANNEL_INFO, iData, 1, rData, &rlen, &cc, fdebug); if (ret == 0xcc || cc == 0xcc) /* special case for ipmi_lan */ continue; if (ret != 0) { if (fdebug) printf("get_chan_info rc = %x\n",ret); break; } mtype = rData[1]; /* channel medium type */ if (mtype == 4) { /* 802.3 LAN type*/ if (fdebug) printf("chan[%d] = lan\n",j); chn = (uchar)j; break; } } *chan = chn; return(ret); } int SoftwareIdResponse(uchar *buf, int blen, uchar hnd, uchar chan) { int rv = 0; uchar resp[12] = {0,0xa6,0,0,0,1,0,0x00,0x01,0x57,0x00,0x01}; #ifdef WIN32 /* check OS version & arch (32/64) */ #else struct utsname uts; rv = uname(&uts); // uts.release=`uname -r` uts.machine=x86_64,ia64,i586,i386 // kver <= 24 bytes, mach/arch <= 6 bytes #endif #ifdef USE_LANMSG rv = SendTimedLanMessageResponse_Ex( (ImbPacket *)buf, (char *)(&resp), 12, IMBPTIMEOUT, hnd, chan); #else rv = SendTimedEmpMessageResponse_Ex((ImbPacket *)buf, (char *)(&resp), 12, IMBPTIMEOUT, hnd,chan); #endif if (fdebug) msgout("SoftwareIdResponse(%d) ret = %d\n",chan,rv); return(rv); } int SmsOsResponse(uchar *buf, int blen, uchar func, uchar hnd, uchar chan) { int rv = 0; char cc = 0; if (frunscript) { write_syslog("igetevent -a running script\n"); rv = system(run_script); if (fdebug) msgout("run(%s) ret = %d\n",run_script,rv); } switch(func) /*data byte has function*/ { case 0x01: /*shutdown & power down*/ rv = SendTimedEmpMessageResponse_Ex((ImbPacket *)buf, &cc,1, IMBPTIMEOUT, hnd,chan); if (fdebug) msgout("OsResponse(%d) ret = %d\n",chan,rv); if (!fAsyncNOP) { write_syslog("igetevent -a initiating OS shutdown\n"); rv = system(SHUTDOWN_CMD); if (fdebug) msgout("shutdown ret = %d\n",rv); } break; case 0x02: /*shutdown & reset*/ rv = SendTimedEmpMessageResponse_Ex((ImbPacket *)buf, &cc,1, IMBPTIMEOUT, hnd,chan); if (fdebug) msgout("OsResponse(%d) ret = %d\n",chan,rv); if (!fAsyncNOP) { write_syslog("igetevent -a initiating OS reboot\n"); rv = system(REBOOT_CMD); if (fdebug) msgout("reboot ret = %d\n",rv); } break; default: if (fdebug) msgout("igetevent -a unknown function %d\n",func); rv = 1; break; } return(rv); } /* * get_imb_event * This only gets certain IMB events, like * OS requests (e.g. shutdown), and get_software_id */ static int get_imb_event(uchar etype, int timeout, uchar *evt) { int ret = -1; int i; int done = 0; ulong mlen; uchar buffer[512]; uchar sendbuf[18]; static uint asyseqnum = 0; uchar chan; uchar sessHandle = 0; uchar privilege = 0; uchar cmd, func; // uchar *pbuf; ret = GetBmcLanChannel(&chan); /* clean out pre-existing async messages */ while(1) { mlen = sizeof(buffer); if (GetAsyncImbpMessage((ImbPacket *)buffer,&mlen, IMBPTIMEOUT, &asyseqnum, IPMB_CHANNEL) != 0) break; if (fdebug) msgout("cleaned out an IPMB message seq=%d\n",asyseqnum); } while(1) { mlen = sizeof(buffer); if (GetAsyncImbpMessage((ImbPacket *)buffer,&mlen, IMBPTIMEOUT, &asyseqnum, LAN_CHANNEL) != 0) break; if (fdebug) msgout("cleaned out a LAN message seq=%d\n",asyseqnum); } ret = RegisterForImbAsyncMessageNotification(&imb_handle); if (fdebug) msgout("RegisterForImbAsync ret=%d, handle=%x\n",ret,imb_handle); if (ret != 0) { msgout("RegisterAsync error %d\n",ret); return(ret); } for (i = 0; (timeout == 0) || (i < timeout); i++) { /*get one imb event*/ if (fdebug) msgout("IsAsyncMessageAvailable ...\n"); if (IsAsyncMessageAvailable(imb_handle) == 0) { if (fdebug) msgout("Async Message is Available\n"); mlen = sizeof(buffer); ret = GetAsyncImbpMessage_Ex ((ImbPacket *)buffer, &mlen, IMBPTIMEOUT, &asyseqnum, ANY_CHANNEL, &sessHandle, &privilege); /* Hack: buffer contains an extra byte to return channel */ if (fdebug) msgout("GetAsync(%d,%d) ret = %d, newchan=%x\n", asyseqnum,chan,ret,buffer[mlen]); if (ret == 0) { /* get the async message command */ if (fdebug) dump_buf("async msg",buffer,mlen+1,0); chan = buffer[mlen]; if (mlen > 16) mlen = 16; if (buffer[0] == sms_sa) { memcpy(&sendbuf[0],buffer,mlen); } else { /* handle shorter format for some BMCs */ sendbuf[0] = sms_sa; memcpy(&sendbuf[1],buffer,mlen); } cmd = sendbuf[5]; func = sendbuf[6]; msgout("got async msg: cmd=%02x len=%d\n",cmd,mlen); memcpy(evt,sendbuf,mlen); switch(cmd) { case CMD_GET_SOFTWARE_ID: /*Get Software ID*/ ret = SoftwareIdResponse(sendbuf,mlen,sessHandle,chan); break; case CMD_SMS_OS_REQUEST: /*SMS OS Request*/ ret = SmsOsResponse(sendbuf,mlen,func,sessHandle,chan); if (ret == 0) done = 1; break; default: ret = LAN_ERR_INVPARAM; msgout("SmsOS cmd %02x unknown, ret = %d\n",cmd,ret); } if (fdebug) msgout("async msg cmd=%02x ret = %d\n",cmd,ret); if (done == 1) { if (func == 0x01) msgout("shutting down\n"); else msgout("rebooting\n"); ret = 0x81; break; } } } /*endif have an event*/ else ret = 0x80; /* no event yet */ } /*loop for one event*/ if (fdebug) msgout("Unregister for imb events\n"); UnRegisterForImbAsyncMessageNotification (imb_handle,0); return(ret); } #endif /*endif DO_ASYNC*/ #ifdef DO_MVL /* Linux, enable MV OpenIPMI interface */ extern int register_async_mv(uchar cmd, uchar netfn); /*see ipmimv.c*/ extern int unregister_async_mv(uchar cmd, uchar netfn); /*see ipmimv.c*/ extern int getevent_mv(uchar *evt_data, int *evt_len, uchar *cc, int t); extern int ipmi_rsp_mv(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, char fdebugcmd); static int send_mv_asy_resp(uchar *evt) { uchar cmd, sa, bus, cc; uchar data0[12] = {0,0xa6,0,0,0,1,0,0x00,0x01,0x57,0x00,0x01}; uchar data1[1] = { 0x00 }; uchar rdata[80]; int sdata, rlen, i; uchar *pdata; int rv = -1; cmd = evt[2]; sa = sms_sa; /* sa = SMS_SA (0x81) */ bus = 0x01; /* usu lan_ch == 1 */ switch(cmd) { case CMD_GET_SOFTWARE_ID: /*software id*/ pdata = &data0[0]; sdata = sizeof(data0); break; case CMD_SMS_OS_REQUEST: /*restart*/ pdata = &data1[0]; sdata = sizeof(data1); break; default: rv = LAN_ERR_INVPARAM; return (rv); break; } rv = ipmi_rsp_mv(cmd, (NETFN_APP | 0x01), sa, bus, BMC_LUN, pdata,sdata, fdebug); if (rv == 0) { for (i = 0; i < 5; i++) { rlen = sizeof(rdata); rv = getevent_mv(rdata,&rlen,&cc,1); if (fdebug) msgout("send_mv_asy_resp: rv=%d cc=%x\n",rv,cc); if (rv == 0 && cc == 0) { if (fdebug) msgout("got rsp ccode: type=%02x len=%d cc=%x\n", rdata[0],rlen,rdata[3]); if (rlen > 0) rv = rdata[3]; /*cc*/ break; } os_usleep(0,5000); /*wait 5 ms*/ } } return (rv); } static int get_mv_asy_event(uchar cmd, int timeout, uchar *evt) { int ret = -1; int rv = -1; uchar cc = 0; uchar rdata[120]; int rlen, i; rv = register_async_mv(cmd,NETFN_APP); /*reserved,GetSoftwareID*/ if (rv != 0) return(rv); for (i = 0; (timeout == 0) || (i < timeout); i++) { /*get one async event*/ rv = getevent_mv(rdata,&rlen,&cc,timeout); if (fdebug) msgout("get_mv_asy_event: i=%d cmd=%x rv=%d cc=%x\n",i,cmd,rv,cc); if (rv == 0 && cc == 0) { msgout("got async msg: type=%02x cmd=%x len=%d\n", rdata[0],rdata[2],rlen); if (fdebug) dump_buf("async msg",rdata,rlen,0); /* check recv_type == 3 (IPMI_CMD_RECV_TYPE) */ if (rdata[0] == 3 && rdata[2] == cmd) { if (rlen > 16) rlen = 16; memcpy(evt,rdata,rlen); break; } else { /*else msg, but no match*/ rv = ERR_BAD_PARAM; break; } } else do_wait(wait_interval); /*wait 1 sec*/ } ret = unregister_async_mv(cmd,NETFN_APP); /*reserved,GetSoftwareID*/ return(rv); } #endif static int get_evt_method(char *evtmethod) { int method = METHOD_UNKNOWN; if (fAsync) { if (drvtype == DRV_MV) method = METHOD_ASYNC_MV; else /* if (drvtype == DRV_IMB) */ method = METHOD_ASYNC_IMB; } else if (fselevts) method = METHOD_SEL_EVTS; else { /*fmsgevts*/ if (drvtype == DRV_MV) method = METHOD_MSG_MV; else method = METHOD_MSG_GET; } if (evtmethod != NULL) strcpy(evtmethod,methodstr[method]); return(method); } static int get_sel_entry(ushort recid, ushort *nextid, uchar *rec) { uchar ibuf[6]; uchar rbuf[32]; int rlen; ushort xid, id = 0; uchar cc; int rv; ibuf[0] = 0; ibuf[1] = 0; ibuf[2] = (recid & 0x00ff); ibuf[3] = (recid & 0xff00) >> 8; ibuf[4] = 0; ibuf[5] = 0xFF; /*get entire record*/ rlen = sizeof(rbuf); rv = ipmi_cmd(GET_SEL_ENTRY, ibuf, 6, rbuf, &rlen, &cc, fdebug); if (rv == 0) { if (cc != 0) rv = cc; else { /*success*/ xid = rbuf[0] + (rbuf[1] << 8); /*next rec id*/ memcpy(rec,&rbuf[2],16); *nextid = xid; id = rbuf[2] + (rbuf[3] << 8); /*curr rec id*/ /* recid (requested) should match newid (received) */ if (fdebug) { if ((recid != id) && (recid != LAST_REC) && (recid != 0)) { /* the OpenIPMI driver does this sometimes */ msgout("get_sel MISMATCH: recid=%x newid=%x next=%x\n", recid,id,xid); dump_buf("get_sel cmd",ibuf,6,0); dump_buf("get_sel rsp",rbuf,rlen,0); } } } } if (fdebug) msgout("get_sel(%x) rv=%d cc=%x id=%x next=%x\n", recid,rv,cc,id,*nextid); return(rv); } static int startevent_sel(ushort *precid, uint *ptime) { FILE *fd; uchar rec[24]; uint t = 0; ushort r = 0; ushort r2 = 0; int rv = -1; fd = fopen(idxfile,"r"); if (fd == NULL) fd = fopen(idxfile2,"r"); /*handle old location*/ if (fdebug) msgout("start: idxfile=%s fd=%p\n",idxfile,fd); if (fd != NULL) { // Read the file, get savtime & savid rv = fscanf(fd,"%x %x",&t,(uint *)&r); fclose(fd); if (r == LAST_REC) r = 0; rv = 0; /*read it, success*/ } else { /* treat as first time */ r = LAST_REC; rv = get_sel_entry(r,&r2,rec); if (rv == 0) { memcpy(&t,&rec[3],4); r = rec[0] + (rec[1] << 8); /*use current rec id*/ } else r = 0; rv = 1; /*first time*/ } if (fdebug) msgout("start: recid=%x time=%x\n",r,t); *ptime = t; *precid = r; return(rv); } static int syncevent_sel(ushort recid, uint itime) { FILE *fd; int rv; // Rewrite the saved time & record id if (fdebug) msgout("sync: recid=%x time=%x\n",recid,itime); fd = fopen(idxfile,"w"); if (fd == NULL) { msgout("syncevent: cannot open %s for writing\n",idxfile); rv = -1; } else { fprintf(fd,"%x %x\n",itime,recid); fclose(fd); rv = 0; } return(rv); } int getevent_sel(uchar *rdata, int *rlen, uchar *ccode) { uchar rec[24]; int rv = 0; ushort newid; ushort nextid; ushort recid; /* get current last record */ recid = sel_recid; rv = get_sel_entry(recid,&nextid,rec); if (rv == 0xCB && recid == 0) { /* SEL is empty */ *ccode = (uchar)rv; /* save the real ccode */ rv = 0x80; /* this is ok, just keep waiting */ } if (rv == 0) { if (fdebug) msgout("sel ok, id=%x next=%x\n",recid,nextid); if ((nextid == LAST_REC) || (recid == nextid)) { *ccode = 0x80; /*nothing new*/ } else { recid = nextid; /* else get new one */ rv = get_sel_entry(recid,&nextid,rec); if (rv == 0) { /* new event */ newid = rec[0] + (rec[1] << 8); if (drvtype == DRV_MV && recid != newid) { /* handle MV driver bug, try to get next one. */ if (fdebug) msgout("%s bug, record mismatch\n", show_driver_type(DRV_MV)); } if (fdebug) msgout("recid=%x newid=%x next=%x\n", recid,newid,nextid); memcpy(rdata,rec,16); *rlen = 16; *ccode = 0; sel_recid = recid; /*or newid*/ memcpy(&sel_time,&rec[3],4); } } } else { /* Error reading last recid saved */ if (fdebug) msgout("sel recid %x error, rv = %d\n",recid,rv); /* We want to set sel_recid = 0 here for some errors. */ if (rv == 0xCB || rv == 0xCD) { /* empty, or wrong SDR id */ sel_recid = 0; *ccode = (uchar)rv; rv = 0x80; /* wait again */ } } return(rv); } static int get_event(uchar etype, uchar snum, int timeout, uchar *evt, uchar *stype) { int ret = 0; uchar rdata[64]; int rlen; uchar ccode; int fretry; int i; for (i = 0; (timeout == 0) || (i < timeout); i++) { rlen = sizeof(rdata); fretry = 0; ccode = 0; if (fselevts) { ret = getevent_sel(rdata,&rlen,&ccode); } else #ifdef DO_MVL if (drvtype == DRV_MV) { /* if MV OpenIPMI driver (Linux only) */ if (timeout == 0) wait_interval = 0; /* use special MV API instead (see ipmimv.c) */ ret = getevent_mv(rdata,&rlen,&ccode,timeout); } else #endif ret = ipmi_cmd(READ_EVENT_MSGBUF,NULL,0,rdata,&rlen,&ccode,fdebug); /* now we have an event from one of the above methods*/ /* IPMI 1.5 spec, section 18.8 says cc 0x80 means * "data not available (queue/buffer empty)" */ if (ret == 0 && ccode != 0) { ret = ccode; } if (ret == 0x80) { fretry = 1; do_wait(wait_interval); /*wait 1 sec*/ } else { if (ret == 0) { char ismatch = 0; /* parse event types for a specified type */ /* etype param == 0xff means get any event */ /* rdata[10] is sensor_type, rdata[11] is sensor_num */ if ((etype == 0xff) || (etype == rdata[10])) ismatch++; if ((snum == 0xff) || (snum == rdata[11])) ismatch++; if (ismatch == 2) { /*event sensor type matches*/ memcpy(evt,rdata,rlen); *stype = rdata[10]; /* return sensor type */ } else { /* keep looking */ do_wait(wait_interval); continue; } } /* if here, either got one, or need to return error */ break; } } /*end for loop*/ return(ret); } int send_nmi(void) { uchar idata[8]; uchar rdata[30]; int rlen; uchar ccode; int ret; idata[0] = 4; /* do NMI */ rlen = sizeof(rdata); ret = ipmi_cmdraw( CHASSIS_CTL, NETFN_CHAS, BMC_SA,PUBLIC_BUS,BMC_LUN, idata,1, rdata,&rlen,&ccode, fdebug); if (ret == 0 && ccode != 0) ret = ccode; return(ret); } void show_event(uchar *evt,char *obuf, int sz) { int i; char sysbuf[250]; /* obuf should be 132 chars or more */ msgout("event data: "); for (i=0; i<16; i++) msgout("%02x ",evt[i]); msgout("\n"); decode_sel_entry(evt,obuf,sz); msgout(obuf); /*writes to outfile*/ /* write the message to syslog also. */ snprintf(sysbuf,sizeof(sysbuf),"%s: %s",progname,obuf); write_syslog(sysbuf); } static void ievt_cleanup(void) { char obuf[48]; if (fselevts) syncevent_sel(sel_recid,sel_time); snprintf(obuf,sizeof(obuf),"%s exiting.\n",progname); msgout(obuf); write_syslog(obuf); free_sdr_cache(sdrs); iclose(); exit(EXIT_SUCCESS); } #if defined(WIN32) | defined(DOS) /* no daemon code */ static void ievt_siginit(void) { return; } #else /* Linux daemon code */ #include static void ievt_sighnd(int sig) { ievt_cleanup(); exit(EXIT_SUCCESS); } static void ievt_siginit(void); static void ievt_siginit(void) { struct sigaction sact; /* handle signals for cleanup */ sact.sa_handler = ievt_sighnd; sact.sa_flags = 0; sigemptyset(&sact.sa_mask); sigaction(SIGINT, &sact, NULL); sigaction(SIGQUIT, &sact, NULL); sigaction(SIGTERM, &sact, NULL); } static int mkdaemon(int fchdir, int fclose); static int mkdaemon(int fchdir, int fclose) { int fdlimit = sysconf(_SC_OPEN_MAX); /*fdlimit usu = 1024.*/ int fd = 0; fdlimit = fileno(stderr); /*only close files up to stderr*/ switch (fork()) { case 0: break; case -1: return -1; default: _exit(0); /* exit the original process */ } if (setsid() < 0) return -1; /* shouldn't fail */ switch (fork()) { case 0: break; case -1: return -1; default: _exit(0); /* exit the original process */ } if (fchdir) { chdir("/"); /* umask(0022); * leave file creation mask at default (0022) & 0777 */ } if (fclose) { /* Close stdin,stdout,stderr and replace them with /dev/null */ for (fd = 0; fd < fdlimit; fd++) close(fd); open("/dev/null",O_RDWR); dup(0); dup(0); } return 0; } #endif static void iclose() { /* close out any IPMI handles or sessions */ #ifdef THREADS_OK #ifdef WIN32 if (threadid != NULL) CloseHandle(threadid); #else /* thread close not needed in Linux */ #endif #endif ipmi_close_(); if (fbackground && fdout != NULL) fclose(fdout); } #ifdef METACOMMAND int i_getevt(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int ret = 0; int c, j; uchar devrec[16]; uchar event[16]; uchar sa, lun; uchar enables = 0; uchar fevmsgok = 0; uchar sensor_type = 0; uchar msg_flags = 0; FILE *fp; char outbuf[160]; char tmpout[20]; char *sdesc; fdout = stdout; msgout("%s ver %s\n", progname,progver); while ( (c = getopt(argc,argv,"abce:lmn:op:r:st:uvT:V:J:YEF:P:N:R:U:Z:x?")) != EOF ) switch(c) { case 'a': fAsync = 1; /* imb async message method */ /* chenge the output log filename */ sdesc = strstr(outfile,"evt.log"); if (sdesc != NULL) strcpy(sdesc,"asy.log"); break; case 'b': fbackground = 1; break; /* background */ case 'c': fcanonical = 1; break; /* canonical */ case 'e': /* event sensor type */ if (strncmp(optarg,"0x",2) == 0) evt_stype = htoi(&optarg[2]); else evt_stype = atob(optarg); break; case 'l': fAsyncNOP = 1; break; /* do not reset (for testing)*/ case 'm': fmsgevts = 1; break; /* use local getmessage method */ case 'n': /* event sensor num, always hex */ if (strncmp(optarg,"0x",2) == 0) evt_snum = htoi(&optarg[2]); else evt_snum = htoi(&optarg[0]); break; case 'o': frunonce = 1; break; /* only run once for first event */ case 'r': /* run script (or binary) on an event */ run_script = optarg; fp = fopen(run_script,"r"); if (fp == NULL) { printf("cannot open %s\n",run_script); ret = ERR_FILE_OPEN; goto do_exit; } else { fclose(fp); frunscript = 1; } break; case 's': fselevts = 1; break; /* use SEL event method*/ case 't': timeout = atoi(optarg); fsettime = 1; break; /*timeout*/ case 'u': futc = 1; break; case 'x': fdebug = 1; break; /* debug messages */ case 'v': fdebug = 3; break; /* verbose debug with lan */ case 'p': case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: printf("Usage: %s [-abenorsux -t sec -NPRUEFTVY]\n", progname); printf(" where -a use Async method\n"); printf(" -b run in Background\n"); printf(" -c use Canonical/delimited event format\n"); printf(" -e T wait for specific event sensor type T\n"); printf(" -n N wait for specific event sensor num N\n"); printf(" -o run Once for the first event\n"); printf(" -r F Run file F when an event occurs\n"); printf(" -s use SEL event method\n"); printf(" -t N set timeout to N seconds\n"); printf(" -u use raw UTC time\n"); printf(" -x show eXtra debug messages\n"); print_lan_opt_usage(1); ret = ERR_USAGE; goto do_exit; } fipmilan = is_remote(); ret = ipmi_getdeviceid(devrec,16,fdebug); if (ret != 0) { goto do_exit; } else { ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16); prod_id = devrec[9] + (devrec[10] << 8); if (vend_id == VENDOR_INTEL) { if (prod_id == 0x003E) /* NSN2U or CG2100 Urbanna */ sms_sa = 0x41; } } /* get event receiver */ ret = get_event_receiver(&sa ,&lun); if (ret != 0) msgout("event receiver error %d\n",ret); else msgout("event receiver sa = %02x lun = %02x\n",sa,lun); ret = get_bmc_enables(&enables); if (ret != 0) msgout("bmc enables error %d\n",ret); else { msgout("bmc enables = %02x\n",enables); if ((enables & 0x02) == 2) fevmsgok = 1; else fevmsgok = 0; } if (fevmsgok == 0 && !fipmilan) { msgout("Event Message Buffers not enabled.\n"); enables |= 0x0f; /* 0x08=SEL, 0x02=EvtMsgBuf, rest is gravy */ ret = set_bmc_enables(enables); if (ret != 0) { msgout("set_bmc_enables error 0x%x\n",ret); } else msgout("set_bmc_enables success\n"); } if (fipmilan && !fselevts) { msgout("Only the SEL method (-s) is supported over IPMI LAN\n"); ret = LAN_ERR_NOTSUPPORT; goto do_exit; } ret = get_msg_flags(&msg_flags); msgout("igetevent reading sensors ...\n"); write_syslog("igetevent reading sensors ...\n"); ret = get_sdr_cache(&sdrs); // if (!fipmilan) set_sel_opts(1,0, NULL,fdebug); if (fdebug) msgout("get_sdr_cache ret = %d\n",ret); if (ret == 0) set_sel_opts(1, fcanonical, sdrs,fdebug,futc); else ret = 0; /*if error, keep going anyway*/ if (fselevts) { #ifdef WIN32 { /*resolve path of idxfile*/ char *ipath; ipath = getenv("ipmiutildir"); /*ipmiutil directory path*/ if (ipath != NULL) { if (strlen(ipath)+12 < sizeof(idxfile)) { sprintf(idxfile,"%s\\%s",ipath,"\\",IDXFILE); } } } #endif if (fipmilan) { char *node; node = get_nodename(); strcat(idxfile,"-"); strcat(idxfile,node); strcat(idxfile2,"-"); strcat(idxfile2,node); strcat(outfile,"-"); strcat(outfile,node); } ret = startevent_sel(&sel_recid,&sel_time); ret = 0; /*ignore any earlier errors, keep going*/ } drvtype = get_driver_type(); if (fdebug) msgout("driver_type = %d (%s)\n", drvtype,show_driver_type(drvtype)); if (evt_stype == 0xFF) sdesc = "any event"; else sdesc = get_sensor_type_desc(evt_stype); if (evt_snum == 0xFF) tmpout[0] = 0; else sprintf(tmpout,"with snum %02x",evt_snum); if (evt_stype != 0xFF || evt_snum != 0xFF) msgout("Look for event sensor type %02x (%s) %s\n", evt_stype,sdesc,tmpout); #ifdef TEST_SEL /* This is used to verify that the interface returns valid next ids, * and that the get_sel_entry is ok. */ { int i; ushort r, r1, r2; uchar rec[40]; int rv; r = 0; for (i = 0; i < 4; i++) { rv = get_sel_entry(r,&r2,rec); if (rv == 0) { r1 = rec[0] + (rec[1] << 8); /*get current rec id*/ if (fdebug) msgout("get_sel: r=%x r1=%x rnext=%x\n",r,r1,r2); show_event(&rec[0],outbuf,sizeof(outbuf)); r = r2; } else break; } } #endif if (drvtype == DRV_IMB) fAsyncOK = 1; else if (drvtype == DRV_MV) { if (fsettime == 0) timeout = 0; /*DRV_MV default to infinite*/ fAsyncOK = 1; } else fAsyncOK = 0; if (fAsync && (!fAsyncOK)) { msgout("Cannot open %s or %s driver, required for -a\n", show_driver_type(DRV_IMB),show_driver_type(DRV_MV)); ret = ERR_NO_DRV; goto do_exit; } if (fbackground) { /* convert to a daemon if background */ #ifdef WIN32 msgout("Background not implemented for Windows\n"); ret = LAN_ERR_NOTSUPPORT; goto do_exit; #elif defined(DOS) msgout("Background not implemented for DOS\n"); ret = LAN_ERR_NOTSUPPORT; goto do_exit; #else /* make sure we can open the log file before doing mkdaemon */ fdout = fopen(outfile,"a"); if (fdout == NULL) printf("%s: Cannot open %s\n", progname,outfile); else { pid_t p; fclose(fdout); ret = mkdaemon(1,1); if (ret != 0) { msgout("%s: Cannot become daemon, ret = %d\n", progname,ret); goto do_exit; } /* open a log file for messages, set fdout */ fdout = fopen(outfile,"a"); #ifdef METACOMMAND /* make sure driver debug also goes to log */ fpdbg = fdout; fperr = fdout; #endif p = getpid(); msgout("PID %d: %s ver %s\n",p,progname,progver); /*log start message*/ } #endif } ievt_siginit(); if (fAsync && (fAsyncOK)) /*use imb/mv async messages*/ { msgout("Wait for an async event\n"); /* no timeout */ if (drvtype == DRV_IMB) { #ifdef DO_ASYNC #ifdef THREADS_OK #ifdef WIN32 /* Windows threads */ threadid = CreateThread(NULL, 0, &pollThread, NULL, 0, NULL); if (threadid == NULL) pollThread(NULL); #else /* Linux threads */ ret = pthread_create( &threadid, NULL, pollThread, (void*) message); // if (ret == 0) pthread_join( threadid, NULL); // if (ret == 0) pthread_detach( threadid); #endif if (fdebug) msgout("pollThread create ret=%d handle=%x\n",ret,threadid); #else /* no threads */ pollThread(NULL); #endif while (ret == 0) { /*wait for imb message events*/ msgout("Waiting %d seconds for an async event ...\n",timeout); ret = get_imb_event(0xff,timeout,event); if (ret == 0x81) { /*ok, shutting down OS*/ ret = 0; break; } if (frunonce) break; if (timeout == 0 && ret == 0x80) { /*0x80 = no data yet */ if (fdebug) msgout("get_event timeout, no event yet.\n"); do_wait(wait_interval); ret = 0; /*ok, keep going*/ } } #endif } /*endif DRV_IMB*/ #ifdef DO_MVL else { /*DRV_MV*/ int stage; stage = 0; while (stage < 3) { /*wait for mv message events*/ if (fdebug) msgout("Waiting for async_mv event, stage %d\n",stage); if (stage == 0) { ret = get_mv_asy_event(CMD_GET_SOFTWARE_ID,timeout,event); if (fdebug) msgout("got SmsOS GetSWID event ret = %d\n",ret); /* send a reply */ if (ret == 0) ret = send_mv_asy_resp(event); if (ret == 0) stage = 1; /* got the SoftwareID request/response */ else stage = 0; } if (stage == 1) { /* get the reset command */ memset(event,0,sizeof(event)); ret = get_mv_asy_event(CMD_SMS_OS_REQUEST,timeout,event); if (fdebug) msgout("got SmsOS GetSmsOS event ret = %d\n",ret); if (ret == 0) ret = send_mv_asy_resp(event); if (ret == 0) stage = 2; else stage = 0; } if (stage == 2) { /* got the SmsOs request in event */ uchar cmd, func; cmd = event[2]; func = event[3]; if (cmd != CMD_SMS_OS_REQUEST) { /*cmd*/ ret = LAN_ERR_INVPARAM; if (fdebug) msgout("SmsOS cmd %x ret = %d\n",cmd,ret); } else { if (frunscript) { write_syslog("igetevent -a running script\n"); ret = system(run_script); if (fdebug) msgout("run(%s) ret = %d\n",run_script,ret); } if (!fAsyncNOP) switch(func) { /*subfunction*/ case 0x01: /*shutdown & power down*/ write_syslog("igetevent -a OS shutdown\n"); ret = system(SHUTDOWN_CMD); msgout("SmsOs shutdown, ret = %d\n",ret); break; case 0x02: /*shutdown & reboot*/ write_syslog("igetevent -a OS reboot\n"); ret = system(REBOOT_CMD); msgout("SmsOs reboot, ret = %d\n",ret); break; case 0x03: /*send NMI locally*/ write_syslog("igetevent -a NMI\n"); ret = send_nmi(); msgout("SmsOs NMI, ret = %d\n",ret); default: ret = LAN_ERR_INVPARAM; msgout("SmsOS func %02x, ret = %d\n",func,ret); break; } } if (ret == 0) stage = 3; /*done, exit loop*/ else { if (fdebug) msgout("SmsOS error = %d, start over\n",ret); stage = 0; /*start over*/ } } /*endif stage 2*/ } /*end-while*/ } /*end else DRV_MV*/ #endif } else { /*not Async, std IPMI events */ if (fselevts) { msgout("Get IPMI SEL events after ID %04x\n",sel_recid); } else msgout("Get IPMI events from %s driver\n",show_driver_type(drvtype)); j = get_evt_method(tmpout); sprintf(outbuf,"igetevent waiting for events via method %d (%s)\n", j, tmpout); msgout(outbuf); write_syslog(outbuf); /* loop on events here, like a daemon would. */ while (ret == 0) { /*wait for bmc message events*/ msgout("Waiting %d seconds for an event ...\n",timeout); /* note: could also get message flags here */ ret = get_event(evt_stype,evt_snum,timeout,event,&sensor_type); if (fdebug) msgout("get_event ret = %d\n",ret); if (ret == 0) { /* got an event successfully */ msgout("got event id %04x, sensor_type = %02x\n", sel_recid, sensor_type); show_event(event,outbuf,sizeof(outbuf)); if (fselevts) syncevent_sel(sel_recid,sel_time); if (frunscript) { /*run some script for each event*/ char run_cmd[256]; sprintf(run_cmd,"%s \"%s\"\n",run_script,outbuf); j = system(run_cmd); msgout("run(%s $1), ret = %d\n",run_script,j); ret = j; /*if that failed, exit loop*/ } } else { if (ret == 0x80) msgout("get_event timeout\n"); else msgout("get_event error: ret = 0x%x\n",ret); } if (frunonce) break; if (timeout == 0 && ret == 0x80) { /*0x80 = no data yet */ if (fdebug) msgout("get_event timeout, no data yet.\n"); do_wait(wait_interval); ret = 0; /*ok, keep going*/ } } /*end while loop*/ } do_exit: ievt_cleanup(); if (ret == 0x80) ret = 0; // show_outcome(progname,ret); /*inert if background*/ return(ret); } /* end main()*/ /* end getevent.c */ ipmiutil-3.1.5/util/ipmibmc.c0000644000076400007640000001446313566765324016227 0ustar mgportalloggers/*M* // $Workfile: ipmibmc.c $ // $Revision: 1.0 $ // $Modtime: 12 Nov 2008 15:20:14 $ // $Author: arcress at users.sourceforge.net $ // // This implements support for the /dev/bmc interface from // the Solaris 10 IPMI driver. // // 11/12/08 ARC - created *M*/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2008, 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 Corporation 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. *----------------------------------------------------------------------*/ #ifdef SOLARIS #include #include #include #include #include #include #include #include #include #include #include #include #include "ipmicmd.h" /* for uchar, NCMDS */ #define MAX_SEND_SIZE 34 #define MAX_RECV_SIZE 33 #define MIN_RQ_SIZE 2 #define MIN_RS_SIZE 3 #define MAX_BUF_SIZE 256 #define MSG_BUF_SIZE 1024 // #define IOCTL_IPMI_KCS_ACTION 0x01 // #define IOCTL_IPMI_INTERFACE_METHOD 0x02 #define BMC_MSG_REQ 1 #define BMC_MSG_RSP 2 #define BMC_MSG_ERR 3 extern ipmi_cmd_t ipmi_cmds[NCMDS]; static int ipmi_fd = -1; typedef struct bmc_rq { uchar netfn; uchar lun; uchar cmd; uchar dlen; uchar data[MAX_SEND_SIZE]; } bmc_rq_t; typedef struct bmc_rs { uchar netfn; uchar lun; uchar cmd; uchar ccode; uchar dlen; uchar data[MAX_RECV_SIZE]; } bmc_rs_t; typedef struct bmc_ioctl_t { bmc_rq_t req; bmc_rs_t rsp; } bmc_ioctl_t; typedef struct bmc_msg { uchar m_type; /* Message type (1=req, 2=resp, 3=error)*/ uint32 m_id; /* Message ID */ uchar reserved[32]; uchar msg[1]; /* Variable length message data */ } bmc_msg_t; int ipmi_open_bmc(char fdebugcmd) { int rc = -1; char *pdev; if (ipmi_fd != -1) return(0); pdev = "/dev/bmc"; ipmi_fd = open(pdev, O_RDWR); if (ipmi_fd == -1) { if (fdebugcmd) printf("ipmi_open_bmc: cannot open %s, errno=%d\n",pdev,errno); return(rc); } /* dont bother to check for ioctl method, just use putmsg method */ rc = 0; if (fdebugcmd) printf("ipmi_open_bmc: successfully opened bmc\n"); return(rc); } int ipmi_close_bmc(void) { int rc = 0; if (ipmi_fd != -1) { close(ipmi_fd); ipmi_fd = -1; } return(rc); } int ipmi_cmdraw_bmc( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rv = -1; static uint32 msg_seq = 0; int flags = 0; struct strbuf sendbuf; struct strbuf recvbuf; bmc_msg_t *msg; bmc_rq_t *rq; bmc_rs_t *rs; int sz, i; if (sdata > MAX_SEND_SIZE) i = sdata - MAX_SEND_SIZE; else i = 0; sz = (sizeof(bmc_msg_t) - 1) + sizeof(bmc_rq_t) + i; msg = malloc(sz); if (msg == NULL) return(rv); rq = (bmc_rq_t *)&msg->msg[0]; msg->m_type = BMC_MSG_REQ; msg->m_id = msg_seq++; rq->netfn = netfn; rq->lun = lun; rq->cmd = cmd; rq->dlen = sdata; memcpy(rq->data, pdata, sdata); sendbuf.len = sz; sendbuf.buf = (uchar *)msg; if (fdebugcmd) { dump_buf("ipmi_cmdraw_bmc sendbuf",sendbuf.buf,sendbuf.len,0); } rv = putmsg(ipmi_fd, NULL, &sendbuf, 0); if (rv < 0) { perror("BMC putmsg: "); free(msg); return(rv); } free(msg); recvbuf.buf = malloc(MSG_BUF_SIZE); recvbuf.maxlen = MSG_BUF_SIZE; rv = getmsg(ipmi_fd, NULL, &recvbuf, &flags); if (rv < 0) { perror("BMC getmsg: "); free(recvbuf.buf); return(rv); } msg = (bmc_msg_t *)recvbuf.buf; if (fdebugcmd) { dump_buf("ipmi_cmdraw_bmc recvbuf",recvbuf.buf,recvbuf.len,0); } switch (msg->m_type) { case BMC_MSG_RSP: rs = (bmc_rs_t *)&msg->msg[0]; *pcc = rs->ccode; i = rs->dlen; if (i < 0) i = 0; *sresp = i; if (*pcc == 0 && i > 0) memcpy(presp,rs->data,i); rv = 0; break; case BMC_MSG_ERR: default: rv = msg->msg[0]; printf("ipmi_cmdraw_bmc: %s\n", strerror(rv)); break; } free(recvbuf.buf); return(rv); } int ipmi_cmd_bmc(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rc, i; for (i = 0; i < NCMDS; i++) { if (ipmi_cmds[i].cmdtyp == cmd) break; } if (i >= NCMDS) { printf("ipmi_cmd_bmc: Unknown command %x\n",cmd); return(-1); } if (cmd >= CMDMASK) cmd = cmd & CMDMASK; /* unmask it */ rc = ipmi_cmdraw_bmc(cmd, ipmi_cmds[i].netfn, ipmi_cmds[i].lun, ipmi_cmds[i].sa, ipmi_cmds[i].bus, pdata,sdata,presp,sresp,pcc,fdebugcmd); return(rc); } #endif /* end of ipmibmc.c */ ipmiutil-3.1.5/util/idcmi.c0000644000076400007640000007407513566765324015701 0ustar mgportalloggers/* * idcmi.c * Data Center Manageability Interface (DCMI) command support * * Change history: * 11/17/2011 ARCress - created * *--------------------------------------------------------------------- */ /*M* Copyright (c) 2011 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 Kontron 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*/ #ifdef WIN32 #include #include #include "getopt.h" #else #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #include #else #include #include #endif #endif #include #include #include #include #include "ipmicmd.h" #include "isensor.h" #include "idcmi.h" #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil dcmi"; #else static char * progver = "3.08"; static char * progname = "idcmi"; #endif extern char fdebug; /*from ipmicmd.c*/ static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static uchar dcmi_ver = 0x00; /* 0x10, 0x11, or 0x15 */ static uchar fpwm = 0; /* =1 if Power Management supported */ static uchar do_sensors = 0; static uchar set_asset = 0; static uchar set_mcid = 0; static char *asset_new = NULL; static char *mcid_new = NULL; static int asset_len = 0; static int mcid_len = 0; static char mc_id[64]; static char asset[64]; #ifdef NOT /* see idcmi.h */ #define NETFN_DCMI 0x2C #define CMD_DCMI_GET_CAPAB 0x01 #define CMD_DCMI_GET_POWREAD 0x02 #define CMD_DCMI_GET_POWLIMIT 0x03 #define CMD_DCMI_SET_POWLIMIT 0x04 #define CMD_DCMI_ACT_POWLIMIT 0x05 #define CMD_DCMI_GET_ASSETTAG 0x06 #define CMD_DCMI_GET_SENSORINF 0x07 #define CMD_DCMI_SET_ASSETTAG 0x08 #define CMD_DCMI_GET_MCIDSTR 0x09 #define CMD_DCMI_SET_MCIDSTR 0x0A /* for DCMI 1.5 only */ #define CMD_DCMI_SET_THERMLIM 0x0B #define CMD_DCMI_GET_THERMLIM 0x0C #define CMD_DCMI_GET_TEMPRDNGS 0x10 #define CMD_DCMI_SET_CONFIG 0x12 #define CMD_DCMI_GET_CONFIG 0x13 #endif static int dcmi_usage(void) { printf("Usage: %s [-admsx -NUPREFTVY] \n", progname); printf(" -a Set DCMI Asset Tag to this string\n"); printf(" -d Set DCMI MC ID to this string\n"); printf(" -m002000 specific MC (bus 00,sa 20,lun 00)\n"); printf(" -s Get DCMI sensor info\n"); printf(" -x Display extra debug messages\n"); print_lan_opt_usage(1); printf("where is one of:\n"); printf(" info Get DCMI Capabilities, MC ID, asset tag (default)\n"); printf(" power [get] Get Power reading & limit\n"); printf(" power set_limit Set Power limit\n"); printf(" power set_action Set Power limit exception action\n"); printf(" (action = no_action | power_off | log_sel)\n"); printf(" power set_correction Set Power limit correction time (in ms)\n"); printf(" power set_sample Set Power limit sampling period (in sec)\n"); printf(" power activate Activate Power limit\n"); printf(" power deactivate Deactivate Power limit\n"); printf(" thermal Get/Set DCMI Thermal parameters\n"); printf(" config Get/Set DCMI Configuration parameters\n"); printf(" help Show this help message\n"); return(ERR_USAGE); } static int dcmi_get_capab(int param, uchar *pdata, int sdata) { uchar idata[4]; uchar rdata[32]; int rlen; uchar cc; int rv, i; if (pdata == NULL || sdata == 0) return(ERR_BAD_PARAM); idata[0] = 0xDC; idata[1] = (uchar)param; rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_GET_CAPAB, NETFN_DCMI, g_sa, g_bus, g_lun, idata,2, rdata, &rlen, &cc, fdebug); if ((rv != 0) || (cc != 0)) { if (fdebug) printf("dcmi_get_capab(%d): rv = %d, ccode %02x\n",param,rv,cc); if (rv == 0) rv = cc; return(rv); } /* if here, success */ if (fdebug) { /*show raw response*/ printf("dcmi_get_capab(%d): rlen = %d\n",param,rlen); for (i = 0; i < rlen; i++) printf("%02x ",rdata[i]); printf("\n"); } if (rlen > sdata) { if (fdebug) printf("dcmi_get_capab(%d): data truncated from %d to %d\n", param,rlen,sdata); rlen = sdata; } memcpy(pdata,rdata,rlen); return(rv); } static int dcmi_get_power_read(int param, uchar *pdata, int sdata) { uchar idata[5]; uchar rdata[32]; int rlen; uchar cc; int rv, i; if (pdata == NULL || sdata == 0) return(ERR_BAD_PARAM); idata[0] = 0xDC; idata[1] = (uchar)param; /*mode 1 or 2*/ idata[2] = 0x00; idata[3] = 0x00; rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_GET_POWREAD, NETFN_DCMI, g_sa, g_bus, g_lun, idata,4, rdata, &rlen, &cc, fdebug); if (rv == 0) rv = cc; if (fdebug) { /*show raw response*/ printf("dcmi_get_power_read(%d): rv = %d rlen = %d\n",param,rv,rlen); for (i = 0; i < rlen; i++) printf("%02x ",rdata[i]); printf("\n"); } if (rv == 0) { /* if here, success */ if (rlen > sdata) { if (fdebug) printf("dcmi_get_power_read(%d): data truncated from %d to %d\n", param,rlen,sdata); rlen = sdata; } memcpy(pdata,rdata,rlen); } return(rv); } static int dcmi_get_power_limit( uchar *pdata, int sdata) { uchar idata[5]; uchar rdata[32]; int rlen; uchar cc; int rv, i; if (pdata == NULL || sdata == 0) return(ERR_BAD_PARAM); idata[0] = 0xDC; idata[1] = 0x00; idata[2] = 0x00; rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_GET_POWLIMIT, NETFN_DCMI, g_sa, g_bus, g_lun, idata,3, rdata, &rlen, &cc, fdebug); if (rv == 0) rv = cc; if (fdebug) { /*show raw response*/ printf("dcmi_get_power_limit: rv = %d rlen = %d\n",rv,rlen); for (i = 0; i < rlen; i++) printf("%02x ",rdata[i]); printf("\n"); } if (rv == 0) { /* if here, success */ if (rlen > sdata) { if (fdebug) printf("dcmi_get_power_limit: data truncated from %d to %d\n", rlen,sdata); rlen = sdata; } memcpy(pdata,rdata,rlen); } return(rv); } static int dcmi_set_power_limit(int param,int value, uchar *pow, int spow) { int rv = 0; uchar idata[32]; uchar rdata[32]; int rlen; uchar cc; if (spow > 15) spow = 15; memcpy(idata,pow,spow); switch(param) { case CORRECTION_TIME: idata[10]=(uchar)((value >> 24) & 0xff); idata[9] =(uchar)((value >> 16) & 0xff); idata[8] =(uchar)((value >> 8) & 0xff); idata[7] =(uchar)((value) & 0xff); break; case EXCEPTION_ACTION: idata[4] = (uchar)(value & 0xff); break; case POWER_LIMIT: idata[5] = (uchar)(value & 0xff); idata[6] = (uchar)((value >> 8) & 0xff); break; case SAMPLE_PERIOD: idata[14] = (uchar)((value >> 8) & 0xff); idata[13] = (uchar)(value & 0xff); break; default: return ERR_BAD_PARAM; break; } rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_SET_POWLIMIT, NETFN_DCMI, g_sa, g_bus, g_lun, idata,15, rdata, &rlen,&cc, fdebug); if (fdebug) printf("dcmi_set_power_limit(%d,%d): rv = %d cc = %x\n", param,value,rv,cc); if (rv == 0) rv = cc; return (rv); } static int dcmi_power_limit_activate ( int yes) { int rv; uchar idata[5]; uchar rdata[32]; int rlen; uchar cc; if (yes < 0) return (ERR_BAD_PARAM); if (yes > 1) return (ERR_BAD_PARAM); idata[0] = 0xDC; idata[1] = yes; idata[2] = 0x00; idata[3] = 0x00; rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_ACT_POWLIMIT, NETFN_DCMI, g_sa, g_bus, g_lun, idata,4, rdata, &rlen, &cc, fdebug); if (fdebug) printf("dcmi_power_limit_activate(%d): rv = %d cc = %x\n",yes,rv,cc); if (rv == 0) rv = cc; return(rv); } void dcmi_show_power_read(int parm, uchar *cdata, int sdata) { int i; ulong sample_period; time_t t = 0; uchar state; if (fdebug) { /*++++*/ printf("dcmi_show_power_read(%d,%p,%d) called\n",parm,cdata,sdata); for (i = 0; i < sdata; i++) printf("%02x ",cdata[i]); printf("\n"); } if (sdata < 18) { printf("power_read data length %d is too short\n",sdata); return; } if (cdata[0] != 0xDC) { printf("power_read: invalid first data byte (0x%02x)\n",cdata[0]); return; } memcpy(&t,&cdata[9],4); sample_period = cdata[13]; sample_period += (cdata[14] << 8); sample_period += (cdata[15] << 16); sample_period += (cdata[16] << 24); state = cdata[17]; switch(parm) { case 1: /* Mode 1 - System Power Statistics */ printf(" Current Power: %d Watts\n",cdata[1]+(cdata[2]<<8)); printf(" Min Power over sample duration: %d Watts\n",cdata[3]+(cdata[4]<<8)); printf(" Max Power over sample duration: %d Watts\n",cdata[5]+(cdata[6]<<8)); printf(" Avg Power over sample duration: %d Watts\n",cdata[7]+(cdata[8]<<8)); printf(" Timestamp: %s\n",ctime(&t)); printf(" Sampling period: %lu ms\n",sample_period); printf(" Power reading state is: %s\n",(state&0x40)? "active":"not active"); break; case 2: /* Mode 2 - Enhanced System Power Statistics */ printf("Enhanced Power Mode 2 decoding not yet implemented\n"); /* TODO */ // break; default: for (i = 0; i < sdata; i++) printf("%02x ",cdata[i]); printf("\n"); break; } } void dcmi_show_power_limit(uchar *cdata, int sdata, int rv) { ulong correction_time; char *pstr; correction_time = cdata[6]; correction_time += (cdata[7] << 8); correction_time += (cdata[8] << 16); correction_time += (ulong)(cdata[9] << 24); if (rv == 0) pstr = "(active)"; else if (rv == 0x80) pstr = "(inactive)"; else pstr = "(error)"; printf(" Exception Action: "); if (cdata[3] & 0x01) printf("Hard Power off\n"); else if ((cdata[3] & 0x11) == 0x11) printf("SEL logging\n"); else printf("OEM defined\n"); printf(" Power Limit: %d Watts %s\n",cdata[4]+(cdata[5]<<8), pstr); printf(" Correction Time: %lu ms\n", correction_time); printf(" Sampling period: %d sec\n", cdata[12]+(cdata[13]<<8)); } static int dcmi_get_sensorinf(uchar styp, uchar snum, uchar offset, uchar *pdata, int sdata) { uchar idata[5]; uchar rdata[32]; int rlen; uchar cc; int rv, i; if (pdata == NULL || sdata == 0) return(ERR_BAD_PARAM); idata[0] = 0xDC; idata[1] = styp; /*sensor type, 0x01 = Temperature*/ idata[2] = snum; /*sensor number */ idata[3] = 0x00; /*Entity Instance, 0 = all instances*/ idata[4] = offset; /*Entity Instance start/offset */ rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_GET_SENSORINF, NETFN_DCMI, g_sa, g_bus, g_lun, idata,5, rdata, &rlen, &cc, fdebug); if (rv == 0) rv = cc; if (fdebug) { /*show raw response*/ printf("dcmi_get_sensorinf(%d): rlen = %d\n",snum,rlen); for (i = 0; i < rlen; i++) printf("%02x ",rdata[i]); printf("\n"); } if (rv == 0) { /* if here, success */ if (rlen > sdata) { if (fdebug) printf("dcmi_get_sensorinf(%d): data truncated from %d to %d\n", snum,rlen,sdata); rlen = sdata; } memcpy(pdata,rdata,rlen); } return(rv); } static char *entstr(int i) { char *pstr = NULL; switch(i) { case 0: pstr = "Inlet"; break; case 1: pstr = "CPU"; break; case 2: default: pstr = "Baseboard"; break; } return(pstr); } static int dcmi_get_sensors(int styp) { int i, j, n, r, recs; uchar offset, id; uchar dbuf[20]; uchar s1; int rv; uchar *sdrs = NULL; uchar sdr[128]; offset = 0; r = 1; n = 8; s1 = 0x40; /*0x40,0x41,0x42*/ rv = get_sdr_cache(&sdrs); printf("---Sensors---\n"); for (i = 0; i < 3; i++) { rv = dcmi_get_sensorinf(styp,s1+i,offset,dbuf,sizeof(dbuf)); if (rv != 0) break; n = dbuf[1]; recs = dbuf[2]; printf(" %d %s temp sensors: \tn_returned=%d\n",n,entstr(i),recs); for (r = 0; r < n; r += recs) { recs = dbuf[2]; if (recs == 0) break; for (j = 0; j < r; j++) { id = (dbuf[4 + (2*j)] << 8) + dbuf[3 + (2*j)]; if (fdebug) printf("j=%d id=%x \n",j,id); /* get the sensor info for each record id */ rv = find_sdr_next(sdr,sdrs,(id-1)); ShowSDR("",sdr); } offset += recs; rv = dcmi_get_sensorinf(1,s1+i,offset,dbuf,sizeof(dbuf)); if (rv != 0) break; } } if (rv != 0) printf("dcmi_get_sensors(%d,%d) error %d\n",styp,i,rv); free_sdr_cache(sdrs); return(rv); } static int dcmi_get_asset_tag(char *pdata, int sdata, int *dlen) { uchar idata[4]; uchar rdata[32]; int rlen; uchar cc; int n, rv = -1; int sz_chunk = 16; int sz_all; if (pdata == NULL || sdata < 16) return(ERR_BAD_PARAM); memset(pdata,0,sdata); sz_all = sdata; for (n = 0; (n < sdata && n < sz_all); n += sz_chunk) { idata[0] = 0xDC; idata[1] = n; /*offset*/ idata[2] = sz_chunk; /*bytes to read*/ rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_GET_ASSETTAG, NETFN_DCMI, g_sa, g_bus, g_lun, idata,3, rdata, &rlen, &cc, fdebug); if (fdebug) printf("dcmi_get_asset(%d): rv=%d ccode=%02x rlen=%d\n", n,rv,cc,rlen); if (rv == 0) rv = cc; if (rv == 0) { /* if here, success */ if (n == 0) sz_all = rdata[1]; if ((rlen - 2) < sz_chunk) sz_chunk = rlen - 2; if ((n + sz_chunk) > sdata) { if (fdebug) printf("dcmi_get_asset(%d): data truncated from %d to %d\n", n,(n+sz_chunk),sdata); sz_chunk = (sdata - n); } memcpy(&pdata[n],&rdata[2],sz_chunk); } else break; } /*end-for loop*/ pdata[n] = 0; /*stringify*/ if (dlen != NULL) *dlen = n; return(rv); } static int dcmi_get_mc_id(char *pdata, int sdata, int *dlen) { uchar idata[4]; uchar rdata[32]; int rlen; uchar cc; int n, rv = -1; int sz_chunk = 16; int sz_all; if (pdata == NULL || sdata < 16) return(ERR_BAD_PARAM); memset(pdata,0,sdata); sz_all = sdata; for (n = 0; (n < sdata && n < sz_all); n += sz_chunk) { idata[0] = 0xDC; idata[1] = n; /*offset*/ idata[2] = sz_chunk; /*bytes to read*/ rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_GET_MCIDSTR, NETFN_DCMI, g_sa, g_bus, g_lun, idata,3, rdata, &rlen, &cc, fdebug); if (fdebug) printf("dcmi_get_mc_id(%d): rv=%d ccode=%02x rlen=%d\n", n,rv,cc,rlen); if (rv == 0) rv = cc; if (rv == 0) { /* if here, success */ if (n == 0) sz_all = rdata[1]; if ((rlen - 2) < sz_chunk) sz_chunk = rlen - 2; if ((n + sz_chunk) > sdata) { if (fdebug) printf("dcmi_get_mc_id(%d): data truncated from %d to %d\n", n,(n+sz_chunk),sdata); sz_chunk = (sdata - n); } memcpy(&pdata[n],&rdata[2],sz_chunk); } else break; } /*end-for loop*/ pdata[n] = 0; /*stringify*/ if (dlen != NULL) *dlen = n; return(rv); } static int dcmi_set_asset_tag(char *pdata, int sdata) { int rv = -1; uchar idata[32]; uchar rdata[8]; uchar cc; int ilen, rlen, n; int sz_chunk = 16; if (pdata == NULL || sdata < 2) return(ERR_BAD_PARAM); for (n = 0; (n < sdata); n += sz_chunk) { idata[0] = 0xDC; idata[1] = n; /*offset*/ idata[2] = sz_chunk; /*bytes to read*/ memset(&idata[3],0x20,sz_chunk); ilen = 3 + sz_chunk; if ((n + sz_chunk) > sdata) sz_chunk = sdata - n; memcpy(&idata[3],&pdata[n],sz_chunk); rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_SET_ASSETTAG, NETFN_DCMI, g_sa, g_bus, g_lun, idata,ilen, rdata, &rlen, &cc, fdebug); if (rv == 0) { if (fdebug) printf("dcmi_set_asset_tag(%d,%d,%d) cc=%x resp: %02x %02x %02x\n", sdata,n,sz_chunk,cc,rdata[0],rdata[1],rdata[2]); rv = cc; } if (rv != 0) break; } return(rv); } static int dcmi_set_mc_id(char *pdata, int sdata) { int rv = -1; uchar idata[32]; uchar rdata[8]; uchar cc; int ilen, rlen, n; int sz_chunk = 16; if (pdata == NULL || sdata < 2) return(ERR_BAD_PARAM); for (n = 0; (n < sdata); n += sz_chunk) { if ((n + sz_chunk) > sdata) sz_chunk = sdata - n; idata[0] = 0xDC; idata[1] = n; /*offset*/ idata[2] = sz_chunk; /*bytes to read*/ memset(&idata[3],0x20,sz_chunk); ilen = 3 + sz_chunk; if ((n + sz_chunk) > sdata) sz_chunk = sdata - n; memcpy(&idata[3],&pdata[n],sz_chunk); rlen = sizeof(rdata); rv = ipmi_cmdraw( CMD_DCMI_SET_MCIDSTR, NETFN_DCMI, g_sa, g_bus, g_lun, idata,ilen, rdata, &rlen, &cc, fdebug); if (rv == 0) { if (fdebug) printf("dcmi_set_mc_id(%d,%d,%d) resp: %02x %02x %02x\n", sdata,n,sz_chunk,rdata[0], rdata[1], rdata[2]); rv = cc; } if (rv != 0) break; } return(rv); } static int dcmi_show_asset_tag(void) { int rv = -1; rv = dcmi_get_asset_tag(asset,sizeof(asset),&asset_len); if (rv == 0) printf("DCMI Asset Tag: \t%s\n",asset); return(rv); } static int dcmi_show_mc_id(void) { int rv = -1; rv = dcmi_get_mc_id(mc_id,sizeof(mc_id),&mcid_len); if (rv == 0) printf("DCMI Mgt Controller ID: \t%s\n",mc_id); return(rv); } static char *supported[2] = { "Unsupported", "Supported" }; void dcmi_show_capab(int parm, uchar *cdata, int sdata) { char mystr[64] = ""; int i, j, k, n, f; switch(parm) { case 1: printf("DCMI Version: \t%d.%d\n",cdata[1],cdata[2]); dcmi_ver = ((cdata[1] & 0x0f) << 4) + (cdata[2] & 0x0f); if (cdata[5] & 0x01) { fpwm = 1; } else { fpwm = 0; } printf("DCMI Power Management: \t%s\n",supported[fpwm]); if (cdata[6] & 0x01) f = 1; else f = 0; printf("DCMI System Interface Access:\t%s\n",supported[f]); if (cdata[6] & 0x02) f = 1; else f = 0; printf("DCMI Serial TMode Access:\t%s\n",supported[f]); if (cdata[6] & 0x02) f = 1; else f = 0; printf("DCMI Secondary LAN Channel:\t%s\n",supported[f]); break; case 2: mystr[0] = 0; if (cdata[5] & 0x80) strcat(mystr,"Overwrite "); else strcat(mystr,"NoOverwrite "); if (cdata[5] & 0x40) strcat(mystr,"FlushAll "); if (cdata[5] & 0x20) strcat(mystr,"FlushRec"); printf("DCMI SEL Management: \t%s\n",mystr); n = ((cdata[5] & 0x0F) << 8) + cdata[4]; printf("DCMI SEL num entries: \t%d\n",n); i = cdata[8]; printf("DCMI Temperature Polling: \t%d sec\n",i); break; case 3: n = ((cdata[4] & 0xFE) >> 1); printf("DCMI PWM Slave_Address: \t%02x\n",n); n = ((cdata[5] & 0xF0) >> 4); printf("DCMI PWM Channel: \t%02x\n",n); printf("DCMI PWM Dev_Rev: \t%02x\n",(cdata[5] & 0x0F)); break; case 4: printf("DCMI LanPlus primary chan:\t%02x\n",cdata[4]); printf("DCMI LanPlus secondary chan:\t%02x\n",cdata[5]); printf("DCMI Serial channel: \t%02x\n",cdata[6]); break; case 5: n = cdata[4]; if (n > (5 + sdata)) n = sdata - 5; /*truncate*/ for (i = 0; i < n; i++) { j = (cdata[5+i] & 0x0f); k = ((cdata[5+i] & 0xf0) >> 4); switch(k) { case 3: strcpy(mystr,"days"); break; case 2: strcpy(mystr,"hrs"); break; case 1: strcpy(mystr,"min"); break; case 0: default: strcpy(mystr,"sec"); break; } printf("DCMI Power Stats Duration(%d):\t%d %s\n",i,j,mystr); } break; default: printf("DCMI(%d) data: %02x %02x %02x %02x %02x %02x %02x %02x\n", parm,cdata[1],cdata[2],cdata[3],cdata[4], cdata[5], cdata[6], cdata[7], cdata[8]); break; } } static int dcmi_show_all_capab(void) { int rv = -1; int i; uchar cdata[32]; for (i = 1; i <= 5; i++) { /* only read power stats(5) when power management is supported */ if (i == 5 && fpwm == 0) continue; rv = dcmi_get_capab(i, cdata, sizeof(cdata)); if (rv != 0) { if (i == 1 && rv == CC_DCMI_INVALID_COMMAND) { /*0xC1 on first*/ printf("DCMI not supported on this platform\n"); break; } else if (i == 5 && rv == CC_DCMI_RECORD_NOT_PRESENT) /*0xCB*/ rv = 0; /*optional, ignore this error*/ /*else just dont show the param*/ } else dcmi_show_capab(i,cdata,sizeof(cdata)); } /*end-for dcmi_capab loop */ return(rv); } #ifdef METACOMMAND int i_dcmi(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int rv = 0; int c, i; char *s1; uchar cdata[32]; uchar powdata[32]; printf("%s ver %s\n", progname,progver); parse_lan_options('V',"4",0); /*default to admin priv*/ while ( (c = getopt( argc, argv,"a:d:m:p:sT:V:J:EYF:P:N:R:U:Z:x?")) != EOF ) switch (c) { case 'a': set_asset = 1; asset_new = optarg; break; case 'd': set_mcid = 1; mcid_new = optarg; break; case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 's': do_sensors = 1; break; case 'x': fdebug = 1; break; /* debug messages */ case 'p': /* port */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; case '?': return(dcmi_usage()); break; } for (i = 0; i < optind; i++) { argv++; argc--; } if ((argc > 0) && strcmp(argv[0], "help") == 0) { return(dcmi_usage()); } rv = ipmi_getdeviceid( cdata, sizeof(cdata),fdebug); if (rv == 0) { uchar ipmi_maj, ipmi_min; ipmi_maj = cdata[4] & 0x0f; ipmi_min = cdata[4] >> 4; show_devid( cdata[2], cdata[3], ipmi_maj, ipmi_min); } else goto do_exit; if (set_asset) { rv = dcmi_get_asset_tag(asset,sizeof(asset),&asset_len); memset(asset,' ',asset_len); /*fill with spaces*/ asset_len = strlen_(asset_new); if (asset_len >= sizeof(asset)) asset_len = sizeof(asset) - 1; memcpy(asset,asset_new,asset_len); asset[asset_len] = 0; rv = dcmi_set_asset_tag(asset, asset_len); printf("Set DCMI Asset Tag to %s, ret = %d\n",asset_new,rv); } if (set_mcid) { rv = dcmi_get_mc_id(mc_id,sizeof(mc_id),&mcid_len); memset(mc_id,' ',mcid_len); /*fill with spaces*/ mcid_len = strlen_(mcid_new); if (mcid_len >= sizeof(mc_id)) mcid_len = sizeof(mc_id) - 1; memcpy(mc_id,mcid_new,mcid_len); mc_id[mcid_len] = 0; rv = dcmi_set_mc_id(mcid_new, mcid_len); printf("Set DCMI MC ID to %s, ret = %d\n",mcid_new,rv); } if ( (argc == 0) || (strcmp(argv[0], "info") == 0) ) { rv = dcmi_show_all_capab(); if (rv == 0) { rv = dcmi_show_mc_id(); rv = dcmi_show_asset_tag(); if (do_sensors) rv = dcmi_get_sensors(1); /*temp sensors*/ rv = 0; /*ignore errors for optional features*/ } } else { rv = dcmi_get_capab(1, cdata, sizeof(cdata)); if (rv == 0) dcmi_show_capab(1,cdata,sizeof(cdata)); else if (rv == CC_DCMI_INVALID_COMMAND) /*0xC1 on first*/ printf("DCMI not supported on this platform\n"); if (strncmp(argv[0], "power",5) == 0) { if (fpwm == 0) { /*not supported in capab */ printf("DCMI Power functions not supported on this platform.\n"); rv = LAN_ERR_NOTSUPPORT; } else { rv = dcmi_get_power_read(1, cdata, sizeof(cdata)); if (rv == 0) { dcmi_show_power_read(1,cdata,sizeof(cdata)); rv = dcmi_get_power_limit(powdata, sizeof(powdata)); if (rv == 0) dcmi_show_power_limit(powdata,sizeof(powdata),rv); else if (rv == 0x80) { dcmi_show_power_limit(powdata,sizeof(powdata),rv); rv = 0; } } if (argc < 2) ; /*just get, done above*/ else if (strncmp(argv[1],"get",3) == 0) ; /*done above*/ else if (strncmp(argv[1],"set_limit",9) == 0) { if (argc < 3) return(dcmi_usage()); i = atoi(argv[2]); { /*let range checking be done by DCMI*/ rv = dcmi_set_power_limit (POWER_LIMIT, i, powdata,16); switch(rv) { case 0: printf("DCMI Power limit applied successfully.\n"); break; case 0x84: printf("Power limit out of range\n"); break; case 0x85: printf("Correction time out of range\n"); break; case 0x89: printf("Statistics reporting period out of range\n"); break; default: printf("DCMI Power Limit Set error %d\n",rv); break; } if (rv == 0) { rv = dcmi_power_limit_activate(1); printf ("DCMI Power Limit Activate returned %d\n",rv); } } } else if (strncmp(argv[1],"activate",8) == 0) { rv = dcmi_power_limit_activate(1); if (rv == 0) printf ("DCMI Power Limit Activated.\n"); else printf("DCMI Power Limit Activate error %d\n",rv); } else if (strncmp(argv[1],"deactivate",10) == 0) { rv = dcmi_power_limit_activate(0); if (rv == 0) printf("DCMI Power Limit Deactivated.\n"); else printf("DCMI Power Limit Deactivate error %d\n",rv); } else if (strcmp(argv[1],"set_action")==0) { if (argc < 3) return(dcmi_usage()); else if (strcmp(argv[2],"no_action") == 0) rv = dcmi_set_power_limit(EXCEPTION_ACTION,0x00, powdata,16); else if (strcmp(argv[2],"log_sel") == 0) rv = dcmi_set_power_limit(EXCEPTION_ACTION,0x11, powdata,16); else if (strcmp(argv[2],"power_off") == 0) rv = dcmi_set_power_limit(EXCEPTION_ACTION,0x01, powdata,16); else return(dcmi_usage()); if (rv == 0) printf("exception action set successfully.\n"); else printf("set_exception action error %d\n",rv); } else if (strcmp(argv[1],"set_sample")==0) { if (argc < 3) return(dcmi_usage()); i = atoi(argv[2]); if (i != 0) { rv = dcmi_set_power_limit (SAMPLE_PERIOD,i,powdata,16); if (rv == 0x00) printf("sample period set successfully\n"); else if (rv == 0x89) printf("sample period %d out of range\n",i); else printf("set_sample period error %d\n",rv); } else { printf("invalid sample period %d\n",i); rv = ERR_USAGE; } } else if (strcmp(argv[1],"set_correction")==0) { if (argc < 3) return(dcmi_usage()); i = atoi(argv[2]); if (i != 0) { rv = dcmi_set_power_limit(CORRECTION_TIME,i,powdata,16); if (rv == 0x00) printf("correction time set successfully\n"); else if (rv == 0x85) printf("correction time %d out of range\n",i); else { dcmi_usage(); rv = ERR_USAGE; } } else { printf("correction time %d invalid\n",i); rv = ERR_USAGE; } } else { printf("invalid subfunction %s\n",argv[1]); rv = ERR_USAGE; } } /* endif power functions supported */ } else if (strcmp(argv[0], "thermal") == 0) { if (dcmi_ver < 0x15) { /*not supported in DCMI < 1.5 */ printf("DCMI 1.5 Thermal functions not supported on this platform.\n"); rv = LAN_ERR_NOTSUPPORT; } else { rv = dcmi_get_sensors(1); /*temp sensors*/ /* These are DCMI 1.5 commands */ // #define CMD_DCMI_SET_THERMLIM 0x0B // #define CMD_DCMI_GET_THERMLIM 0x0C // #define CMD_DCMI_GET_TEMPRDNGS 0x10 /* TODO: implement these 3 DCMI thermal commands */ printf("DCMI 1.5 Thermal functions not yet implemented\n"); rv = ERR_USAGE; } } else if (strcmp(argv[0], "config") == 0) { if (dcmi_ver < 0x15) { /*not supported in DCMI < 1.5 */ printf("DCMI 1.5 Config functions not supported on this platform.\n"); rv = LAN_ERR_NOTSUPPORT; } else { /* These are DCMI 1.5 commands */ // #define CMD_DCMI_SET_CONFIG 0x12 // #define CMD_DCMI_GET_CONFIG 0x13 /* TODO: implement these 2 DCMI config commands */ printf("DCMI 1.5 Config get/set functions not yet implemented\n"); rv = ERR_USAGE; } } else { return(dcmi_usage()); } } /*else not info command*/ do_exit: ipmi_close_(); return rv; } /* end idcmi.c */ ipmiutil-3.1.5/util/iuser.c0000644000076400007640000002230113566765324015724 0ustar mgportalloggers/* * iuser.c * Handle IPMI user command functions * * Change history: * 03/22/2017 ARCress - included in source tree * *----------------------------------------------------------------------* The BSD License Copyright (c) 2017, Andy Cress. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Intel Corporation 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. *----------------------------------------------------------------------*/ #ifdef WIN32 #include #include #include #include #include "getopt.h" #else #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include "ipmicmd.h" /* global variables */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil user"; #else static char * progver = "3.08"; static char * progname = "iuser"; #endif static char fdebug = 0; static char fcanonical = 0; static char bdelim = '|'; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; extern int verbose; /*see ipmilanplus.c*/ extern void lprintf(int level, const char * format, ...); /*ipmilanplus.c*/ /* from ilan.c */ char *parse_priv(uchar c); int DisableUser (int unum, uchar chan); int SetPasswd(int unum, char *uname, char *upswd, uchar chan, uchar priv); int GetBmcEthDevice(uchar lan_parm, uchar *pchan); int GetUserInfo(uchar unum, uchar chan, uchar *enab, uchar *priv, char *uname, char fdebug); static void printf_user_usage(void) { printf("ipmiutil user Commands:\n"); printf("\tuser list [channel]\n"); printf("\tuser enable [channel]\n"); printf("\tuser disable \n"); printf("\tuser set name \n"); printf("\tuser set password \n"); printf("\tuser set priv [channel]\n"); printf("\t\twhere priv_level: 4=Admin, 3=Operator, 2=User\n"); } /* ipmi_user_list - print out info for users * * @intf: ipmi inteface * @argc: argument count * @argv: argument list * returns 0 on success, -1 on error */ static int ipmi_user_list(void * intf, int argc, char ** argv) { int i,ret = 0; int rv = -1; uchar num = 1; uchar chan = 1; uchar enab, priv; char uname[21]; char *privstr; if (argv[0] != NULL) chan = atoi(argv[0]); else i = GetBmcEthDevice(0xFF, &chan); while (ret == 0) { uname[0] = '\0'; ret = GetUserInfo(num, chan, &enab, &priv, uname, fdebug); if (ret == 0) { privstr = parse_priv(priv); if (fcanonical) printf("User %2d %c chan=%d %c %8s %c %8s %c %s\n", num,bdelim,chan,bdelim,(enab? "enabled": "disabled"), bdelim,privstr,bdelim,uname); else printf("User %2d: chan=%d \t%8s \t%8s \t%s\n", num,chan,(enab? "enabled": "disabled"),privstr,uname); rv = 0; } num++; } return(rv); } /* ipmi_user_enable_disable - enable/disable BMC functions * * @intf: ipmi inteface * @enable: whether to enable or disable * @argc: argument count * @argv: argument list * * returns 0 on success, -1 on error */ static int ipmi_user_enable_disable(void * intf, int enable, int argc, char ** argv) { int i, ret = -1; uchar unum, chan, enab; uchar priv = 3; char uname[21] = {'\0'}; if (argc < 1 || strncmp(argv[0], "help", 4) == 0) { printf_user_usage(); return ERR_USAGE; } if (argv[0] == NULL) { printf_user_usage(); return ERR_USAGE; } unum = atoi(argv[0]); if (argv[1] != NULL) chan = atoi(argv[1]); else i = GetBmcEthDevice(0xFF, &chan); if (enable == 0) { ret = DisableUser(unum, chan); } else { ret = GetUserInfo(unum, chan, &enab, &priv, uname, fdebug); ret = SetPasswd(unum, uname, NULL, chan, priv); } return ret; } /* ipmi_user_reset - reset firmware user to enable everything * * @intf: ipmi inteface * @argc: argument count * @argv: argument list * * returns 0 on success, -1 on error */ static int ipmi_user_set(void * intf, int argc, char ** argv) { int ret = -1; int i, func = -1; char *uname = NULL; char *upass = NULL; uchar unum, chan, enab, dummy; uchar priv = 3; char name[21] = {'\0'}; if ((argc < 2) || (argc > 0 && strncmp(argv[0], "help", 4) == 0)) { printf_user_usage(); return ERR_USAGE; } if ((argv[1] == NULL) || (argv[2] == NULL)) { printf_user_usage(); return ERR_USAGE; } unum = atoi(argv[0]); if (strncmp(argv[1], "name", 4) == 0) { func = 1; uname = argv[2]; } else if (strncmp(argv[1], "password", 8) == 0) { func = 2; upass = argv[2]; } else if (strncmp(argv[1], "priv", 4) == 0) { func = 3; priv = atoi(argv[2]); } else { printf_user_usage(); return(ERR_USAGE); } if (argv[3] != NULL) chan = atoi(argv[3]); else i = GetBmcEthDevice(0xFF, &chan); switch(func) { case 1: /*set name*/ ret = GetUserInfo(unum, chan, &enab, &priv, name, fdebug); ret = SetPasswd(unum, uname, upass, chan, priv); break; case 2: /*set password*/ ret = GetUserInfo(unum, chan, &enab, &priv, name, fdebug); if (ret == 0) uname = name; ret = SetPasswd(unum, uname, upass, chan, priv); break; case 3: /*set priv*/ ret = GetUserInfo(unum, chan, &enab, &dummy, name, fdebug); if (ret == 0) uname = name; ret = SetPasswd(unum, uname, upass, chan, priv); break; } return ret; } #ifdef METACOMMAND int i_user(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { void *intf = NULL; int rc = 0; int c, i; char *s1; printf("%s ver %s\n", progname,progver); parse_lan_options('V',"4",0); /*default to admin priv*/ while ( (c = getopt( argc, argv,"cm:T:V:J:EYF:P:N:R:U:Z:x?")) != EOF ) switch (c) { case 'c': fcanonical = 1; break; case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'x': fdebug = 1; verbose = 1; break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; case '?': print_lan_opt_usage(0); printf_user_usage(); return ERR_USAGE; break; } for (i = 0; i < optind; i++) { argv++; argc--; } if (argc < 1 || strncmp(argv[0], "help", 4) == 0) { printf_user_usage(); } else if (strncmp(argv[0], "list", 4) == 0) { rc = ipmi_user_list(intf, argc-1, &(argv[1])); } else if (strncmp(argv[0], "enable", 6) == 0) { rc = ipmi_user_enable_disable(intf, 1, argc-1, &(argv[1])); } else if (strncmp(argv[0], "disable", 7) == 0) { rc = ipmi_user_enable_disable(intf, 0, argc-1, &(argv[1])); } else if (strncmp(argv[0], "set", 3) == 0) { rc = ipmi_user_set(intf, argc-1, &(argv[1])); } else { printf_user_usage(); rc = ERR_BAD_PARAM; } ipmi_close_(); return rc; } ipmiutil-3.1.5/util/ipmimv.c0000644000076400007640000006027713566765324016114 0ustar mgportalloggers/*M* // PVCS: // $Workfile: ipmimv.c $ // $Revision: 1.1 $ // $Modtime: 08 Apr 2003 15:31:14 $ // $Author: arcress at users.sourceforge.net $ // // This implements support for the /dev/ipmi0 native interface from // the MontaVista OpenIPMI Linux driver. // // To build this as a standalone test program, do this: // # gcc -DLINUX -g -O2 -DTEST_BIN -o ipmimv ipmimv.c // // 01/29/03 ARC - created, derived from ipmi_test.c and ipmitool_mv.c // 04/08/03 ARC - don't watch stdin on select, since stdin may not be // valid if invoked from cron, etc. // 06/11/03 ARC - ignore EMSGSIZE errno for get_wdt command // 05/05/04 ARC - only open/close device once per application, // rely on each app calling ipmi_close, helps performance. // 08/10/04 ARC - handle alternate device filenames for some 2.6 kernels // 03/01/05 ARC - fix /dev/ipmi0 IPMB requests (to other than BMC_SA) // 04/12/07 ARC - check for IPMI_ASYNC_EVENT_RECV_TYPE in ipmicmd_mv *M*/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2002-2005, 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 Corporation 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. *----------------------------------------------------------------------*/ #if defined(LINUX) || defined(BSD) || defined(MACOS) || defined(HPUX) #include #include #include #include #include #include #include #include #include #include #if defined(MACOS) #include #else #include #endif #ifdef SCO_UW #include #endif #ifdef TEST_BIN #define ALONE 1 #endif static void dbgmsg(char *pattn, ...); #ifdef ALONE #define uchar unsigned char #define ACCESS_OK 0 #define GET_SEL_ENTRY 0x43 static FILE *fperr = NULL; static FILE *fpdbg = NULL; void dump_buf(char *tag,uchar *pbuf,int sz, char fshowascii) { if (pbuf == NULL || sz == 0) return; dbgmsg("%s sz=%d buf: %02x %02x %02x %02x\n",tag,sz, pbuf[0],pbuf[1], pbuf[2],pbuf[3]); } #else #include "ipmicmd.h" extern FILE *fperr; /*defined in ipmicmd.c*/ extern FILE *fpdbg; /*defined in ipmicmd.c*/ extern ipmi_cmd_t ipmi_cmds[NCMDS]; #endif #define MV_BUFFER_SIZE 300 /*see IPMI_RSPBUF_SIZE also */ #define IPMI_MAX_ADDR_SIZE 32 #define IPMI_RESPONSE_RECV_TYPE 1 #define IPMI_ASYNC_EVENT_RECV_TYPE 2 #define IPMI_CMD_RECV_TYPE 3 #define IPMI_RESPONSE_RESPONSE_TYPE 4 #ifdef TV_PORT /* use this to define timeval if it is a portability issue */ struct timeval { long int tv_sec; /* (time_t) seconds */ long int tv_usec; /* (suseconds_t) microseconds */ }; #endif int ipmi_timeout_mv = 10; /* 10 seconds, was 5 sec */ #if defined(BSD7) #pragma pack(1) #endif struct ipmi_addr { int adrtype; short channel; char data[IPMI_MAX_ADDR_SIZE]; }; struct ipmi_msg { uchar netfn; uchar cmd; ushort data_len; uchar *data; }; struct ipmi_req { unsigned char *addr; /* Address to send the message to. */ unsigned int addr_len; long msgid; /* The sequence number for the message. */ struct ipmi_msg msg; }; struct ipmi_recv { int recv_type; /* Is this a command, response, etc. */ unsigned char *addr; /* Address the message was from */ int addr_len; /* The size of the address buffer. */ long msgid; /* The sequence number from the request */ struct ipmi_msg msg; /* The data field must point to a buffer. */ }; struct ipmi_cmdspec { unsigned char netfn; unsigned char cmd; }; #if defined(BSD7) #pragma pack() #endif #if defined(BSD) || defined(MACOS) || defined(HPUX) /* FreeBSD 7.x ipmi ioctls, use _IOW */ #define IPMI_IOC_MAGIC 'i' #define IPMICTL_RECEIVE_MSG_TRUNC _IOWR(IPMI_IOC_MAGIC, 11, struct ipmi_recv) #define IPMICTL_RECEIVE_MSG _IOWR(IPMI_IOC_MAGIC, 12, struct ipmi_recv) #define IPMICTL_SEND_COMMAND _IOW(IPMI_IOC_MAGIC, 13, struct ipmi_req) #define IPMICTL_REGISTER_FOR_CMD _IOW(IPMI_IOC_MAGIC, 14, struct ipmi_cmdspec) #define IPMICTL_UNREGISTER_FOR_CMD _IOW(IPMI_IOC_MAGIC, 15, struct ipmi_cmdspec) #define IPMICTL_SET_GETS_EVENTS_CMD _IOW(IPMI_IOC_MAGIC, 16, int) #define IPMICTL_SET_MY_ADDRESS_CMD _IOW(IPMI_IOC_MAGIC, 17, unsigned int) #define IPMICTL_GET_MY_ADDRESS_CMD _IOW(IPMI_IOC_MAGIC, 18, unsigned int) #else /* Linux ipmi ioctls */ #define IPMI_IOC_MAGIC 'i' #define IPMICTL_RECEIVE_MSG_TRUNC _IOWR(IPMI_IOC_MAGIC, 11, struct ipmi_recv) #define IPMICTL_RECEIVE_MSG _IOWR(IPMI_IOC_MAGIC, 12, struct ipmi_recv) #define IPMICTL_SEND_COMMAND _IOR(IPMI_IOC_MAGIC, 13, struct ipmi_req) #define IPMICTL_REGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 14,struct ipmi_cmdspec) #define IPMICTL_UNREGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 15,struct ipmi_cmdspec) #define IPMICTL_SET_GETS_EVENTS_CMD _IOR(IPMI_IOC_MAGIC, 16, int) #define IPMICTL_SET_MY_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 17, unsigned int) #define IPMICTL_GET_MY_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 18, unsigned int) #endif /* MAINT ioctls used below, but only valid for Linux */ #define IPMICTL_GET_MAINTENANCE_MODE_CMD _IOR(IPMI_IOC_MAGIC, 30, int) #define IPMICTL_SET_MAINTENANCE_MODE_CMD _IOW(IPMI_IOC_MAGIC, 31, int) #define IPMICTL_GETMAINT 0x8004691e /*only valid if OpenIPMI >=v39.1 */ #define IPMICTL_SETMAINT 0x4004691f /*only valid if OpenIPMI >=v39.1 */ #define BMC_SA 0x20 #define IPMI_BMC_CHANNEL 0xf #define IPMI_SYSTEM_INTERFACE_ADDR_TYPE 0x0c #define IPMI_IPMB_ADDR_TYPE 0x01 #define IPMI_IPMB_BROADCAST_ADDR_TYPE 0x41 /* Broadcast get device id is used as described in IPMI 1.5 section 17.9. */ #define IPMI_LAN_ADDR_TYPE 0x04 struct ipmi_system_interface_addr { int adrtype; short channel; unsigned char lun; }; struct ipmi_ipmb_addr { int adrtype; short channel; uchar slave_addr; uchar lun; }; struct ipmi_lan_addr { int adrtype; short channel; unsigned char privilege; unsigned char session_handle; unsigned char remote_SWID; unsigned char local_SWID; unsigned char lun; }; static int ipmi_fd = -1; static int curr_seq = 0; static int fdebugmv = 0; static struct ipmi_addr rsp_addr; /*used in getevent_mv, ipmi_rsp_mv*/ static int rsp_addrlen = 0; /*used in getevent_mv, ipmi_rsp_mv*/ void ipmi_get_mymc(uchar *bus, uchar *sa, uchar *lun, uchar *type); static void dbgmsg(char *pattn, ...) { va_list arglist; if (fpdbg == NULL) return; // if (fdebugmv == 0) return; va_start( arglist, pattn ); vfprintf( fpdbg, pattn, arglist ); va_end( arglist ); fflush( fpdbg ); } int set_cloexec(int fd, int fdebugcmd) { int flags; flags = fcntl(fd, F_GETFD); if (flags == -1) { if (fdebugcmd) printf("fcntl(get) errno = %d\n",errno); return -1; } flags |= FD_CLOEXEC; if (fcntl(fd, F_SETFD, flags) == -1) { if (fdebugcmd) printf("fcntl(set) errno = %d\n",errno); return -1; } return 0; } int ipmi_open_mv(char fdebugcmd) { char *pdev; uchar bus, sa, lun; #ifdef ALONE fperr = stderr; fpdbg = stdout; #endif if (ipmi_fd != -1) return(0); /*already open*/ fdebugmv = fdebugcmd; pdev = "/dev/ipmi/0"; ipmi_fd = open("/dev/ipmi/0", O_RDWR); if (ipmi_fd == -1) { if (fdebugcmd) dbgmsg("ipmi_open_mv: cannot open %s\n",pdev); pdev = "/dev/ipmi0"; ipmi_fd = open(pdev, O_RDWR); } if (ipmi_fd == -1) { if (fdebugcmd) dbgmsg("ipmi_open_mv: cannot open %s\n",pdev); pdev = "/dev/ipmidev0"; ipmi_fd = open(pdev, O_RDWR); } if (ipmi_fd == -1) { if (fdebugcmd) dbgmsg("ipmi_open_mv: cannot open %s\n",pdev); pdev = "/dev/ipmidev/0"; ipmi_fd = open(pdev, O_RDWR); } if (ipmi_fd == -1) { if (fdebugcmd) dbgmsg("ipmi_open_mv: cannot open %s\n",pdev); return(-1); } ipmi_get_mymc(&bus,&sa,&lun,NULL); if (sa != BMC_SA) { /* user specified my slave address*/ int a, rv; a = sa; rv = ioctl(ipmi_fd, IPMICTL_SET_MY_ADDRESS_CMD, &a); if (fdebugcmd) dbgmsg("ipmi_open_mv: set_my_address(%x) rv=%d\n",sa,rv); if (rv < 0) { return(rv); } } set_cloexec(ipmi_fd,fdebugcmd); if (fdebugcmd) { dbgmsg("ipmi_open_mv: successfully opened %s, fd=%d\n",pdev,ipmi_fd); } return(0); } int ipmi_close_mv(void) { int rc = 0; if (ipmi_fd != -1) { rc = close(ipmi_fd); ipmi_fd = -1; } return(rc); } int ipmi_rsp_mv(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, char fdebugcmd) { struct ipmi_req req; // struct ipmi_recv rsp; struct ipmi_lan_addr lan_addr; // int i, done; int rv; rv = ipmi_open_mv(fdebugcmd); if (rv != 0) return(rv); if (rsp_addrlen > 0) { /* rsp_addr was previously saved in getevent_mv */ req.addr = (char *)&rsp_addr; req.addr_len = rsp_addrlen; } else { /* try some defaults */ lan_addr.adrtype = IPMI_LAN_ADDR_TYPE; lan_addr.channel = bus; /* usu lan_ch == 1 */ lan_addr.privilege = 0x04; /*admin*/ lan_addr.session_handle = 0x01; /*may vary*/ lan_addr.remote_SWID = sa; /*usu 0x81*/ lan_addr.local_SWID = 0x81; lan_addr.lun = lun; req.addr = (char *) &lan_addr; req.addr_len = sizeof(lan_addr); } req.msg.cmd = cmd; req.msg.netfn = (netfn | 0x01); req.msgid = curr_seq; req.msg.data = pdata; req.msg.data_len = sdata; rv = ioctl(ipmi_fd, IPMICTL_SEND_COMMAND, &req); curr_seq++; if (rv == -1) { if (fdebugcmd) dbgmsg("mv IPMICTL_SEND_COMMAND errno %d\n",errno); rv = errno; } return(rv); } int ipmicmd_mv(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int sresp, int *rlen) { fd_set readfds; struct timeval tv; struct ipmi_req req; struct ipmi_recv rsp; struct ipmi_addr addr; struct ipmi_ipmb_addr ipmb_addr; struct ipmi_system_interface_addr bmc_addr; static int need_set_events = 1; int i, done; int rv; rv = ipmi_open_mv(fdebugmv); if (rv != 0) return(rv); if (need_set_events) { i = 1; rv = ioctl(ipmi_fd, IPMICTL_SET_GETS_EVENTS_CMD, &i); if (fdebugmv) dbgmsg("getevent_mv: set_gets_events rv=%d errno=%d, n=%d\n", rv,errno,i); if (rv) { return(errno); } need_set_events = 0; } FD_ZERO(&readfds); // FD_SET(0, &readfds); /* dont watch stdin */ FD_SET(ipmi_fd, &readfds); /* only watch ipmi_fd for input */ /* Special handling for ReadEventMsgBuffer, etc. */ #ifdef TEST_MSG recv.msg.data = data; recv.msg.data_len = sizeof(data); recv.addr = (unsigned char *) &addr; recv.addr_len = sizeof(addr); rv = ioctl(fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv); if (rv == -1) { if (errno == EMSGSIZE) { /* The message was truncated, handle it as such. */ data[0] = IPMI_REQUESTED_DATA_LENGTH_EXCEEDED_CC; rv = 0; } else goto out; } #endif /* Send the IPMI command */ if (sa == BMC_SA) { i = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; bmc_addr.adrtype = i; bmc_addr.channel = IPMI_BMC_CHANNEL; bmc_addr.lun = lun; /* usu BMC_LUN = 0 */ req.addr = (char *) &bmc_addr; req.addr_len = sizeof(bmc_addr); } else { i = IPMI_IPMB_ADDR_TYPE; ipmb_addr.adrtype = i; ipmb_addr.channel = bus; /* usu PUBLIC_BUS = 0 */ ipmb_addr.slave_addr = sa; ipmb_addr.lun = lun; req.addr = (char *) &ipmb_addr; req.addr_len = sizeof(ipmb_addr); } if (fdebugmv) dbgmsg("mv cmd=%02x netfn=%02x mc=%02x;%02x;%02x adrtype=%x\n", cmd,netfn,bus,sa,lun,i); req.msg.cmd = cmd; req.msg.netfn = netfn; req.msgid = curr_seq; req.msg.data = pdata; req.msg.data_len = sdata; rv = ioctl(ipmi_fd, IPMICTL_SEND_COMMAND, &req); curr_seq++; if (rv == -1) { if (fdebugmv) dbgmsg("mv IPMICTL_SEND_COMMAND errno %d\n",errno); rv = errno; } if (netfn & 0x01) done = 1; /*sending response only*/ else done = 0; /*normal request/response*/ if (rv == 0) while (!done) { done = 1; tv.tv_sec=ipmi_timeout_mv; tv.tv_usec=0; rv = select(ipmi_fd+1, &readfds, NULL, NULL, &tv); /* expect select rv = 1 here */ if (rv <= 0) { /* no data within 5 seconds */ if (fdebugmv) fprintf(fperr,"mv select timeout, fd = %d, isset = %d, rv = %d, errno = %d\n", ipmi_fd,FD_ISSET(ipmi_fd, &readfds),rv,errno); if (rv == 0) rv = -3; else rv = errno; } else { /* receive the IPMI response */ rsp.addr = (char *) &addr; rsp.addr_len = sizeof(addr); rsp.msg.data = presp; rsp.msg.data_len = sresp; rv = ioctl(ipmi_fd, IPMICTL_RECEIVE_MSG_TRUNC, &rsp); if (rv == -1) { if ((errno == EMSGSIZE) && (rsp.msg.data_len == sresp)) rv = 0; /* errno 90 is ok */ else { rv = errno; fprintf(fperr,"mv rcv_trunc errno = %d, len = %d\n", errno, rsp.msg.data_len); } } else rv = 0; /* Driver should ensure matching req.msgid and rsp.msgid */ /* Skip & retry if async events, only listen for those in * getevent_mv() below. */ // if (rsp.recv_type == IPMI_ASYNC_EVENT_RECV_TYPE) if (rsp.recv_type != IPMI_RESPONSE_RECV_TYPE) { if (fdebugmv) dbgmsg("mv cmd=%02x netfn=%02x, got recv_type %d\n", cmd,netfn,rsp.recv_type); done = 0; } *rlen = rsp.msg.data_len; } } /*endif send ok, while select/recv*/ /* ipmi_close_mv(); * rely on the app calling ipmi_close */ return(rv); } int ipmi_cmdraw_mv(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { uchar buf[MV_BUFFER_SIZE]; int rc, szbuf; int rlen = 0; uchar cc; if (fdebugcmd) { dbgmsg("mv cmd=%02x netfn=%02x lun=%02x sdata=%d sresp=%d\n", cmd,netfn,lun,sdata,*sresp); dump_buf("mv cmd data",pdata,sdata,0); } szbuf = sizeof(buf); if (*sresp < 2) ; /*just completion code*/ else if (*sresp < szbuf) szbuf = *sresp + 1; else if (fdebugcmd) dbgmsg("mv sresp %d >= szbuf %d, truncated\n",*sresp,szbuf); rc = ipmicmd_mv(cmd,netfn,lun,sa, bus, pdata,sdata, buf,szbuf,&rlen); cc = buf[0]; if (fdebugcmd) { dbgmsg("ipmi_cmdraw_mv: status=%d ccode=%x rlen=%d\n", (uint)rc,cc,rlen); if (rc == 0) dump_buf("mv rsp data",buf,rlen,0); } if (rlen > 0) { /* copy data, except first byte */ rlen -= 1; if (rlen > *sresp) rlen = *sresp; memcpy(presp,&buf[1],rlen); } *pcc = cc; *sresp = rlen; return(rc); } #ifdef ALONE void ipmi_get_mymc(uchar *bus, uchar *sa, uchar *lun, uchar *type) { if (bus != NULL) *bus = 0; //PUBLIC_BUS; if (sa != NULL) *sa = BMC_SA; if (lun != NULL) *lun = 0; //BMC_LUN; if (type != NULL) *type = 1; //ADDR_SMI; } #else int ipmi_cmd_mv(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { uchar buf[MV_BUFFER_SIZE]; int rc, i, szbuf; uchar cc; int rlen = 0; int xlen, j; uchar sa, lun, bus, mtype; for (i = 0; i < NCMDS; i++) { if (ipmi_cmds[i].cmdtyp == cmd) break; } if (i >= NCMDS) { fprintf(fperr, "ipmi_cmd_mv: Unknown command %x\n",cmd); return(-1); } if (cmd >= CMDMASK) cmd = cmd & CMDMASK; /* unmask it */ if (fdebugcmd) { dbgmsg( "mv cmd=%02x netfn=%02x lun=%02x sdata=%d sresp=%d\n", cmd,ipmi_cmds[i].netfn,ipmi_cmds[i].lun,sdata, *sresp); dump_buf("mv cmd data",pdata,sdata,0); } szbuf = sizeof(buf); if (*sresp < szbuf && *sresp >= 2) szbuf = *sresp + 1; else if (fdebugcmd) dbgmsg("mv sresp %d >= szbuf %d, truncated\n",*sresp,szbuf); // ipmi_cmds[i].lun, ipmi_cmds[i].sa, ipmi_cmds[i].bus, ipmi_get_mc(&bus, &sa, &lun, &mtype); rc = ipmicmd_mv(cmd,ipmi_cmds[i].netfn, lun, sa, bus, pdata,sdata,buf,szbuf,&rlen); // if (rc == -1) dbgmsg("ipmi_cmd_mv: cannot open /dev/ipmi0\n"); cc = buf[0]; if (fdebugcmd) { dbgmsg("ipmi_cmd_mv: ipmicmd_mv status=%x, ccode=%x\n", (uint)rc, cc); if (rc == ACCESS_OK) { uchar * pc; int sz; sz = rlen; pc = (uchar *)buf; dbgmsg("ipmi_cmd_mv: response (len=%d): ",sz); for (j = 0; j < sz; j++) dbgmsg("%02x ",pc[j]); dbgmsg("\n"); } } xlen = ipmi_cmds[i].rslen + 1; if ((ipmi_cmds[i].cmdtyp == GET_SEL_ENTRY) && (rlen < xlen) && (rc == 0) && (cc != 0) && (i > 0) && (rlen > 1)) /*not temp slot, have data*/ { /* Detect/Handle MV driver SEL bug returning missing bytes */ if (fdebugcmd) { dbgmsg("ipmi_cmd_mv[%d] BUG: returned %d, expected %d\n", i,rlen,xlen); } cc = 0x80; /*flag as busy, retry*/ j = xlen - rlen; j--; /* omit cc */ for (i = 0; i < j; i++) presp[i] = 0xff; if ((rlen+j) > *sresp) rlen = *sresp - j; memcpy(&presp[j],&buf[0],rlen); rlen += j; } if (rlen > 0) { /* copy data, except first byte */ rlen -= 1; if (rlen > *sresp) rlen = *sresp; memcpy(presp,&buf[1],rlen); } *pcc = cc; *sresp = rlen; return(rc); } /*end ipmi_cmd_mv*/ #endif int setmaint_mv(uchar mode, uchar *cc) { int data[2]; int rv; /* * Normally OpenIPMI driver issues ReadEventMessageBuffer cmds * every 1 second. Maint mode disables that polling in * driver v39.1 and greater. * maintenance mode values: * 2 = turn on maint mode * 1 = turn off maint mode * 0 = automatic maint mode (on for 30 sec if reset or fw request) */ /* should have called ipmi_open_mv in a previous call */ rv = ioctl(ipmi_fd, IPMICTL_GETMAINT, &data); if (rv == -1) { if (errno != 0) *cc = errno; } else *cc = 0; if (fdebugmv) dbgmsg("getmaint: rv=%d mode=%d\n",rv,data[0]); data[0] = mode; rv = ioctl(ipmi_fd, IPMICTL_SETMAINT, &data); if (rv == -1) { if (errno != 0) *cc = errno; } else *cc = 0; return(rv); } int register_async_mv(uchar cmd, uchar netfn) { uchar data[2]; int rv; data[0] = netfn; data[1] = cmd; rv = ioctl(ipmi_fd, IPMICTL_REGISTER_FOR_CMD, &data); if (fdebugmv) dbgmsg("register_async_mv(%x,%x) rv=%d\n",cmd,netfn,rv); return(rv); } int unregister_async_mv(uchar cmd, uchar netfn) { uchar data[2]; int rv; data[0] = netfn; data[1] = cmd; rv = ioctl(ipmi_fd, IPMICTL_UNREGISTER_FOR_CMD, &data); if (fdebugmv) dbgmsg("unregister_async_mv(%x,%x) rv=%d\n",cmd,netfn,rv); return(rv); } int getevent_mv(uchar *evt_data, int *evt_len, uchar *cc, int timeout) { struct ipmi_recv rsp; uchar data[36]; /* #define MAX_IPMI_DATA_SIZE 36 */ struct ipmi_addr addr; static int need_set_events = 1; int rv = 0; int n; if (need_set_events) { n = 1; rv = ioctl(ipmi_fd, IPMICTL_SET_GETS_EVENTS_CMD, &n); if (fdebugmv) dbgmsg("getevent_mv: set_gets_events rv=%d errno=%d, n=%d\n", rv,errno,n); need_set_events = 0; } /* wait for the mv openipmi driver to provide input to fd */ if (timeout == 0) { /*do poll*/ #if defined(MACOS) /* there is no poll function in MACOS, so skip this. */ #else struct pollfd myfd; myfd.fd = ipmi_fd; myfd.events = POLLIN; myfd.revents = 0; rv = poll(&myfd,1,-1); if (rv <= 0) { if (fdebugmv) dbgmsg("getevent_mv poll rv=%d\n",rv); return(rv); } /* else have input ready to read (myfd.revents & POLLIN)*/ if (fdebugmv) dbgmsg("getevent_mv poll revents %x\n",myfd.revents); #endif } /* read the message from the ipmi_fd */ rsp.msg.data = data; rsp.msg.data_len = sizeof(data); rsp.addr = (unsigned char *) &addr; rsp.addr_len = sizeof(addr); rv = ioctl(ipmi_fd, IPMICTL_RECEIVE_MSG_TRUNC, &rsp); if (rv < 0) { if (fdebugmv) dbgmsg("getevent_mv rv=%d, errno=%d\n",rv,errno); if (errno == EMSGSIZE) { /* The message was truncated */ *cc = 0xC8; /*IPMI_REQUESTED_DATA_LENGTH_EXCEEDED_CC;*/ rsp.msg.data_len = sizeof(data); rv = 0; } else if (errno == EINTR) { return(EINTR); } } else *cc = 0; if (rv == 0) { n = rsp.msg.data_len; if (fdebugmv) { dbgmsg("getevent_mv: recv_type=%x cmd=%x data_len=%d\n", rsp.recv_type,rsp.msg.cmd,n); // if (n > 0) dump_buf("mv rsp.msg.data",rsp.msg.data, n, 0); // dump_buf("mv rsp.addr",rsp.addr,rsp.addr_len,0); } if (rsp.recv_type == IPMI_CMD_RECV_TYPE) { evt_data[0] = rsp.recv_type; evt_data[1] = rsp.msg.netfn; evt_data[2] = rsp.msg.cmd; if (n > 0) memcpy(&evt_data[3],&data[0],n); n += 3; /* save the response address */ memcpy(&rsp_addr,rsp.addr,rsp.addr_len); rsp_addrlen = rsp.addr_len; } else if (rsp.recv_type == IPMI_RESPONSE_RESPONSE_TYPE) { evt_data[0] = rsp.recv_type; evt_data[1] = rsp.msg.netfn; evt_data[2] = rsp.msg.cmd; evt_data[3] = data[0]; n += 3; } else { /* rsp.recv_type == IPMI_ASYNC_EVENT_RECV_TYPE */ if (n > 0) memcpy(evt_data,&data[0],n); } *evt_len = n; } else if (rv == -1 || rv == -11) { rv = 0x80; /* -EAGAIN, no data, try again */ } return(rv); } #ifdef TEST_BIN int main(int argc, char *argv[]) { fd_set readfds; struct timeval tv; uchar data[40]; int i, j; int err, rv; int rlen = 0; uchar cc; fperr = stderr; fpdbg = stdout; fdebugmv = 1; rlen = sizeof(data); err = ipmi_cmdraw_mv(0x01, 0x06, 0, 0x20, 0, /*get_device_id*/ NULL, 0, data, &rlen, &cc, fdebugmv); dbgmsg("ipmi_cmdraw_mv ret=%d, cc=%02x\n",err,cc); rv = err; if (err == 0) { rv = cc; dbgmsg(" ** Return Code: %2.2X\n", cc); dbgmsg(" ** Data[%d]:",rlen); for (i=0; i < rlen; i++) dbgmsg(" %2.2X", (uchar)data[i]); dbgmsg("\n"); } err = setmaint_mv(2,&cc); dbgmsg("setmaint_mv(2) err=%d cc=%d\n",err,cc); err = setmaint_mv(1,&cc); dbgmsg("setmaint_mv(1) err=%d cc=%d\n",err,cc); err = setmaint_mv(0,&cc); dbgmsg("setmaint_mv(0) err=%d cc=%d\n",err,cc); err = register_async_mv(0x10,0x06); dbgmsg("register_async_mv(10,6) rv=%d\n",err); err = register_async_mv(0x01,0x06); dbgmsg("register_async_mv(01,6) rv=%d\n",err); err = unregister_async_mv(0x01,0x06); dbgmsg("unregister_async_mv(01,6) rv=%d\n",err); err = unregister_async_mv(0x10,0x06); dbgmsg("unregister_async_mv(10,6) rv=%d\n",err); dbgmsg("\n"); ipmi_close_mv(); return rv; } #endif #endif ipmiutil-3.1.5/util/oem_kontron.h0000644000076400007640000000532113566765324017137 0ustar mgportalloggers/* * Copyright (c) 2004 Kontron Canada, Inc. All Rights Reserved. * * Base on code from * Copyright (c) 2003 Sun Microsystems, 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: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution 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. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #ifndef IPMI_KONTRONOEM_H #define IPMI_KONTRONOEM_H #define IPMI_BUF_SIZE 1024 #ifdef HAVE_LANPLUS #include "../lib/lanplus/lanplus_defs.h" #endif #define TRUE 1 #define FALSE 0 #define IPMI_NETFN_APP 0x06 #define IPMI_NETFN_STORAGE 0x0a #define IPMI_NETFN_PICMG 0x2C #define IPMI_BMC_SLAVE_ADDR 0x20 #define BMC_GET_DEVICE_ID 0x1 #define GET_FRU_INFO 0x10 #define GET_FRU_DATA 0x11 #pragma pack(1) struct fru_info { uint16_t size; uint8_t access:1; }; struct fru_header { uint8_t version; struct { uint8_t internal; uint8_t chassis; uint8_t board; uint8_t product; uint8_t multi; } offset; uint8_t pad; uint8_t checksum; }; #pragma pack() /* the ERRs are defined in ipmicmd.h */ int ipmi_kontronoem_main(void *intf, int argc, char **argv); #endif /* IPMI_KONTRONOEM_H */ ipmiutil-3.1.5/util/oem_hp.c0000644000076400007640000001513713566765324016055 0ustar mgportalloggers/* * oem_hp.c * Handle HP OEM command functions * * Change history: * 02/23/2012 ARCress - included in source tree * *--------------------------------------------------------------------- */ /*M* Copyright (c) 2012 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 Kontron 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*/ #ifdef WIN32 #include #endif #include #include #include #include "ipmicmd.h" #include "ievents.h" #include "isensor.h" #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil hpoem"; #else static char * progver = "3.13"; static char * progname = "ihpoem"; #endif static char *redund_str(uchar b) { char *pstr; if (b == 0x00) pstr = "Disabled"; else if (b == 0x01) pstr = "Fully Redundant"; else if (b == 0x02) pstr = "Redundancy Lost"; else if (b == 0x0b) pstr = "AC Lost"; else pstr = "Redundancy Degraded"; return(pstr); } /* * decode_sensor_hp * inputs: * sdr = the SDR buffer * reading = the 3 or 4 bytes of data from GetSensorReading * pstring = points to the output string buffer * slen = size of the output buffer * outputs: * rv = 0 if this sensor was successfully interpreted here, * non-zero otherwise, to use default interpretations. * pstring = contains the sensor reading interpretation string (if rv==0) */ int decode_sensor_hp(uchar *sdr,uchar *reading,char *pstring, int slen) { int rv = -1; char *pstr = NULL; uchar stype, evtype, b; ushort v; int analog = 0; int fshort = 1; double val; char *typestr = NULL; SDR01REC *sdr01 = (SDR01REC *)sdr; if (sdr == NULL || reading == NULL) return(rv); if (pstring == NULL || slen == 0) return(rv); /* sdr[3] is SDR type 1=full, 2=compact */ stype = sdr[12]; /*sensor type*/ evtype = sdr[13]; /*event type */ if (stype == 0xC0) { /* HP OEM Sensor, no sensor reading */ strncpy(pstring,"na",slen); /*oem*/ rv = 0; } else { #ifdef OLD int vend, prod; get_mfgid(&vend,&prod); /* This was an anomaly for an older HP DL380 but is no longer valid */ if ((prod == 0x2000) && ((reading[2] & 0x40) == 0x40)) { /*custom Init/Unavail state if DL380*/ strncpy(pstring,"Init",slen); rv = 0; } else #endif /* HP has packed analog readings into some of their non-Threshold sensors * so we have to handle that. */ if (sdr[3] == 0x01) { /*only full sensors can be analog*/ if (evtype == 0x01) analog = 1; /*threshold*/ else { /*if units are defined, assume analog reading */ if ((sdr01->sens_units & 0x07) != 0) analog = 1; if (sdr01->sens_base != 0) analog = 1; if (sdr01->sens_mod != 0) analog = 1; } if ((reading[1] & 0x20) != 0) analog = 0; /*Init state, no analog*/ else if (sdr01->sens_units == 0xC0) analog = 0; /*reading NotAvailable*/ else if (reading[2] == 0xc7) analog = 0; /* Absent (Intel) */ } if (evtype == 0x6f) { /*evtype==0x6f special*/ pstr = "DiscreteEvt"; if (stype == 0x08) { /*Power Supply presence*/ if (reading[2] & 0x01) pstr = "Present"; else pstr = "Absent"; } rv = 0; } else if (evtype == 0x0B) { /*Redundancy*/ b = reading[2] & 0x3f; pstr = "DiscretePS"; /*Power Supplies*/ if (evtype == 0x0b) pstr = redund_str(b); rv = 0; } else if (evtype == 0x0A) { /*Discrete Fan*/ v = reading[2] + (reading[3] & 0x3f); if (v & 0x001) pstr = "Transition to Running"; else if (v & 0x002) pstr = "Transition to In Test"; else if (v & 0x004) pstr = "Transition to Power Off"; else if (v & 0x008) pstr = "Transition to On Line"; else if (v & 0x010) pstr = "Transition to Off Line"; else if (v & 0x020) pstr = "Transition to Off Duty"; else if (v & 0x040) pstr = "Transition to Degraded"; else if (v & 0x080) pstr = "Transition to Power"; else if (v & 0x100) pstr = "Install Error"; else pstr = "Unknown"; rv = 0; } else if (evtype == 0x09) { /* stype==0x03 Power Meter */ b = reading[2] & 0x3f; if (b & 0x01) pstr = "Disabled"; else if (b & 0x02) pstr = "Enabled"; else pstr = "Unknown"; rv = 0; } else if ((sdr[20] & 0xC0) == 0xC0) { /*unit1==discrete*/ b = reading[2] & 0x3f; pstr = "DiscreteUnit"; if (evtype == 0x0b) pstr = redund_str(b); rv = 0; } if (rv == 0) { if (analog == 1) { val = RawToFloat(reading[0],sdr); typestr = get_unit_type(sdr01->sens_units, sdr01->sens_base, sdr01->sens_mod, fshort); snprintf(pstring,slen,"%.2f %s, %s",val,typestr,pstr); } else { snprintf(pstring,slen,"%02x%02x %s",reading[3],reading[2],pstr); } } } return(rv); } void show_oemsdr_hp(uchar *sdr) { int len, i; len = sdr[4] + 5; if (sdr[8] == 0x02) len = 18; printf("HP: "); for (i = 8; i < len; i++) printf("%02x ",sdr[i]); if (sdr[8] == 0x02) printf("%s",&sdr[18]); printf("\n"); return; } #ifdef METACOMMAND int i_hpoem(int argc, char **argv) { printf("%s ver %s\n", progname,progver); return(0); } #endif /* end oem_hp.c */ ipmiutil-3.1.5/util/oem_lenovo.h0000644000076400007640000000371413566765324016753 0ustar mgportalloggers/* * oem_lenovo.h * Handle Lenovo OEM command functions * * Author: Andy Cress arcress at users.sourceforge.net * Change history: * 11/21/2016 ARCress - created * *--------------------------------------------------------------------- */ /*M* Copyright (c) 2016 Andy Cress All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of the copyright holder nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ #ifndef IPMI_OEMLENOVO_H #define IPMI_OEMLENOVO_H int ipmi_oem_lenovo_main(void *, int, char **); int decode_sensor_lenovo(uchar *sdr,uchar *reading,char *pstring, int slen); #endif /*IPMI_OEMLENOVO_H*/ ipmiutil-3.1.5/util/imb_api.h0000644000076400007640000005267113566765324016217 0ustar mgportalloggers/*M* // PVCS: // $Workfile: imb_api.h $ // $Revision: 1.0 $ // $Modtime: Jul 22 2002 16:40:32 $ // $Author: arcress at users.sf.net $ // // Combined include files needed for imbapi.c // *M*/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2002, 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 Corporation 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. *----------------------------------------------------------------------*/ #ifndef _WINDEFS_H #define _WINDEFS_H #if defined(WIN32) | defined(BSD) | defined(DOS) /* WIN32 defines wchar_t in stdio.h */ /* BSD defines wchar_t in stdlib.h */ /* DOS defines wchar_t in stdlib.h */ #else #if defined(LINUX) /* LINUX should define wchar_t in stdlib.h */ #include #endif // SOLARIS or MACOS may need wchar_t #include "config.h" #if !HAVE_WCHAR_T typedef long wchar_t; #endif #endif #ifndef NULL #define NULL 0 #endif #define TRUE 1 #define FALSE 0 #define far #define near #define FAR far #define NEAR near #ifndef CONST #define CONST const #endif typedef unsigned int UINT32; typedef unsigned long DWORD; typedef int BOOL; typedef unsigned char BYTE; typedef unsigned short WORD; typedef float FLOAT; typedef FLOAT *PFLOAT; typedef BOOL near *PBOOL; typedef BOOL far *LPBOOL; typedef BYTE near *PBYTE; typedef BYTE far *LPBYTE; typedef int near *PINT; typedef int far *LPINT; typedef WORD near *PWORD; typedef WORD far *LPWORD; typedef long far *LPLONG; typedef DWORD near *PDWORD; typedef DWORD far *LPDWORD; typedef void far *LPVOID; typedef CONST void far *LPCVOID; typedef int INT; typedef unsigned int UINT; typedef unsigned int *PUINT; #ifndef NTSTATUS typedef DWORD NTSTATUS; #endif /* File structures */ #ifndef WIN32 typedef struct _OVERLAPPED { DWORD Internal; DWORD InternalHigh; DWORD Offset; DWORD OffsetHigh; /* HANDLE hEvent; */ } OVERLAPPED, *LPOVERLAPPED; #endif /* * Data structure redefines */ typedef char CHAR; typedef short SHORT; typedef long LONG; typedef char * PCHAR; typedef short * PSHORT; typedef long * PLONG; typedef unsigned char UCHAR; typedef unsigned short USHORT; typedef unsigned long ULONG; typedef char CCHAR; typedef short CSHORT; typedef ULONG CLONG; typedef CCHAR * PCCHAR; typedef CSHORT * PCSHORT; typedef CLONG * PCLONG; typedef void * PVOID; #ifndef WIN32 typedef void VOID; typedef struct _LARGE_INTEGER { ULONG LowPart; LONG HighPart; } LARGE_INTEGER; typedef struct _ULARGE_INTEGER { ULONG LowPart; ULONG HighPart; } ULARGE_INTEGER; #endif typedef LARGE_INTEGER * PLARGE_INTEGER; typedef LARGE_INTEGER PHYSICAL_ADDRESS; typedef LARGE_INTEGER * PPHYSICAL_ADDRESS; typedef ULARGE_INTEGER * PULARGE_INTEGER; typedef UCHAR BOOLEAN; typedef BOOLEAN *PBOOLEAN; /* Unicode strings are counted 16-bit character strings. If they are NULL terminated, Length does not include trailing NULL. */ typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; wchar_t *Buffer; } UNICODE_STRING; typedef UNICODE_STRING *PUNICODE_STRING; #define IN /* */ #define OUT /* */ #define OPTIONAL /* */ #ifdef WIN32 #define HandleType HANDLE #else #define HandleType long #define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field)) #define UNREFERENCED_PARAMETER(x) #define INVALID_HANDLE_VALUE ((HandleType)-1) #endif typedef HandleType *PHANDLE; /* Define the method codes for how buffers are passed for I/O and FS controls */ #define METHOD_BUFFERED 0 /* Define the access check value for any access The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these constants *MUST* always be in sync. */ #define FILE_ANY_ACCESS 0 /* These are the generic rights. */ #define MAX_PATH 260 // #define GetLastError() (NTstatus.Status) /* Macro definition for defining IOCTL and FSCTL function control codes. Note that function codes 0-2047 are reserved for Microsoft Corporation, and 2048-4095 are reserved for customers. */ /* * Linux drivers expect ioctls defined using macros defined in ioctl.h. * So, instead of using the CTL_CODE defined for NT and UW, I define CTL_CODE * using these macros. That way imb_if.h, where the ioctls are defined get * to use the correct ioctl command we expect. * Notes: I am using the generic _IO macro instead of the more specific * ones. The macros expect 8bit entities, so I am cleaning what is sent to * us from imb_if.h - Mahendra */ #ifdef LINUX #define CTL_CODE(DeviceType, Function, Method, Access)\ _IO(DeviceType & 0x00FF, Function & 0x00FF) #else /* WIN32 may have this defined in winsdk\include\winioctl.h */ #ifndef CTL_CODE #define CTL_CODE( DeviceType, Function, Method, Access ) ((ULONG)( \ ((ULONG)(DeviceType) << 16) | ((ULONG)(Access) << 14) | ((ULONG)(Function) << 2) | ((ULONG)Method) \ )) #endif #endif #endif /*_WINDEFS_H */ /*----------------------------------------------------------------------*/ #ifndef _SMI_H #define _SMI_H #define SMI_Version1_00 0x00001000 #define SMI_Version2_00 0x00002000 /* LPVOID = (void far *) */ /* DWORD = (unsigned long ) */ /* typedef DWORD far *LPDWORD; */ /* LPOVERLAPPED = struct w 4 DWORDs */ struct smi { DWORD smi_VersionNo; DWORD smi_Reserved1; DWORD smi_Reserved2; LPVOID ntstatus; /* address of NT status block*/ LPVOID lpvInBuffer; /* address of buffer for input data*/ DWORD cbInBuffer; /* size of input buffer*/ LPVOID lpvOutBuffer; /* address of output buffer*/ DWORD cbOutBuffer; /* size of output buffer*/ LPDWORD lpcbBytesReturned; /* address of actual bytes of output*/ LPOVERLAPPED lpoOverlapped; /* address of overlapped structure*/ }; struct smi32 { UINT32 smi_VersionNo; UINT32 smi_Reserved1; UINT32 smi_Reserved2; UINT32 ntstatus; /* address of NT status block*/ UINT32 lpvInBuffer; /* address of buffer for input data*/ UINT32 cbInBuffer; /* size of input buffer*/ UINT32 lpvOutBuffer; /* address of output buffer*/ UINT32 cbOutBuffer; /* size of output buffer*/ UINT32 lpcbBytesReturned; /* address of actual bytes of output*/ struct { UINT32 h[4]; } lpoOverlapped; /* address of overlapped structure*/ }; #ifndef STATUS_SUCCESS typedef struct _IO_STATUS_BLOCK { ULONG Status; ULONG Information; } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; /* * I2C ioctl's return NTStatus codes */ #define STATUS_SUCCESS (0x00000000U) #define STATUS_UNSUCCESSFUL (0xC0000001U) #define STATUS_DEVICE_BUSY (0x80000011U) #ifndef WIN32 // see \inc\winnt.h(1171) #define STATUS_PENDING (0x00000103U) #define STATUS_INVALID_PARAMETER (0xC000000DU) #endif #define STATUS_INVALID_DEVICE_REQUEST (0xC0000010U) #define STATUS_BUFFER_TOO_SMALL (0xC0000023U) #define STATUS_FILE_CLOSED (0xC0000128U) #define STATUS_INSUFFICIENT_RESOURCES (0xC000009AU) #define STATUS_NO_DATA_DETECTED (0x80000022U) #define STATUS_NO_SUCH_DEVICE (0xC000000EU) #define STATUS_ALLOTTED_EXCEEDED (0xC000000FU) #define STATUS_IO_DEVICE_ERROR (0xC0000185U) #define STATUS_TOO_MANY_OPEN_FILES (0xC000011FU) #define STATUS_ACCESS_DENIED (0xC0000022U) #define STATUS_BUFFER_OVERFLOW (0x80000005U) #define STATUS_CANCELLED (0xC0000120U) #endif /* STATUS_SUCCESS*/ #endif /* _SMI_H*/ /*----------------------------------------------------------------------*/ #ifndef IMB_IF__ #define IMB_IF__ /* * This is the structure passed in to the IOCTL_IMB_SHUTDOWN_CODE request */ typedef struct { int code; int delayTime; } ShutdownCmdBuffer; #define SD_NO_ACTION 0 #define SD_RESET 1 #define SD_POWER_OFF 2 #pragma pack(1) /* * This is the generic IMB packet format, the final checksum cant be * represented in this structure and will show up as the last data byte */ typedef struct { BYTE rsSa; BYTE nfLn; BYTE cSum1; BYTE rqSa; BYTE seqLn; BYTE cmd; BYTE data[1]; } ImbPacket; #define MIN_IMB_PACKET_SIZE 7 #define MAX_IMB_PACKET_SIZE 57 /*was 33, now 64-7=57*/ // #define MAX_IMB_PACKET_SIZE 135 (if using flashupdt large packets) #define MAX_RBUFFER_SIZE 64 /*no longer used*/ /* * This is the standard IMB response format where the first byte of * IMB packet data is interpreted as a command completion code. */ typedef struct { BYTE rsSa; BYTE nfLn; BYTE cSum1; BYTE rqSa; BYTE seqLn; BYTE cmd; BYTE cCode; BYTE data[1]; } ImbRespPacket; #define MIN_IMB_RESPONSE_SIZE 7 /* min packet + completion code */ #define MAX_IMB_RESPONSE_SIZE MAX_IMB_PACKET_SIZE /************************ * ImbRequestBuffer ************************/ /*D* // Name: ImbRequestBuffer // Purpose: Structure definition for holding IMB message data // Context: Used by SendTimedImbpMessage and SendTimedI2cMessge // functions in the library interface. In use, it is overlayed on a // char buffer of size MIN_IMB_REQ_BUF_SIZE + // Fields: // respBufSize size of the response buffer // // timeout timeout value in milli seconds // // req body of request to send // *D*/ typedef struct { BYTE rsSa; BYTE cmd; BYTE netFn; BYTE rsLun; BYTE dataLength; BYTE data[16]; } ImbRequest; typedef struct { UINT32 flags; /* request flags*/ #define NO_RESPONSE_EXPECTED 0x01 /*dont wait around for an IMB response*/ UINT32 timeOut; /* in uSec units*/ ImbRequest req; /* message buffer*/ } ImbRequestBuffer; #define MIN_IMB_REQ_BUF_SIZE 13 /* a buffer without any request data*/ #define MAX_IMB_REQ_SIZE (MIN_IMB_RESP_BUF_SIZE + MAX_IMB_PACKET_SIZE) /************************ * ImbResponseBuffer ************************/ /*D* // Name: ImbResponseBuffer // Purpose: Structure definition for response of a previous send // Context: Used by DeviceIoControl to pass the message to be sent to // MISSMIC port // Fields: // cCode completion code returned by firmware // data buffer for response data from firmware *D*/ typedef struct { BYTE cCode; BYTE data[1]; } ImbResponseBuffer; #define MIN_IMB_RESP_BUF_SIZE 1 #define MAX_IMB_RESP_SIZE (MIN_IMB_RESP_BUF_SIZE + MAX_IMB_RESPONSE_SIZE) #pragma pack() /* * Async message access structures and types */ typedef UINT32 ImbAsyncSeq; /* * This is the structure passed in to IOCTL_IMB_GET_ASYNC_MSG */ typedef struct { UINT32 timeOut; ImbAsyncSeq lastSeq; } ImbAsyncRequest; #define ASYNC_SEQ_START 0 typedef struct { ImbAsyncSeq thisSeq; BYTE data[1]; } ImbAsyncResponse; #define MIN_ASYNC_RESP_SIZE sizeof( ImbAsyncSeq ) #define MAX_ASYNC_RESP_SIZE (MIN_ASYNC_RESP_SIZE + MAX_IMB_PACKET_SIZE) /* ** Driver Ioctls ** In Linux, these calculate to: ** IOCTL_IMB_SEND_MESSAGE =1082 ** IOCTL_IMB_GET_ASYNC_MSG =1088 ** IOCTL_IMB_MAP_MEMORY =108e ** IOCTL_IMB_UNMAP_MEMORY =1090 ** IOCTL_IMB_SHUTDOWN_CODE =1092 ** IOCTL_IMB_REGISTER_ASYNC_OBJ =1098 ** IOCTL_IMB_DEREGISTER_ASYNC_OBJ=109a ** IOCTL_IMB_CHECK_EVENT =109c ** IOCTL_IMB_POLL_ASYNC =1094 */ #define FILE_DEVICE_IMB 0x00008010 #define IOCTL_IMB_BASE 0x00000880 #define IOCTL_IMB_SEND_MESSAGE CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 2), METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_IMB_GET_ASYNC_MSG CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 8), METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_IMB_MAP_MEMORY CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 14),METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_IMB_UNMAP_MEMORY CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 16),METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_IMB_SHUTDOWN_CODE CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 18),METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_IMB_REGISTER_ASYNC_OBJ CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 24),METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_IMB_DEREGISTER_ASYNC_OBJ CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 26),METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_IMB_CHECK_EVENT CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 28),METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_IMB_POLL_ASYNC CTL_CODE(FILE_DEVICE_IMB, (IOCTL_IMB_BASE + 20),METHOD_BUFFERED, FILE_ANY_ACCESS) #endif /* IMB_IF__ */ /*----------------------------------------------------------------------*/ /* No asynchronous messages available */ #define IMB_MSG_NOT_AVAILABLE ((NTSTATUS)0xE0070012L) #ifdef IMBLOG_H__ /* Define the facility codes */ #define FACILITY_RPC_STUBS 0x3 #define FACILITY_RPC_RUNTIME 0x2 #define FACILITY_IO_ERROR_CODE 0x4 #define IMB_IO_ERROR_CODE 0x7 #define STATUS_SEVERITY_WARNING 0x2 #define STATUS_SEVERITY_SUCCESS 0x0 #define STATUS_SEVERITY_INFORMATIONAL 0x1 #define STATUS_SEVERITY_ERROR 0x3 /* Not enough memory for internal storage of device %1. */ #define INSUFFICIENT_RESOURCES ((NTSTATUS)0xE0070001L) #define INVALID_INPUT_BUFFER ((NTSTATUS)0xE0070002L) #define INVALID_OUTPUT_BUFFER ((NTSTATUS)0xE0070003L) #define IMB_SEND_TIMEOUT ((NTSTATUS)0xE0070004L) #define IMB_RECEIVE_TIMEOUT ((NTSTATUS)0xE0070005L) #define IMB_IF_SEND_TIMEOUT ((NTSTATUS)0xE0070006L) #define IMB_IF_RECEIVE_TIMEOUT ((NTSTATUS)0xE0040007L) #define HARDWARE_FAILURE ((NTSTATUS)0xE0040008L) #define DRIVER_FAILURE ((NTSTATUS)0xE0040009L) #define IMB_INVALID_IF_RESPONSE ((NTSTATUS)0xE004000AL) #define IMB_INVALID_PACKET ((NTSTATUS)0xE004000BL) #define IMB_RESPONSE_DATA_OVERFLOW ((NTSTATUS)0xE004000CL) #define IMB_INVALID_REQUEST ((NTSTATUS)0xE007000DL) #define INVALID_DRIVER_IOCTL ((NTSTATUS)0xE007000EL) #define INVALID_DRIVER_REQUEST ((NTSTATUS)0xE007000FL) #define IMB_CANT_GET_SMS_BUFFER ((NTSTATUS)0xE0070010L) #define INPUT_BUFFER_TOO_SMALL ((NTSTATUS)0xE0070011L) #define IMB_SEND_ERROR ((NTSTATUS)0xE0070013L) #endif /* IMBLOG_H__ */ /*----------------------------------------------------------------------*/ #ifndef IMBAPI_H__ #define IMBAPI_H__ #include #if defined(MACOS) /* has caddr_t */ #else #ifndef _SYS_TYPES_H #ifndef _CADDR_T #define _CADDR_T typedef char * caddr_t; #endif #endif #endif #define WRITE_READ_I2C 0x52 #define WRITE_EMP_BUFFER 0x7a #define GET_DEVICE_ID 0x1 #define CMD_GET_DEVICE_ID 0x01 #define SEND_MESSAGE 0x34 #define GET_MESSAGE 0x33 #define BMC_SA 0x20 #define BMC_LUN 0 #define APP_NETFN 0x06 #define IPMI_09_VERSION 0x90 #define IPMI_10_VERSION 0x01 #define IPMI_15_VERSION 0x51 #ifndef IPMI10_GET_DEVICE_ID_RESP_LENGTH #define IPMI10_GET_DEVICE_ID_RESP_LENGTH 12 #endif #define IPMB_CHANNEL 0x0 #define EMP_CHANNEL 0x1 #define LAN_CHANNEL 0x2 #define ANY_CHANNEL 0xFF #define RESERVED_LUN 0x3 #define IPMB_LUN 0x2 #define EMP_LUN 0x0 #define PUBLIC_BUS 0 #define BMC_CONTROLLER 0x20 #define FPC_CONTROLLER 0x22 typedef enum { ACCESN_OK, ACCESN_ERROR, ACCESN_OUT_OF_RANGE, ACCESN_END_OF_DATA, ACCESN_UNSUPPORTED, ACCESN_INVALID_TRANSACTION, ACCESN_TIMED_OUT } ACCESN_STATUS; #pragma pack(1) /* * Request structure provided to SendTimedImbpRequest() */ typedef struct { unsigned char cmdType; unsigned char rsSa; unsigned char busType; unsigned char netFn; unsigned char rsLun; unsigned char * data; int dataLength; } IMBPREQUESTDATA; /* * Request structure provided to SendTimedI2cRequest() */ typedef struct { unsigned char rsSa; unsigned char busType; unsigned char numberOfBytesToRead; unsigned char * data; int dataLength; } I2CREQUESTDATA; #pragma pack() /*#ifdef IMB_API * * This section is provided to be able to compile using imb_if.h * * * function return type. This is also defined in the local instrumentation * so we ifdef here to avoid conflict. */ #define METHOD_BUFFERED 0 #define FILE_ANY_ACCESS 0 /* * This is necessary to compile using memIf.h */ typedef enum _INTERFACE_TYPE { Internal, Isa, Eisa, MicroChannel, TurboChannel, MaximumInterfaceType } INTERFACE_TYPE, * PINTERFACE_TYPE; #ifdef WIN32 /* From memIf.h */ #pragma pack(1) typedef struct { INTERFACE_TYPE InterfaceType; // Isa, Eisa, etc.... ULONG BusNumber; // Bus number PHYSICAL_ADDRESS BusAddress; // Bus-relative address ULONG AddressSpace; // 0 is memory, 1 is I/O ULONG Length; // Length of section to map } PHYSICAL_MEMORY_INFO, * PPHYSICAL_MEMORY_INFO; #pragma pack() #endif /*#else // not IMB_API */ /* * These are defined in imb_if.h but are needed by users of the imbapi library */ #define ASYNC_SEQ_START 0 /* * This is the generic IMB packet format, the final checksum cant be * represented in this structure and will show up as the last data byte */ /*#endif // IMB_API */ /****************************** * FUNCTION PROTOTYPES ******************************/ #ifdef LINK_LANDESK #define SendTimedImbpRequest ia_SendTimedImbpRequest #define StartAsyncMesgPoll ia_StartAsyncMesgPoll #define SendTimedI2cRequest ia_SendTimedI2cRequest #define SendTimedEmpMessageResponse ia_SendTimedEmpMessageResponse #define SendTimedEmpMessageResponse_Ex ia_SendTimedEmpMessageResponse_Ex #define SendTimedLanMessageResponse ia_SendTimedLanMessageResponse #define SendTimedLanMessageResponse_Ex ia_SendTimedLanMessageResponse_Ex #define SendAsyncImbpRequest ia_SendAsyncImbpRequest #define GetAsyncImbpMessage ia_GetAsyncImbpMessage #define GetAsyncImbpMessage_Ex ia_GetAsyncImbpMessage_Ex #define IsAsyncMessageAvailable ia_IsAsyncMessageAvailable #define RegisterForImbAsyncMessageNotification ia_RegisterForImbAsyncMessageNotification #define UnRegisterForImbAsyncMessageNotification ia_UnRegisterForImbAsyncMessageNotification #define SetShutDownCode ia_SetShutDownCode #define GetIpmiVersion ia_GetIpmiVersion #else int initIPMI(void); int termIPMI(void); #endif ACCESN_STATUS SendTimedImbpRequest ( IMBPREQUESTDATA *reqPtr, int timeOut, BYTE * respDataPtr, int * respDataLen, BYTE * completionCode ); ACCESN_STATUS SendTimedI2cRequest ( I2CREQUESTDATA *reqPtr, int timeOut, BYTE * respDataPtr, int * respDataLen, BYTE * completionCode ); ACCESN_STATUS SendAsyncImbpRequest ( IMBPREQUESTDATA *reqPtr, BYTE * seqNo ); ACCESN_STATUS GetAsyncImbpMessage ( ImbPacket * msgPtr, DWORD * msgLen, DWORD timeOut, ImbAsyncSeq * seqNo, DWORD channelNumber ); ACCESN_STATUS GetAsyncImbpMessage_Ex ( ImbPacket * msgPtr, DWORD * msgLen, DWORD timeOut, ImbAsyncSeq * seqNo, DWORD channelNumber, BYTE * sessionHandle, BYTE * privilege ); ACCESN_STATUS UnmapPhysicalMemory( int virtualAddress, int Length ); ACCESN_STATUS StartAsyncMesgPoll(void); ACCESN_STATUS MapPhysicalMemory ( int startAddress, int addressLength, int *virtualAddress ); ACCESN_STATUS SetShutDownCode ( int delayTime, int code ); ACCESN_STATUS SendTimedEmpMessageResponse ( ImbPacket * ptr, char *responseDataBuf, int responseDataLen, int timeOut ); ACCESN_STATUS SendTimedEmpMessageResponse_Ex ( ImbPacket * ptr, char *responseDataBuf, int responseDataLen, int timeOut, BYTE sessionHandle, BYTE channelNumber ); ACCESN_STATUS SendTimedLanMessageResponse ( ImbPacket * ptr, char *responseDataBuf, int responseDataLen, int timeOut ); ACCESN_STATUS SendTimedLanMessageResponse_Ex ( ImbPacket * ptr, char *responseDataBuf, int responseDataLen, int timeOut , BYTE sessionHandle, BYTE channelNumber ); ACCESN_STATUS IsAsyncMessageAvailable (HandleType eventId); ACCESN_STATUS RegisterForImbAsyncMessageNotification (HandleType *handleId); ACCESN_STATUS UnRegisterForImbAsyncMessageNotification (HandleType handleId,int iFlag); BYTE GetIpmiVersion(void); #endif /* IMBAPI_H__ */ ipmiutil-3.1.5/util/ipicmg.c0000644000076400007640000015236313566765324016061 0ustar mgportalloggers/* * ipicmg.c * * This module handles PICMG extended IPMI commands. * * Change History: * 06/03/2010 ARCress - new, included in source tree * 08/15/2011 ARCress - updated with PICMG 2.3 * *---------------------------------------------------------------------- * Copyright (c) 2010 Kontron. All right reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution 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. * * Neither the name of Kontron, or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * THE COPYRIGHT HOLDER AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE * COPYRIGHT HOLDER OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR * DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. *---------------------------------------------------------------------- */ #ifdef WIN32 #include #include #include #include #include "getopt.h" #else #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include "ipmicmd.h" #include "ipicmg.h" /* Misc PICMG defines */ #define PICMG_EXTENSION_ATCA_MAJOR_VERSION 2 #define PICMG_EXTENSION_AMC0_MAJOR_VERSION 4 #define PICMG_EXTENSION_UTCA_MAJOR_VERSION 5 #define PICMG_EKEY_MODE_QUERY 0 #define PICMG_EKEY_MODE_PRINT_ALL 1 #define PICMG_EKEY_MODE_PRINT_ENABLED 2 #define PICMG_EKEY_MODE_PRINT_DISABLED 3 #define PICMG_EKEY_MAX_CHANNEL 16 #define PICMG_EKEY_MAX_FABRIC_CHANNEL 15 #define PICMG_EKEY_MAX_INTERFACE 3 #define PICMG_EKEY_AMC_MAX_CHANNEL 16 #define PICMG_EKEY_AMC_MAX_DEVICE 15 /* 4 bits */ /* Global data */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil picmg"; #else static char * progver = "3.08"; static char * progname = "ipicmg"; #endif static char fdebug = 0; static char fset_mc = 0; static uint8_t g_bus = PUBLIC_BUS; static uint8_t g_sa = BMC_SA; static uint8_t g_lun = BMC_LUN; static uint8_t g_addrtype = ADDR_SMI; static uint8_t g_fruid = 0; static unsigned char PicmgExtMajorVersion; /* the LED color capabilities */ static const char* led_color_str[] = { //__attribute__((unused)) = { "reserved", "BLUE", "RED", "GREEN", "AMBER", "ORANGE", "WHITE", "reserved" }; static const char* amc_link_type_str[] = { // __attribute__((unused)) = { "RESERVED", "RESERVED1", "PCI EXPRESS", "ADVANCED SWITCHING1", "ADVANCED SWITCHING2", "ETHERNET", "RAPIDIO", "STORAGE", }; static const char* amc_link_type_ext_str[][16]= { // __attribute__((unused)) /* FRU_PICMGEXT_AMC_LINK_TYPE_RESERVED */ { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_RESERVED1 */ { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_PCI_EXPRESS */ { "Gen 1 - NSSC", "Gen 1 - SSC", "Gen 2 - NSSC", "Gen 2 - SSC", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_ADVANCED_SWITCHING1 */ { "Gen 1 - NSSC", "Gen 1 - SSC", "Gen 2 - NSSC", "Gen 2 - SSC", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_ADVANCED_SWITCHING2 */ { "Gen 1 - NSSC", "Gen 1 - SSC", "Gen 2 - NSSC", "Gen 2 - SSC", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET */ { "1000BASE-BX (SerDES Gigabit)", "10GBASE-BX410 Gigabit XAUI", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_RAPIDIO */ { "1.25 Gbaud transmission rate", "2.5 Gbaud transmission rate", "3.125 Gbaud transmission rate", "", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE */ { "Fibre Channel", "Serial ATA", "Serial Attached SCSI", "", "", "", "", "", "", "", "", "", "", "", "", "" } }; typedef enum picmg_bused_resource_mode { PICMG_BUSED_RESOURCE_SUMMARY, } t_picmg_bused_resource_mode ; typedef enum picmg_card_type { PICMG_CARD_TYPE_CPCI, PICMG_CARD_TYPE_ATCA, PICMG_CARD_TYPE_AMC, PICMG_CARD_TYPE_RESERVED } t_picmg_card_type ; /* This is the version of the PICMG Extenstion */ static t_picmg_card_type PicmgCardType = PICMG_CARD_TYPE_RESERVED; const struct valstr picmg_frucontrol_vals[] = { { 0, "Cold Reset" }, { 1, "Warm Reset" }, { 2, "Graceful Reboot" }, { 3, "Issue Diagnostic Interrupt" }, { 4, "Quiesce" }, { 5, NULL }, }; const struct valstr picmg_clk_family_vals[] = { { 0x00, "Unspecified" }, { 0x01, "SONET/SDH/PDH" }, { 0x02, "Reserved for PCI Express" }, { 0x03, "Reserved" }, /* from 03h to C8h */ { 0xC9, "Vendor defined clock family" }, /* from C9h to FFh */ { 0x00, NULL }, }; const struct oemvalstr picmg_clk_accuracy_vals[] = { { 0x01, 10, "PRS" }, { 0x01, 20, "STU" }, { 0x01, 30, "ST2" }, { 0x01, 40, "TNC" }, { 0x01, 50, "ST3E" }, { 0x01, 60, "ST3" }, { 0x01, 70, "SMC" }, { 0x01, 80, "ST4" }, { 0x01, 90, "DUS" }, { 0x02, 0xE0, "PCI Express Generation 2" }, { 0x02, 0xF0, "PCI Express Generation 1" }, { 0xffffff, 0x00, NULL } }; const struct oemvalstr picmg_clk_resource_vals[] = { { 0x0, 0, "On-Carrier Device 0" }, { 0x0, 1, "On-Carrier Device 1" }, { 0x1, 1, "AMC Site 1 - A1" }, { 0x1, 2, "AMC Site 1 - A2" }, { 0x1, 3, "AMC Site 1 - A3" }, { 0x1, 4, "AMC Site 1 - A4" }, { 0x1, 5, "AMC Site 1 - B1" }, { 0x1, 6, "AMC Site 1 - B2" }, { 0x1, 7, "AMC Site 1 - B3" }, { 0x1, 8, "AMC Site 1 - B4" }, { 0x2, 0, "ATCA Backplane" }, { 0xffffff, 0x00, NULL } }; const struct oemvalstr picmg_clk_id_vals[] = { { 0x0, 0, "Clock 0" }, { 0x0, 1, "Clock 1" }, { 0x0, 2, "Clock 2" }, { 0x0, 3, "Clock 3" }, { 0x0, 4, "Clock 4" }, { 0x0, 5, "Clock 5" }, { 0x0, 6, "Clock 6" }, { 0x0, 7, "Clock 7" }, { 0x0, 8, "Clock 8" }, { 0x0, 9, "Clock 9" }, { 0x0, 10, "Clock 10" }, { 0x0, 11, "Clock 11" }, { 0x0, 12, "Clock 12" }, { 0x0, 13, "Clock 13" }, { 0x0, 14, "Clock 14" }, { 0x0, 15, "Clock 15" }, { 0x1, 1, "TCLKA" }, { 0x1, 2, "TCLKB" }, { 0x1, 3, "TCLKC" }, { 0x1, 4, "TCLKD" }, { 0x1, 5, "FLCKA" }, { 0x2, 1, "CLK1A" }, { 0x2, 2, "CLK1A" }, { 0x2, 3, "CLK1A" }, { 0x2, 4, "CLK1A" }, { 0x2, 5, "CLK1A" }, { 0x2, 6, "CLK1A" }, { 0x2, 7, "CLK1A" }, { 0x2, 8, "CLK1A" }, { 0x2, 9, "CLK1A" }, { 0xffffff, 0x00, NULL } }; const struct valstr picmg_busres_id_vals[] = { { 0x0, "Metallic Test Bus pair #1" }, { 0x1, "Metallic Test Bus pair #2" }, { 0x2, "Synch clock group 1 (CLK1)" }, { 0x3, "Synch clock group 2 (CLK2)" }, { 0x4, "Synch clock group 3 (CLK3)" }, { 0x5, NULL } }; const struct valstr picmg_busres_board_cmd_vals[] = { { 0x0, "Query" }, { 0x1, "Release" }, { 0x2, "Force" }, { 0x3, "Bus Free" }, { 0x4, NULL } }; const struct valstr picmg_busres_shmc_cmd_vals[] = { { 0x0, "Request" }, { 0x1, "Relinquish" }, { 0x2, "Notify" }, { 0x3, NULL } }; const struct oemvalstr picmg_busres_board_status_vals[] = { { 0x0, 0x0, "In control" }, { 0x0, 0x1, "No control" }, { 0x1, 0x0, "Ack" }, { 0x1, 0x1, "Refused" }, { 0x1, 0x2, "No control" }, { 0x2, 0x0, "Ack" }, { 0x2, 0x1, "No control" }, { 0x3, 0x0, "Accept" }, { 0x3, 0x1, "Not Needed" }, { 0xffffff, 0x00, NULL } }; const struct oemvalstr picmg_busres_shmc_status_vals[] = { { 0x0, 0x0, "Grant" }, { 0x0, 0x1, "Busy" }, { 0x0, 0x2, "Defer" }, { 0x0, 0x3, "Deny" }, { 0x1, 0x0, "Ack" }, { 0x1, 0x1, "Error" }, { 0x2, 0x0, "Ack" }, { 0x2, 0x1, "Error" }, { 0x2, 0x2, "Deny" }, { 0xffffff, 0x00, NULL } }; void ipmi_picmg_help (void) { printf(" properties - get PICMG properties\n"); printf(" frucontrol - FRU control\n"); printf(" addrinfo - get address information\n"); printf(" activate - activate a FRU\n"); printf(" deactivate - deactivate a FRU\n"); printf(" policy get - get the FRU activation policy\n"); printf(" policy set - set the FRU activation policy\n"); printf(" portstate get - get port state \n"); printf(" portstate getdenied - get all denied[disabled] port description\n"); printf(" portstate getgranted - get all granted[enabled] port description\n"); printf(" portstate getall - get all port state description\n"); printf(" portstate set - set port state \n"); printf(" amcportstate get - get port state \n"); printf(" amcportstate set - set port state \n"); printf(" led prop - get led properties\n"); printf(" led cap - get led color capabilities\n"); printf(" led get - get led state\n"); printf(" led set - set led state\n"); printf(" power get - get power level info\n"); printf(" power set - set power level\n"); printf(" clk get - get clk state\n"); printf(" clk getdenied - get all(up to 16) denied[disabled] clock descriptions\n"); printf(" clk getgranted - get all(up to 16) granted[enabled] clock descriptions\n"); printf(" clk getall - get all(up to 16) clock descriptions\n"); printf(" clk set - set clk state\n"); printf(" busres summary - display brief bused resource status info \n"); } struct sAmcAddrMap { unsigned char ipmbLAddr; char* amcBayId; unsigned char siteNum; } amcAddrMap[] = { {0xFF, "reserved", 0}, {0x72, "A1" , 1}, {0x74, "A2" , 2}, {0x76, "A3" , 3}, {0x78, "A4" , 4}, {0x7A, "B1" , 5}, {0x7C, "B2" , 6}, {0x7E, "B3" , 7}, {0x80, "B4" , 8}, {0x82, "reserved", 0}, {0x84, "reserved", 0}, {0x86, "reserved", 0}, {0x88, "reserved", 0}, }; int ipmi_picmg_getaddr(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[5]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_ADDRESS_INFO_CMD; req.msg.data = msg_data; req.msg.data_len = 2; msg_data[0] = 0; /* picmg identifier */ msg_data[1] = 0; /* default fru id */ if(argc > 0) { msg_data[1] = (uint8_t)strtoul(argv[0], NULL,0); /* FRU ID */ } rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error getting address information CC: 0x%02x\n", rv); return rv; } printf("Hardware Address : 0x%02x\n", rsp[1]); printf("IPMB-0 Address : 0x%02x\n", rsp[2]); printf("FRU ID : 0x%02x\n", rsp[4]); printf("Site ID : 0x%02x\n", rsp[5]); printf("Site Type : "); switch (rsp[6]) { case PICMG_ATCA_BOARD: printf("ATCA board\n"); break; case PICMG_POWER_ENTRY: printf("Power Entry Module\n"); break; case PICMG_SHELF_FRU: printf("Shelf FRU\n"); break; case PICMG_DEDICATED_SHMC: printf("Dedicated Shelf Manager\n"); break; case PICMG_FAN_TRAY: printf("Fan Tray\n"); break; case PICMG_FAN_FILTER_TRAY: printf("Fan Filter Tray\n"); break; case PICMG_ALARM: printf("Alarm module\n"); break; case PICMG_AMC: printf("AMC"); printf(" -> IPMB-L Address: 0x%02x\n", amcAddrMap[rsp[5]].ipmbLAddr); break; case PICMG_PMC: printf("PMC\n"); break; case PICMG_RTM: printf("RTM\n"); break; default: if (rsp[6] >= 0xc0 && rsp[6] <= 0xcf) { printf("OEM\n"); } else { printf("unknown\n"); } } return 0; } int ipmi_picmg_properties(void * intf, int show ) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; unsigned char PicmgExtMajorVersion; struct ipmi_rq req; unsigned char msg_data; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_PICMG_PROPERTIES_CMD; req.msg.data = &msg_data; req.msg.data_len = 1; msg_data = 0; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error %d getting picmg properties\n", rv); return rv; } if( show ) { printf("PICMG identifier : 0x%02x\n", rsp[0]); printf("PICMG Ext. Version : %i.%i\n", rsp[1]&0x0f, (rsp[1]&0xf0) >> 4); printf("Max FRU Device ID : 0x%02x\n", rsp[2]); printf("FRU Device ID : 0x%02x\n", rsp[3]); } /* We cache the major extension version ... to know how to format some commands */ PicmgExtMajorVersion = rsp[1]&0x0f; if( PicmgExtMajorVersion == PICMG_CPCI_MAJOR_VERSION ) { PicmgCardType = PICMG_CARD_TYPE_CPCI; } else if( PicmgExtMajorVersion == PICMG_ATCA_MAJOR_VERSION) { PicmgCardType = PICMG_CARD_TYPE_ATCA; } else if( PicmgExtMajorVersion == PICMG_AMC_MAJOR_VERSION) { PicmgCardType = PICMG_CARD_TYPE_AMC; } return 0; } #define PICMG_FRU_DEACTIVATE (unsigned char) 0x00 #define PICMG_FRU_ACTIVATE (unsigned char) 0x01 int ipmi_picmg_fru_activation(void * intf, int argc, char ** argv, unsigned char state) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; struct picmg_set_fru_activation_cmd cmd; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_FRU_ACTIVATION_CMD; req.msg.data = (unsigned char*) &cmd; req.msg.data_len = 3; cmd.picmg_id = 0; /* PICMG identifier */ cmd.fru_id = atob(argv[0]); /* FRU ID */ cmd.fru_state = state; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error %d on activation/deactivation of FRU\n",rv); return rv; } if (rsp[0] != 0x00) { printf("Error, invalid response\n"); } return 0; } int ipmi_picmg_fru_activation_policy_get(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[4]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_FRU_POLICY_CMD; req.msg.data = msg_data; req.msg.data_len = 2; msg_data[0] = 0; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU ID */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } printf(" %s\n", ((rsp[1] & 0x01) == 0x01) ? "activation locked" : "activation not locked"); printf(" %s\n", ((rsp[1] & 0x02) == 0x02) ? "deactivation locked" : "deactivation not locked"); return 0; } int ipmi_picmg_fru_activation_policy_set(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[4]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_SET_FRU_POLICY_CMD; req.msg.data = msg_data; req.msg.data_len = 4; msg_data[0] = 0; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU ID */ msg_data[2] = atob(argv[1])& 0x03; /* FRU act policy mask */ msg_data[3] = atob(argv[2])& 0x03; /* FRU act policy set bits */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } #define PICMG_MAX_LINK_PER_CHANNEL 4 int ipmi_picmg_portstate_get(void * intf, int interfc, uchar channel, int mode) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[4]; struct fru_picmgext_link_desc* d; /* descriptor pointer for rec. data */ memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_PORT_STATE_CMD; req.msg.data = msg_data; req.msg.data_len = 2; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = (interfc & 0x3)<<6; /* interface */ msg_data[1] |= (channel & 0x3F); /* channel number */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else if( mode == PICMG_EKEY_MODE_QUERY ) printf("returned Completion Code 0x%02x\n", rv); return rv; } if (rsp_len >= 6) { int index; /* add support for more than one link per channel */ for(index=0;index (1+ (index*5))){ d = (struct fru_picmgext_link_desc *) &(rsp[1 + (index*5)]); if ( mode == PICMG_EKEY_MODE_PRINT_ALL || mode == PICMG_EKEY_MODE_QUERY || ( mode == PICMG_EKEY_MODE_PRINT_ENABLED && rsp[5 + (index*5) ] == 0x01 ) || ( mode == PICMG_EKEY_MODE_PRINT_DISABLED && rsp[5 + (index*5) ] == 0x00 ) ) { printf(" Link Grouping ID: 0x%02x\n", d->grouping); printf(" Link Type Extension: 0x%02x\n", d->ext); printf(" Link Type: 0x%02x ", d->type); if (d->type == 0 || d->type == 0xff) { printf("Reserved %d\n",d->type); } else if (d->type >= 0x06 && d->type <= 0xef) { printf("Reserved %d\n",d->type); } else if (d->type >= 0xf0 && d->type <= 0xfe) { printf("OEM GUID Definition %d\n",d->type); } else { switch (d->type) { case FRU_PICMGEXT_LINK_TYPE_BASE: printf("PICMG 3.0 Base Interface 10/100/1000\n"); break; case FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET: printf("PICMG 3.1 Ethernet Fabric Interface\n"); break; case FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND: printf("PICMG 3.2 Infiniband Fabric Interface\n"); break; case FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR: printf("PICMG 3.3 Star Fabric Interface\n"); break; case FRU_PICMGEXT_LINK_TYPE_PCIE: printf("PCI Express Fabric Interface\n"); break; default: printf("Invalid\n"); break; } } printf(" Link Designator: \n"); printf(" Port Flag: 0x%02x\n", d->desig_port); printf(" Interface: 0x%02x - ", d->desig_if); switch (d->desig_if) { case FRU_PICMGEXT_DESIGN_IF_BASE: printf("Base Interface\n"); break; case FRU_PICMGEXT_DESIGN_IF_FABRIC: printf("Fabric Interface\n"); break; case FRU_PICMGEXT_DESIGN_IF_UPDATE_CHANNEL: printf("Update Channel\n"); break; case FRU_PICMGEXT_DESIGN_IF_RESERVED: printf("Reserved\n"); break; default: printf("Invalid"); break; } printf(" Channel Number: 0x%02x\n", d->desig_channel); printf(" STATE: %s\n", ( rsp[5 +(index*5)] == 0x01) ?"enabled":"disabled"); printf("\n"); } } } } else { printf("Unexpected answer len %d, can't print result\n",rsp_len); } return 0; } int ipmi_picmg_portstate_set(void * intf, int interfc, uchar channel, uchar port, int type, int typeext, int group, int enable) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; // struct fru_picmgext_link_desc* d; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_SET_PORT_STATE_CMD; req.msg.data = msg_data; req.msg.data_len = 6; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = (channel & 0x3f) | ((interfc & 3) << 6); msg_data[2] = (port & 0xf) | ((type & 0xf) << 4); msg_data[3] = ((type >> 4) & 0xf) | ((typeext & 0xf) << 4); msg_data[4] = group & 0xff; msg_data[5] = (unsigned char) (enable & 0x01); /* en/dis */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } /* AMC.0 commands */ #define PICMG_AMC_MAX_LINK_PER_CHANNEL 4 int ipmi_picmg_amc_portstate_get(void * intf,int device,uchar channel, int mode) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[4]; struct fru_picmgext_amc_link_info* d; /* descriptor pointer for rec. data */ memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_AMC_GET_PORT_STATE_CMD; req.msg.data = msg_data; /* FIXME : add check for AMC or carrier device */ if(device == -1 || PicmgCardType != PICMG_CARD_TYPE_ATCA ){ req.msg.data_len = 2; /* for amc only channel */ }else{ req.msg.data_len = 3; /* for carrier channel and device */ } msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = channel ; msg_data[2] = (uchar)device ; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else if ( mode == PICMG_EKEY_MODE_QUERY ) printf("returned Completion Code 0x%02x\n", rv); return rv; } if (rsp_len >= 5) { int index; /* add support for more than one link per channel */ for(index=0;index (1+ (index*4))){ unsigned char type; unsigned char ext; unsigned char grouping; unsigned char port; unsigned char enabled; d = (struct fru_picmgext_amc_link_info *)&(rsp[1 + (index*4)]); /* Removed endianness check here, probably not required as we dont use bitfields */ port = d->linkInfo[0] & 0x0F; type = ((d->linkInfo[0] & 0xF0) >> 4 )|(d->linkInfo[1] & 0x0F ); ext = ((d->linkInfo[1] & 0xF0) >> 4 ); grouping = d->linkInfo[2]; enabled = rsp[4 + (index*4) ]; if ( mode == PICMG_EKEY_MODE_PRINT_ALL || mode == PICMG_EKEY_MODE_QUERY || ( mode == PICMG_EKEY_MODE_PRINT_ENABLED && enabled == 0x01 ) || ( mode == PICMG_EKEY_MODE_PRINT_DISABLED && enabled == 0x00 ) ) { if(device == -1 || PicmgCardType != PICMG_CARD_TYPE_ATCA ){ printf(" Link device : AMC\n"); }else{ printf(" Link device : 0x%02x\n", device ); } printf(" Link Grouping ID: 0x%02x\n", grouping); if (type == 0 || type == 1 ||type == 0xff) { printf(" Link Type Extension: 0x%02x\n", ext); printf(" Link Type: Reserved\n"); } else if (type >= 0xf0 && type <= 0xfe) { printf(" Link Type Extension: 0x%02x\n", ext); printf(" Link Type: OEM GUID Definition\n"); } else { if (type <= FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE ) { printf(" Link Type Extension: %s\n", amc_link_type_ext_str[type][ext]); printf(" Link Type: %s\n", amc_link_type_str[type]); } else{ printf(" Link Type Extension: 0x%02x\n", ext); printf(" Link Type: undefined\n"); } } printf(" Link Designator: \n"); printf(" Channel Number: 0x%02x\n", channel); printf(" Port Flag: 0x%02x\n", port ); printf(" STATE: %s\n", ( enabled == 0x01 )?"enabled":"disabled"); printf("\n"); } } } } else { printf("ipmi_picmg_amc_portstate_get: " "Unexpected answer, can't print result\n"); } return 0; } int ipmi_picmg_amc_portstate_set(void * intf, uchar channel, uchar port, int type, int typeext, int group, int enable, int device) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[7]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_AMC_SET_PORT_STATE_CMD; req.msg.data = msg_data; msg_data[0] = 0x00; /* PICMG identifier*/ msg_data[1] = channel; /* channel id */ msg_data[2] = port & 0xF; /* port flags */ msg_data[2] |= (type & 0x0F)<<4; /* type */ msg_data[3] = (type & 0xF0)>>4; /* type */ msg_data[3] |= (typeext & 0x0F)<<4; /* extension */ msg_data[4] = (group & 0xFF); /* group */ msg_data[5] = (enable & 0x01); /* state */ req.msg.data_len = 6; /* device id - only for carrier needed */ if (device >= 0) { msg_data[6] = (uchar)device; req.msg.data_len = 7; } rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } int ipmi_picmg_get_led_properties(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_FRU_LED_PROPERTIES_CMD; req.msg.data = msg_data; req.msg.data_len = 2; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } printf("General Status LED Properties: 0x%2x\n\r", rsp[1] ); printf("App. Specific LED Count: 0x%2x\n\r", rsp[2] ); return 0; } int ipmi_picmg_get_led_capabilities(void * intf, int argc, char ** argv) { int i; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_LED_COLOR_CAPABILITIES_CMD; req.msg.data = msg_data; req.msg.data_len = 3; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* LED-ID */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } printf("LED Color Capabilities: %02x", rsp[1] ); for ( i=0 ; i<8 ; i++ ) { if ( rsp[1] & (0x01 << i) ) { printf("%s, ", led_color_str[ i ]); } } printf("\n\r"); printf("Default LED Color in\n\r"); printf(" LOCAL control: %s\n\r", led_color_str[ rsp[2] ] ); printf(" OVERRIDE state: %s\n\r", led_color_str[ rsp[3] ] ); return 0; } int ipmi_picmg_get_led_state(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_FRU_LED_STATE_CMD; req.msg.data = msg_data; req.msg.data_len = 3; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* LED-ID */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } printf("LED states: %x ", rsp[1] ); if (rsp[1] == 0x1) printf("[LOCAL CONTROL]\n\r"); else if (rsp[1] == 0x2) printf("[OVERRIDE]\n\r"); else if (rsp[1] == 0x4) printf("[LAMPTEST]\n\r"); else printf("\n\r"); printf(" Local Control function: %x ", rsp[2] ); if (rsp[2] == 0x0) printf("[OFF]\n\r"); else if (rsp[2] == 0xff) printf("[ON]\n\r"); else printf("[BLINKING]\n\r"); printf(" Local Control On-Duration: %x\n\r", rsp[3] ); printf(" Local Control Color: %x [%s]\n\r", rsp[4], led_color_str[ rsp[4] ]); /* override state or lamp test */ if (rsp[1] == 0x02) { printf(" Override function: %x ", rsp[5] ); if (rsp[2] == 0x0) printf("[OFF]\n\r"); else if (rsp[2] == 0xff) printf("[ON]\n\r"); else printf("[BLINKING]\n\r"); printf(" Override On-Duration: %x\n\r", rsp[6] ); printf(" Override Color: %x [%s]\n\r", rsp[7], led_color_str[ rsp[7] ]); }else if (rsp[1] == 0x06) { printf(" Override function: %x ", rsp[5] ); if (rsp[2] == 0x0) printf("[OFF]\n\r"); else if (rsp[2] == 0xff) printf("[ON]\n\r"); else printf("[BLINKING]\n\r"); printf(" Override On-Duration: %x\n\r", rsp[6] ); printf(" Override Color: %x [%s]\n\r", rsp[7], led_color_str[ rsp[7] ]); printf(" Lamp test duration: %x\n\r", rsp[8] ); } return 0; } int ipmi_picmg_set_led_state(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_SET_FRU_LED_STATE_CMD; req.msg.data = msg_data; req.msg.data_len = 6; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* LED-ID */ msg_data[3] = atob(argv[2]); /* LED function */ msg_data[4] = atob(argv[3]); /* LED on duration */ msg_data[5] = atob(argv[4]); /* LED color */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } int ipmi_picmg_get_power_level(void * intf, int argc, char ** argv) { int i; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_POWER_LEVEL_CMD; req.msg.data = msg_data; req.msg.data_len = 3; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* Power type */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } printf("Dynamic Power Configuration: %s\n", (rsp[1]&0x80)==0x80?"enabled":"disabled" ); printf("Actual Power Level: %i\n", (rsp[1] & 0xf)); printf("Delay to stable Power: %i\n", rsp[2]); printf("Power Multiplier: %i\n", rsp[3]); for ( i = 1; i+3 < rsp_len ; i++ ) { printf(" Power Draw %i: %i\n", i, (rsp[i+3]) * rsp[3] / 10); } return 0; } int ipmi_picmg_set_power_level(void * intf, int argc, char ** argv) { // int i; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_SET_POWER_LEVEL_CMD; req.msg.data = msg_data; req.msg.data_len = 4; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* power level */ msg_data[3] = atob(argv[2]); /* present to desired */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } int ipmi_picmg_bused_resource(void * intf, t_picmg_bused_resource_mode mode) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); switch ( mode ) { case PICMG_BUSED_RESOURCE_SUMMARY: { t_picmg_busres_resource_id resource; t_picmg_busres_board_cmd_types cmd =PICMG_BUSRES_BOARD_CMD_QUERY; req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_BUSED_RESOURCE_CMD; req.msg.data = msg_data; req.msg.data_len = 3; /* IF BOARD query for all resources */ for( resource=PICMG_BUSRES_METAL_TEST_BUS_1;resource<=PICMG_BUSRES_SYNC_CLOCK_GROUP_3;resource+=(t_picmg_busres_resource_id)1 ) { msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = (unsigned char) cmd; msg_data[2] = (unsigned char) resource; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("bused resource control: no response\n"); else printf("bused resource control: returned Completion Code 0x%02x\n",rv); return rv; } else { printf("Resource 0x%02x '%-26s' : 0x%02x [%s] \n" , resource, val2str(resource,picmg_busres_id_vals), rsp[1], oemval2str(cmd,rsp[1], picmg_busres_board_status_vals)); } } } break; default: rv = -1; break; } return rv; } int ipmi_picmg_fru_control(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_FRU_CONTROL_CMD; req.msg.data = msg_data; req.msg.data_len = 3; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* control option */ printf("FRU Device Id: %d FRU Control Option: %s\n\r", msg_data[1], \ val2str( msg_data[2], picmg_frucontrol_vals)); rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("frucontrol: no response\n"); else printf("frucontrol: returned Completion Code 0x%02x\n",rv); return rv; } else { printf("frucontrol: ok\n"); } return 0; } int ipmi_picmg_clk_get(void * intf, int clk_id,int clk_res,int mode) { // int i; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char enabled; unsigned char direction; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_AMC_GET_CLK_STATE_CMD; req.msg.data = msg_data; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = clk_id; if(clk_res == -1 || PicmgCardType != PICMG_CARD_TYPE_ATCA ){ req.msg.data_len = 2; /* for amc only channel */ }else{ req.msg.data_len = 3; /* for carrier channel and device */ msg_data[2] = clk_res; } rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } { enabled = (rsp[1]&0x8)!=0; direction = (rsp[1]&0x4)!=0; if ( mode == PICMG_EKEY_MODE_QUERY || mode == PICMG_EKEY_MODE_PRINT_ALL || ( mode == PICMG_EKEY_MODE_PRINT_DISABLED && enabled == 0 ) || ( mode == PICMG_EKEY_MODE_PRINT_ENABLED && enabled == 1 ) ) { if( PicmgCardType != PICMG_CARD_TYPE_AMC ) { printf("CLK resource id : %3d [ %s ]\n", clk_res , oemval2str( ((clk_res>>6)&0x03), (clk_res&0x0F), picmg_clk_resource_vals)); } else { printf("CLK resource id : N/A [ AMC Module ]\n"); clk_res = 0x40; /* Set */ } printf("CLK id : %3d [ %s ]\n", clk_id, oemval2str( ((clk_res>>6)&0x03), clk_id , picmg_clk_id_vals)); printf("CLK setting : 0x%02x\n", rsp[1]); printf(" - state: %s\n", (enabled)?"enabled":"disabled"); printf(" - direction: %s\n", (direction)?"Source":"Receiver"); printf(" - PLL ctrl: 0x%x\n", rsp[1]&0x3); if(enabled){ unsigned long freq = 0; freq = ( rsp[5] << 0 | rsp[6] << 8 | rsp[7] << 16 | rsp[8] << 24 ); printf(" - Index: %3d\n", rsp[2]); printf(" - Family: %3d [ %s ]\n", rsp[3], val2str( rsp[3], picmg_clk_family_vals)); printf(" - AccLVL: %3d [ %s ]\n", rsp[4], oemval2str(rsp[3],rsp[4],picmg_clk_accuracy_vals)); printf(" - Freq: %lu\n", freq); } } } return 0; } int ipmi_picmg_clk_set(void * intf, int argc, char ** argv) { // int i; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[11]; unsigned long freq=0; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_AMC_SET_CLK_STATE_CMD; req.msg.data = msg_data; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = (uchar)strtoul(argv[0], NULL,0); /* clk id */ msg_data[2] = (uchar)strtoul(argv[1], NULL,0); /* clk index */ msg_data[3] = (uchar)strtoul(argv[2], NULL,0); /* setting */ msg_data[4] = (uchar)strtoul(argv[3], NULL,0); /* family */ msg_data[5] = (uchar)strtoul(argv[4], NULL,0); /* acc */ freq = strtoul(argv[5], NULL,0); msg_data[6] = (uchar)((freq >> 0)& 0xFF); /* freq */ msg_data[7] = (uchar)((freq >> 8)& 0xFF); /* freq */ msg_data[8] = (uchar)((freq >>16)& 0xFF); /* freq */ msg_data[9] = (uchar)((freq >>24)& 0xFF); /* freq */ req.msg.data_len = 10; if( PicmgCardType == PICMG_CARD_TYPE_ATCA ) { if( argc > 7) { req.msg.data_len = 11; msg_data[10] = (uchar)strtoul(argv[6], NULL,0); /* resource id */ } else { printf("missing resource id for atca board\n"); return -1; } } #if 1 printf("## ID: %d\n", msg_data[1]); printf("## index: %d\n", msg_data[2]); printf("## setting: 0x%02x\n", msg_data[3]); printf("## family: %d\n", msg_data[4]); printf("## acc: %d\n", msg_data[5]); printf("## freq: %lu\n", freq ); printf("## res: %d\n", msg_data[10]); #endif rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } #ifdef METACOMMAND int i_picmg(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int rc = 0; int showProperties = 0; void *intf = NULL; int c, i; char *s1; printf("%s ver %s\n", progname,progver); while ( (c = getopt( argc, argv,"m:i:T:V:J:EYF:P:N:R:U:Z:x?")) != EOF) switch (c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } fset_mc = 1; ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'i': /*specify a fru id*/ if (strncmp(optarg,"0x",2) == 0) g_fruid = htoi(&optarg[2]); else g_fruid = htoi(optarg); printf("Using FRU ID 0x%02x\n",g_fruid); break; case 'x': fdebug = 1; break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; case '?': ipmi_picmg_help(); return ERR_USAGE; break; } for (i = 0; i < optind; i++) { argv++; argc--; } /* Get PICMG properties is called to obtain version information */ if (argc !=0 && !strncmp(argv[0], "properties", 10)) { showProperties =1; } if (argc == 0 || (!strncmp(argv[0], "help", 4))) { ipmi_picmg_help(); return ERR_USAGE; } rc = ipmi_picmg_properties(intf,showProperties); if (rc < 0) { /*cannot contact MC, so exit*/ goto do_exit; } /* address info command */ else if (!strncmp(argv[0], "addrinfo", 8)) { rc = ipmi_picmg_getaddr(intf, argc-1, &argv[1]); } else if (!strncmp(argv[0], "busres", 6)) { if (argc > 1) { if (!strncmp(argv[1], "summary", 7)) { ipmi_picmg_bused_resource(intf, PICMG_BUSED_RESOURCE_SUMMARY ); } } else { printf("usage: busres summary\n"); } } /* fru control command */ else if (!strncmp(argv[0], "frucontrol", 10)) { if (argc > 2) { rc = ipmi_picmg_fru_control(intf, argc-1, &(argv[1])); } else { printf("usage: frucontrol