summaryrefslogtreecommitdiff
path: root/util/ireset.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/ireset.c')
-rw-r--r--util/ireset.c751
1 files changed, 751 insertions, 0 deletions
diff --git a/util/ireset.c b/util/ireset.c
new file mode 100644
index 0000000..8116b7d
--- /dev/null
+++ b/util/ireset.c
@@ -0,0 +1,751 @@
+/*
+ * ireset.c (was hwreset.c)
+ *
+ * This tool power cycles (or powers off) the IPMI system.
+ *
+ * Author: Andy Cress arcress at users.sourceforge.net
+ * Copyright (c) 2009 Kontron America, Inc.
+ * Copyright (c) 2002-2008 Intel Corporation
+ *
+ * 01/08/02 Andy Cress - created
+ * 01/31/02 Andy Cress - converted to use ipmi_cmd_ia,
+ * added more user options
+ * 02/06/02 Andy Cress - added ipmi_cmd_va
+ * 02/22/02 Andy Cress - added -s to reboot to service partition
+ * 07/02/02 Andy Cress v1.3 added more Usage text
+ * 08/02/02 Andy Cress v1.4 moved common ipmi_cmd() code to ipmicmd.c
+ * 09/24/02 Andy Cress - stubbed in OS shutdown option
+ * 01/29/03 Andy Cress v1.5 added MV OpenIPMI support
+ * 04/08/03 Andy Cress v1.6 added OS shutdown option (-o)
+ * 05/02/03 Andy Cress v1.7 leave console redir alone in SET_BOOT_OPTIONS
+ * 05/05/04 Andy Cress v1.8 call ipmi_close before exit, did WIN32 port.
+ * 08/09/04 Andy Cress v1.9 make sure to show error if ccode != 0, and
+ * detect Langley platforms to do special
+ * watchdog method for -o option.
+ * 11/01/04 Andy Cress 1.10 add -N / -R for remote nodes
+ * 11/16/04 Andy Cress 1.11 add -U for remote username
+ * 11/30/04 Andy Cress 1.12 fix bug 1075550 with -o -N, skip -o if not local.
+ * 03/28/05 Andy Cress 1.13 add netapp_reset commands for platforms that
+ * use this instead of chassis_reset.
+ * 05/16/05 Andy Cress 1.14 add -u option for power up
+ * 03/31/06 Andy Cress 1.15 add -e -p -m options
+ * 09/18/06 Andy Cress 1.20 allow more platforms to do soft reset, and
+ * if Tyan, ignore set boot options errors.
+ * 01/10/07 Andy Cress 1.25 added reset_str(), modify initchar (6) if -o.
+ */
+/*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 <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "getopt.h"
+#elif defined(EFI)
+ // EFI: defined (EFI32) || defined (EFI64) || defined(EFIX64)
+ // also would define ALONE (not METACOMMAND) to minimize externals
+ #ifndef NULL
+ #define NULL 0
+ #endif
+ #include <types.h>
+ #include <libdbg.h>
+ #include <unistd.h>
+#elif defined(DOS)
+#include <dos.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "getopt.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#if defined(HPUX)
+/* getopt is defined in stdio.h */
+#elif defined(MACOS)
+/* getopt is defined in unistd.h */
+#include <unistd.h>
+#else
+#include <getopt.h>
+#endif
+#endif
+#include <string.h>
+#include "ipmicmd.h"
+#include "oem_intel.h" /* for is_romley*/
+
+#define platIntel 1 /*Intel Sahalee servers, use alt soft-shutdown.*/
+#define platMBMC 2 /*mini-BMC platforms */
+#define platS5500 3 /*Intel S5500 platforms */
+#define platOther 4 /*Other platforms */
+#define GET_POWER_STATE 0x07
+#define INIT_VAL 0xff
+
+/*
+ * Global variables
+ */
+static char * progver = "2.93";
+static char * progname = "ireset";
+static uchar ipmi_maj;
+static uchar ipmi_min;
+static uchar sms_sa = 0x81;
+static char fdebug = 0;
+static char fipmilan = 0;
+static char fignore_opterr = 0;
+static char fwait = 0;
+static char fpersist = 0;
+static char platform = 0; /* platform type: MBMC or TSR */
+static int shuttime = 60; /* shutdown timeout in seconds */
+#define MAX_INIT 77 /* 80 minus 3 for IANA */
+static char * initstr = NULL; /* boot initiator mailbox string */
+static uchar iana[3] = { 0x00, 0x00, 0x00 }; /*default to devid, see -j */
+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 gbootparm = 0x48; //verbose disply, bypass pswd, same console redir
+
+#if defined(EFI)
+int getopt(int argc, char **argv, const char *opts)
+{ /*very simple getopt */
+ int c = EOF;
+ static int iopt = 0;
+ iopt++;
+ if ((argc <= iopt) || (argv[iopt] == NULL)) return c;
+ if (argv[iopt][0] == '-') c = argv[iopt][1];
+ return(c);
+}
+#endif
+#if defined(ALONE)
+int is_romley(int vend, int prod)
+{
+ int ret = 0;
+ if (vend != VENDOR_INTEL) return(ret);
+ if (prod >= 0x0048 && prod <= 0x005e) ret = 1;
+ return(ret);
+}
+int write_syslog(char *msg) { return(0); } /*stub*/
+#else
+/*extern*/ int write_syslog(char *msg); /*from showsel.c*/
+#endif
+
+static void show_error(char *tag, int rv, uchar cc)
+{
+ if (rv > 0 && cc == 0) cc = (uchar)rv;
+ printf("%s: error %d ccode = %x %s\n",
+ tag,rv,cc,decode_cc((ushort)0,cc));
+ return;
+}
+
+static int set_wdt(uchar val, uchar act)
+{
+ uchar idata[6];
+ uchar rdata[16];
+ int rlen = 8;
+ uchar ccode;
+ int ret, t;
+
+ t = val * 10; /* val is in sec, make timeout in 100msec */
+ if ((ipmi_maj > 1) || /* IPMI 1.5 or greater */
+ (ipmi_maj == 1 && ipmi_min >= 5))
+ idata[0] = 0x44; /* DontLog=0, DontStop=1 & use SMS/OS */
+ else idata[0] = 0x04; /* IPMI 1.0 or less */
+ idata[1] = act;
+ /* 0x01; * action: no pretimeout, hard reset action */
+ /* 0x02; * action value for power down instead */
+ idata[2] = 0; /* pretimeout: 30 sec (but disabled) */
+ 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_mc(WATCHDOG_SET, idata, 6, rdata, &rlen, &ccode, fdebug);
+ if (fdebug) printf("set_wdt: wd set(%d,%d) rv=%d cc=%x\n",
+ val,act,ret,ccode);
+ if (ret == 0 && ccode != 0) ret = ccode;
+
+ if (ret == 0) { /* Start the timer by issuing a watchdog reset */
+ ret = ipmi_cmd_mc(WATCHDOG_RESET,idata,0,rdata,&rlen, &ccode,fdebug);
+ if (fdebug) printf("set_wdt: wd reset rv=%d cc=%x\n",ret,ccode);
+ if (ret == 0 && ccode != 0) ret = ccode;
+ }
+ return(ret);
+} /*end set_wdt()*/
+
+char *reset_str(uchar breset, uchar bopt)
+{
+ char *str;
+ switch(breset) {
+ case 0: str = "powering down"; break;
+ case 1: str = "powering up"; break;
+ case 2: str = "power cycling"; break;
+ case 3: str = "resetting"; break; /* -r, etc.*/
+ case 4: str = "sending NMI"; break;
+ case 5: str = "shutdown/reset"; break;
+ case 6: str = "shutdown/power_off"; break; /*via agent*/
+ case 7: str = "cold reset"; break;
+ default: str = "resetting"; break;
+ }
+ if (bopt > 0)
+ switch(bopt) {
+ case 1: str = "resetting to Svc partition"; break;
+ case 2: str = "resetting to EFI"; break;
+ case 3: str = "resetting to PXE"; break;
+ case 4: str = "resetting to CDROM"; break;
+ case 5: str = "resetting to hard disk"; break;
+ case 6: str = "resetting to BIOS Setup"; break;
+ case 7: str = "resetting to floppy"; break;
+ default: str = "resetting"; break;
+ }
+ return(str);
+}
+
+int set_boot_init_string(char *istr)
+{
+ int rv = 0;
+ uchar idata[20]; /*need 17 bytes*/
+ uchar rdata[MAX_BUFFER_SIZE];
+ uchar cc;
+ int i, n, len, rlen;
+
+ /* set param 7 for boot initiator mailbox */
+ len = (int)strlen(istr);
+ n = 0;
+ for (i = 0; n < len; i++)
+ {
+ memset(idata,0,18);
+ idata[0] = 0x07; /* param, 7 = boot init mailbox */
+ idata[1] = i; /* set selector */
+ if (i == 0) { /* insert IANA */
+ idata[2] = iana[0];
+ idata[3] = iana[1];
+ idata[4] = iana[2];
+ strncpy(&idata[5],&istr[n],13);
+ n += 13;
+ } else {
+ strncpy(&idata[2],&istr[n],16);
+ n += 16;
+ }
+ rlen = MAX_BUFFER_SIZE;
+ rv = ipmi_cmd_mc(SET_BOOT_OPTIONS, idata, 18, rdata, &rlen, &cc, fdebug);
+ if (rv == 0 && cc != 0) rv = cc;
+ if (rv != 0) break;
+ }
+ return(rv);
+}
+
+static int IPMI_Reset(uchar bpower, uchar bootopt)
+{
+ uchar responseData[MAX_BUFFER_SIZE];
+ int responseLength = MAX_BUFFER_SIZE;
+ uchar completionCode;
+ uchar inputData[20];
+ char initmsg[80];
+ int status = 0;
+ uchar cmd;
+
+ /* May want to GetSystemBootOptions first to show existing. */
+
+ /* if (bootopt != 0) then set param 3 to not clear boot valid flag */
+ if (bootopt != 0)
+ {
+ inputData[0] = 0x03; // param, 3 = boot clear
+ if (fpersist)
+ inputData[1] = 0x1F; // persist all available conditions
+ else inputData[1] = 0x00; // clear after next boot
+ responseLength = MAX_BUFFER_SIZE;
+ status = ipmi_cmd_mc(SET_BOOT_OPTIONS, inputData, 2, responseData,
+ &responseLength, &completionCode, fdebug);
+ if (status == 0) status = completionCode;
+ if (status != 0) {
+ if (fdebug || !fignore_opterr)
+ printf("set_boot_options ccode %x, resp[0] = %x, resp[1] = %x\n",
+ completionCode, responseData[0], responseData[1]);
+ if (!fignore_opterr)
+ return(status); /* abort if the boot options can't be set */
+ }
+
+ inputData[0] = 0x05; // param, 5 = boot flags
+ if (fpersist)
+ inputData[1] = 0xC0; // valid flags, persistent
+ else inputData[1] = 0x80; // valid flags, next boot only
+ if (bootopt == 2) inputData[1] |= 0x20; // add boot to EFI
+ if (bootopt == 1) inputData[2] = 0x10; // boot to svc partition
+ else if (bootopt == 3) inputData[2] = 0x04; // boot to PXE
+ else if (bootopt == 4) inputData[2] = 0x14; // boot to CDROM
+ else if (bootopt == 5) inputData[2] = 0x08; // boot to Hard Disk
+ else if (bootopt == 6) inputData[2] = 0x18; // boot to BIOS Setup
+ else if (bootopt == 7) inputData[2] = 0x3C; // boot to Floppy/Remov
+ else if (bootopt == 8) inputData[2] = 0x0C; // boot to HardDisk/Safe
+ else inputData[2] = 0x00; // normal boot
+ inputData[3] = gbootparm;
+ inputData[4] = 0x00; //no overrides
+ inputData[5] = 0x00; //
+ responseLength = MAX_BUFFER_SIZE;
+ status = ipmi_cmd_mc(SET_BOOT_OPTIONS, inputData, 6, responseData,
+ &responseLength, &completionCode, fdebug);
+ if (status == 0) status = completionCode;
+ if (status != 0) {
+ if (fdebug || !fignore_opterr)
+ printf("set_boot_options ccode %x, resp[0] = %x, resp[1] = %x\n",
+ completionCode, responseData[0], responseData[1]);
+ if (!fignore_opterr)
+ return(status); /* abort if the boot options can't be set */
+ }
+ if (initstr != NULL) {
+ status = set_boot_init_string(initstr);
+ if (fdebug) printf("set_boot_init_string(%s) status = %d\n",
+ initstr,status);
+ if (status != 0) {
+ if (!fignore_opterr) return(status);
+ else status = 0;
+ }
+ }
+ }
+
+ /*
+ * fshutdown (bpower >= 5) for Intel:
+ * Since we are in user mode, we can't wait for it to fully
+ * shut down and then issue the IPMI Chassis Reset.
+ * IPMI can trigger this by emulating an overtemp event.
+ * There is also a watchdog/init0 method used by platIntel.
+ * bpower was set by caller to 5 or 6
+ */
+ if ((bpower >= 5) && (platform == platIntel))
+ { /*Intel os shutdown requested*/
+ if (fipmilan) {
+#ifdef EXPERIMENTAL
+ int rv;
+ /*Try remote shutdown via Bridged SMS */
+ inputData[0] = 5; /* chassis ctl soft shutdown option */
+ responseLength = MAX_BUFFER_SIZE;
+ rv = ipmi_cmdraw( CHASSIS_CTL,
+ NETFN_APP,BMC_SA,PUBLIC_BUS, SMS_LUN,
+ inputData,1,responseData,&responseLength,
+ &completionCode, fdebug);
+ printf("Remote soft shutdown initiated (%d,%d).\n",status,rv);
+#else
+ /* abort if call this with fipmi_lan, platIntel. */
+ /* should have invoked remote agent method before this. */
+ return(LAN_ERR_NOTSUPPORT);
+#endif
+ } else { /* do local shutdown with wdt*/
+ uchar action;
+ char initcmd[16];
+ char initchar, shutchar;
+
+ /*
+ * Special OS shutdown method for CG Servers
+ * Set up a watchdog event to do reset after timeout.
+ * Valid on other platforms too if they support watchdog.
+ * Note that the "init 0" only makes sense if local.
+ */
+ if (bpower == 6) { action = 0x02; /*do power_down*/
+ initchar = '0';
+ shutchar = 's';
+ } else { action = 0x01; /*do hard_reset*/
+ initchar = '6';
+ shutchar = 'r';
+ }
+ status = set_wdt((uchar)shuttime, action);
+ if (status == 0)
+ { /*local shutdown */
+ sprintf(initmsg,"%s: soft shutdown -%c initiated\n",progname,shutchar);
+ write_syslog(initmsg);
+#ifdef WIN32
+ sprintf(initcmd,"shutdown -%c -c %s",shutchar,progname);
+ status = system(initcmd); /* do the OS shutdown */
+ printf("Windows soft shutdown initiated (%s).\n",initcmd);
+#else
+ sprintf(initcmd,"init %c",initchar);
+ status = system(initcmd); /* do the OS shutdown */
+ printf("Linux soft shutdown initiated (%s).\n",initcmd);
+#endif
+ }
+ /*
+ * Note that this can generate a Watchdog 2 event in the SEL.
+ * If the init 0/6 is successful within the 60 second timeout,
+ * BIOS will stop the watchdog.
+ */
+ return(status);
+ } /*endif local*/
+ } /*endif Intel os shutdown*/
+
+ /* 0 = power down, 1 = power up, 2 = power cycle, 3 = hard reset */
+ /* 4 = NMI interrupt, 5 = soft shutdown OS via ACPI */
+ if (bpower > 5) bpower = 5; /* if invalid, try shutdown */
+ if (!fipmilan) { /*only write to syslog if local*/
+ sprintf(initmsg,"%s: chassis %s\n",progname,reset_str(bpower,bootopt));
+ write_syslog(initmsg);
+ }
+ inputData[0] = bpower; // chassis control reset
+ responseLength = MAX_BUFFER_SIZE;
+ status = ipmi_cmd_mc(CHASSIS_CTL, inputData, 1, responseData,
+ &responseLength, &completionCode, fdebug);
+ if (fdebug) {
+ printf("Chassis_Ctl(%x) ccode=%x, resp[0]=%x, resp[1]=%x\n",
+ bpower, completionCode,
+ responseData[0], responseData[1]);
+ }
+ if (status == ACCESS_OK && completionCode == 0) {
+ printf("chassis_reset ok\n");
+ //successful, done
+ return(0);
+ } else if (fipmilan && (status < 0)) {
+ /* Remote IPMI LAN reset could not connect,
+ * no point in continuing. */
+ return(status);
+ } else {
+ if (bpower == 5 && completionCode == 0xcc) {
+ /* See IPMI spec 22.3 Chassis Control, Table 22-4 */
+ printf("Optional soft-shutdown mode not supported\n");
+ /* If get here, need to use method like platIntel above. */
+ } else {
+ show_error("chassis_reset",status,completionCode);
+ // status = -1;
+
+ /* Try net_app warm/cold reset commands instead */
+ if (bpower == 2) cmd = 2; /* cold reset */
+ else cmd = 3; /* warm reset */
+ responseLength = MAX_BUFFER_SIZE;
+ status = ipmi_cmdraw( cmd,NETFN_APP, g_sa, g_bus, g_lun,
+ inputData,0,responseData,&responseLength,
+ &completionCode, fdebug);
+ if (status == ACCESS_OK && completionCode == 0) {
+ printf("netapp_reset ok\n");
+ } else {
+ show_error("netapp_reset",status,completionCode);
+ if (status == 0) status = completionCode;
+ }
+ }
+ } /*end else*/
+ return(status);
+} /*end IPMI_Reset()*/
+
+static void wait_ready(void)
+{
+ int i, c;
+ uchar devrec[16];
+ /* wait for BMC ready again */
+ os_usleep(1,0); /*delay 1 sec*/
+ for (i = 0; i < 15; i++) {
+ os_usleep(1,0); /*delay 1 sec*/
+ c = ipmi_getdeviceid(devrec,16,fdebug);
+ if (c == 0) break;
+ else { /* expect LAN_ERR_RECV_FAIL if BMC not ready */
+ if (fdebug) printf("after reset, try%d ret = %d\n",i,c);
+ if (c != LAN_ERR_RECV_FAIL) break;
+ }
+ } /*end-for*/
+}
+
+static void show_usage(void)
+{
+ printf("Usage: %s [-bcdDefhkmnoprsuwxy -N node -U user -P/-R pswd -EFTVY]\n",
+ progname);
+ printf(" where -c power Cycles the system\n");
+ printf(" -d powers Down the system\n");
+ printf(" -D soft-shutdown OS and power down\n");
+ printf(" -k do Cold Reset of the BMC firmware\n");
+ printf(" -i<str> set boot Initiator mailbox string\n");
+ printf(" -j<num> set IANA number for boot Initiator\n");
+ printf(" -n sends NMI to the system\n");
+ printf(" -o soft-shutdown OS and reset\n");
+ printf(" -r hard Resets the system\n");
+ printf(" -u powers Up the system\n");
+ printf(" -m002000 specific MC (bus 00,sa 20,lun 00)\n");
+ printf(" -b reboots to BIOS Setup\n");
+ printf(" -e reboots to EFI\n");
+ printf(" -f reboots to Floppy/Removable\n");
+ printf(" -h reboots to Hard Disk\n");
+ printf(" -p reboots to PXE via network\n");
+ printf(" -s reboots to Service Partition\n");
+ printf(" -v reboots to DVD/CDROM Media\n");
+ printf(" -w Wait for BMC ready after reset\n");
+ printf(" -x show eXtra debug messages\n");
+ printf(" -y Yes, persist boot options [-befhpms]\n");
+ print_lan_opt_usage();
+}
+
+#ifdef METACOMMAND
+int i_reset(int argc, char **argv)
+#else
+#ifdef WIN32
+int __cdecl
+#else
+int
+#endif
+main(int argc, char **argv)
+#endif
+{
+ int ret;
+ int c;
+ uchar breset;
+ uchar bopt;
+ uchar fshutdown = 0;
+ uchar devrec[16];
+ int rlen;
+ uchar rqdata[10];
+ uchar rsdata[32];
+ int rslen;
+ int mfg = 0;
+ uchar cc;
+ char *s1;
+
+#if defined (EFI)
+ InitializeLib(_LIBC_EFIImageHandle, _LIBC_EFISystemTable);
+#endif
+ // progname = argv[0];
+ printf("%s ver %s\n", progname,progver);
+ breset = INIT_VAL; /* invalid as default, require an option */
+ bopt = 0; /* Boot Options default */
+ /* Request admin privilege by default, since power control requires it. */
+ parse_lan_options('V',"4",0);
+
+ while ((c = getopt(argc,argv,"bcdDefhi:j:km:noprsuvwyT:V:J:YEF:N:P:R:U:Z:x?")) != EOF)
+ switch(c) {
+ case 'd': breset = 0; break; /* power down */
+ case 'u': breset = 1; break; /* power up */
+ case 'c': breset = 2; break; /* power cycle */
+ case 'o': breset = 5; fshutdown = 1; break; /*soft shutdown,reset*/
+ case 'D': breset = 6; fshutdown = 1; break; /*soft shutdown,pwrdown*/
+ case 'n': breset = 4; break; /* interrupt (NMI) */
+ case 'r': breset = 3; break; /* hard reset */
+ case 's': breset = 3; bopt = 1; break; /* hard reset to svc part */
+ case 'e': breset = 3; bopt = 2; break; /* hard reset to EFI */
+ case 'p': breset = 3; bopt = 3; break; /* hard reset to PXE */
+ case 'v': breset = 3; bopt = 4; break; /* hard reset to DVD/CD Media*/
+ case 'h': breset = 3; bopt = 5; break; /* hard reset to Hard Disk */
+ case 'b': breset = 3; bopt = 6; break; /* hard reset to BIOS Setup */
+ case 'f': breset = 3; bopt = 7; break; /* hard reset to floppy/remov*/
+ case 'i': if (strlen(optarg) < MAX_INIT) initstr = optarg; break;
+ case 'j': mfg = atoi(optarg); /*IANA number*/
+ iana[0] = ((mfg & 0xFF0000) >> 16);
+ iana[1] = ((mfg & 0x00FF00) >> 8);
+ iana[2] = (mfg & 0x0000FF);
+ break;
+ case 'k': breset = 7; break; /* cold reset */
+ case 'w': fwait = 1; break; /* wait for ready */
+ case 'y': fpersist = 1; break; /* yes, persist boot options */
+ 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"; }
+ ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype);
+ printf("set MC at %s bus=%x sa=%x lun=%x\n",
+ s1,g_bus,g_sa,g_lun);
+ 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;
+ case 'x': fdebug = 1; break; /* debug messages */
+ default:
+ show_usage();
+ ret = ERR_USAGE;
+ goto do_exit;
+ }
+
+ if (breset == INIT_VAL) {
+ show_usage();
+ printf("An option is required\n");
+ ret = ERR_BAD_PARAM;
+ goto do_exit;
+ }
+
+ fipmilan = is_remote();
+ /*
+ * Check the Device ID to determine the platform type.
+ */
+ ret = ipmi_getdeviceid(devrec,16,fdebug);
+ if (ret != 0) {
+ ipmi_close_();
+ goto do_exit;
+ } else {
+ char *pstr;
+ int vendid;
+ ushort prodid;
+ uchar 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;
+ vendid = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16);
+ if (mfg == 0) memcpy(iana,&devrec[6],3); /*not set, use default*/
+ prodid = devrec[9] + (devrec[10] << 8);
+ pstr = "BMC";
+ if (fdebug) printf("vendor = %06x, product_id = %04x\n",vendid,prodid);
+ if (vendid == VENDOR_NSC) { /* NSC mBMC */
+ pstr = "mBMC";
+ platform = platMBMC;
+ } else if (vendid == VENDOR_HP) { /* HP */
+ platform = platOther; /* other platform types */
+ gbootparm = 0x00;
+ fignore_opterr = 1; /* ignore boot options errors */
+ } else if (vendid == VENDOR_TYAN) { /* Tyan */
+ platform = platOther; /* other platform types */
+ fignore_opterr = 1; /* ignore boot options errors */
+ } else if (vendid == VENDOR_INTEL) { /* Intel */
+ if (prodid != 0x0100) /* ia64 Itanium2 is different */
+ platform = platIntel; /* else handle as Intel Sahalee */
+ if (is_romley(vendid,prodid) || (prodid == 0x003E)) {
+ /* Romley or Thurley/S5520UR */
+ platform = platS5500; /* not like Intel Sahalee */
+ set_max_kcs_loops(URNLOOPS); /*longer KCS timeout*/
+ }
+ } else if (vendid == VENDOR_KONTRON) { /* Kontron */
+ fignore_opterr = 1; /* ignore boot options errors */
+ /* supports Chassis Soft Power command 0x05, so not platIntel */
+ platform = platOther; /* handle like other platforms */
+ } else { /* other vendors */
+ platform = platOther; /* other platform types */
+ }
+ printf("-- %s version %x.%x, IPMI version %d.%d \n",
+ pstr, devrec[2], devrec[3], ipmi_maj, ipmi_min);
+ }
+
+ { /* show current power state */
+ char *pstr;
+ uchar pstate;
+ rlen = sizeof(devrec);
+ ret = ipmi_cmdraw( GET_POWER_STATE, NETFN_APP,
+ g_sa, g_bus, g_lun,
+ NULL,0, devrec,&rlen,&cc, fdebug);
+ if (ret == 0) {
+ pstate = devrec[0] & 0x7f;
+ 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;
+ default: pstr = "unknown"; break;
+ }
+ if (cc == 0)
+ printf("Power State = %02x (%s)\n",pstate,pstr);
+ }
+ }
+
+ if (breset == 7) { /*do Cold Reset */
+ printf("%s: %s ...\n",progname,reset_str(breset,bopt));
+ rslen = sizeof(rsdata);
+ ret = ipmi_cmdraw( 0x02, NETFN_APP, g_sa, g_bus, g_lun,
+ rqdata,0, rsdata, &rslen, &cc, fdebug);
+ if (fdebug)
+ printf("cold_reset(%02x) ret=%d cc=%x, rslen=%d\n",g_sa,ret,cc,rslen);
+ if (ret == 0) ret = cc;
+ if (ret == 0)
+ printf("%s: Cold_Reset ok\n",progname);
+ else
+ printf("%s: Cold_Reset error %d\n",progname,ret);
+ ipmi_close_();
+
+ } else if (fshutdown && fipmilan && (platform == platIntel)) { /*soft reset*/
+ int fdaemonok = 0;
+ /* Either do special remote soft-shutdown, or
+ * handle it within IPMI_Reset. */
+ /* Special remote soft-shutdown, requires a service to
+ * be running on the target node.
+ * GET_SOFTWARE_ID == 0x00
+ * SMS_OS_REQUEST == 0x10 : (down=0, reset=1)
+ * BRIDGE_REQUEST == 0x20 : (down=0, reset=1)
+ * SMS_SA == 0x81
+ */
+ rslen = sizeof(rsdata);
+ ret = ipmi_cmdraw( 0x00, NETFN_APP,sms_sa,PUBLIC_BUS, SMS_LUN,
+ rqdata,0, rsdata, &rslen, &cc, fdebug);
+ if (fdebug)
+ printf("ipmilan getswid ret=%d cc=%x, rslen=%d\n",ret,cc,rslen);
+ if (ret == 0 && cc == 0) {
+ ushort v,x;
+ v = (rsdata[6] << 16) + (rsdata[7] << 8) + rsdata[8];
+ x = (rsdata[9] << 8) + rsdata[10];
+ if (fdebug) printf("swid v: %06x x: %04x\n",v,x);
+ if (v == 0x000157 && x == 0x0001) fdaemonok = 1;
+ }
+ if (fdaemonok) {
+ /* os_usleep(0,50000); *delay 50 ms, not needed*/
+ if (breset == 0 || breset == 6)
+ rqdata[0] = 0x01; /* shutdown & power down */
+ else rqdata[0] = 0x02; /* shutdown & reset */
+ if (fdebug) printf("ipmilan shutdown action=%x\n",rqdata[0]);
+ rslen = sizeof(rsdata);
+ ret = ipmi_cmdraw( SMS_OS_REQUEST, NETFN_APP,sms_sa,PUBLIC_BUS,SMS_LUN,
+ rqdata,1, rsdata, &rslen, &cc, fdebug);
+ printf("ipmilan shutdown request: ret = %d, cc = %x\n", ret,cc);
+ if (fipmilan && fwait) {
+ ipmi_close_(); /* to try new connection */
+ wait_ready();
+ }
+ }
+ else printf("ipmilan async bridge agent not present\n");
+ ipmi_close_();
+ } else {
+ printf("%s: %s ...\n",progname,reset_str(breset,bopt));
+ ret = IPMI_Reset(breset,bopt);
+ if (ret == 0) { /* if ok */
+ printf("%s: IPMI_Reset ok\n",progname);
+ /* It starts resetting by this point, so do not close. */
+ if (breset == 4) ipmi_close_(); /*NMI, so close*/
+ if (fipmilan && fwait) {
+ ipmi_close_(); /* to try new connection */
+ wait_ready();
+ ipmi_close_();
+ }
+ } else {
+ printf("%s: IPMI_Reset error %d\n",progname,ret);
+ ipmi_close_();
+ }
+ }
+do_exit:
+ // show_outcome(progname,ret);
+ return(ret);
+} /* end main()*/
+
+/* end ireset.c */