diff options
Diffstat (limited to 'util/icmd.c')
-rw-r--r-- | util/icmd.c | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/util/icmd.c b/util/icmd.c new file mode 100644 index 0000000..5911262 --- /dev/null +++ b/util/icmd.c @@ -0,0 +1,366 @@ +/* + * 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 <types.h> + #include <libdbg.h> + #include <unistd.h> + #include <errno.h> +#else + /* Linux, Solaris, BSD, Windows */ + #include <stdio.h> + #include <stdlib.h> + #include <sys/types.h> + #include <sys/stat.h> + #include <fcntl.h> + #include <string.h> + #ifdef WIN32 + #include "getopt.h" + #elif defined(DOS) + #include <dos.h> + #include "getopt.h" + #elif defined(HPUX) + /* getopt is defined in stdio.h */ +#elif defined(MACOS) +/* getopt is defined in unistd.h */ +#include <unistd.h> + #else + #include <getopt.h> + #endif +#endif +#include "ipmicmd.h" +extern void ipmi_lan_set_timeout(int ipmito, int tries, int pingto); + +/* + * Global variables + */ +static char * progver = "2.93"; +static char * progname = "icmd"; +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:xN: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 '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(); + 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 */ |