summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2014-07-06 18:04:32 +0200
committerJörg Frings-Fürst <debian@jff-webhosting.net>2014-07-06 18:04:32 +0200
commita7f89980e5b3f4b9a74c70dbc5ffe8aabd28be28 (patch)
tree41c4deec1fdfbafd7821b4ca7a9772ac0abd92f5
Imported Upstream version 2.9.3upstream/2.9.3
-rw-r--r--AUTHORS10
-rw-r--r--COPYING31
-rw-r--r--ChangeLog3981
-rwxr-xr-xINSTALL224
-rw-r--r--Makefile.am60
-rw-r--r--Makefile.in687
-rw-r--r--NEWS74
-rw-r--r--README156
-rw-r--r--TODO293
-rw-r--r--aclocal.m47261
-rwxr-xr-xbeforeconf.sh55
-rw-r--r--buildsamp.cmd13
-rw-r--r--buildwin.cmd45
-rw-r--r--buildwin2.cmd31
-rw-r--r--cleanwin.cmd23
-rwxr-xr-xconfig.guess1411
-rw-r--r--config.h.in118
-rwxr-xr-xconfig.sub1500
-rwxr-xr-xconfigure22199
-rw-r--r--configure.ac441
-rw-r--r--debian/changelog272
-rw-r--r--debian/compat1
-rw-r--r--debian/control27
-rw-r--r--debian/copyright129
-rw-r--r--debian/dirs2
-rw-r--r--debian/docs2
-rw-r--r--debian/files1
l---------debian/ipmiutil.cron.daily1
-rw-r--r--debian/ipmiutil.lintian-overrides4
-rw-r--r--debian/ipmiutil.substvars2
-rwxr-xr-xdebian/postinst41
-rwxr-xr-xdebian/prerm26
-rwxr-xr-xdebian/rules23
-rw-r--r--debian/source/format1
-rw-r--r--debian/watch2
-rwxr-xr-xdepcomp530
-rw-r--r--doc/Makefile383
-rw-r--r--doc/Makefile.am61
-rw-r--r--doc/Makefile.in383
-rw-r--r--doc/UserGuide6497
-rw-r--r--doc/bmclanaol.mib210
-rw-r--r--doc/bmclanpet.mib1083
-rw-r--r--doc/ialarms.8103
-rw-r--r--doc/icmd.8113
-rw-r--r--doc/iconfig.896
-rw-r--r--doc/idcmi.8122
-rw-r--r--doc/idelloem.8177
-rw-r--r--doc/idiscover.892
-rw-r--r--doc/iekanalyzer.8251
-rw-r--r--doc/ievents.893
-rw-r--r--doc/ifirewall.8152
-rw-r--r--doc/ifru.8111
-rw-r--r--doc/ifruset.8122
-rw-r--r--doc/ifwum.8124
-rw-r--r--doc/igetevent.8154
-rw-r--r--doc/ihealth.893
-rw-r--r--doc/ihpm.8185
-rw-r--r--doc/ilan.8305
-rw-r--r--doc/ipicmg.8157
-rw-r--r--doc/ipmi_port.844
-rw-r--r--doc/ipmiutil.8116
-rw-r--r--doc/ipmiutil.spec424
-rw-r--r--doc/ireset.8118
-rw-r--r--doc/isel.8137
-rw-r--r--doc/iseltime.879
-rw-r--r--doc/isensor.8213
-rw-r--r--doc/iserial.8251
-rw-r--r--doc/ismcoem.8104
-rw-r--r--doc/isol.8133
-rw-r--r--doc/isunoem.8135
-rw-r--r--doc/itsol.866
-rw-r--r--doc/iwdt.8113
-rw-r--r--doc/rh.patch111
-rw-r--r--doc/rh_spec.patch111
-rw-r--r--doc/winsockerr.txt301
-rw-r--r--hpiutil/COPYING28
-rw-r--r--hpiutil/ChangeLog106
-rw-r--r--hpiutil/INSTALL27
-rw-r--r--hpiutil/Makefile77
-rw-r--r--hpiutil/README249
-rw-r--r--hpiutil/SaHpi.h4509
-rw-r--r--hpiutil/SaHpi.h-A4509
-rw-r--r--hpiutil/SaHpi.h-B6785
-rw-r--r--hpiutil/TODO65
-rwxr-xr-xhpiutil/env.hpi11
-rwxr-xr-xhpiutil/env.openhpi2
-rw-r--r--hpiutil/hpialarmpanel.c373
-rw-r--r--hpiutil/hpievent.c621
-rw-r--r--hpiutil/hpifru.c19
-rw-r--r--hpiutil/hpifrua.c550
-rw-r--r--hpiutil/hpifrub.c619
-rwxr-xr-xhpiutil/hpiinit.sh69
-rw-r--r--hpiutil/hpireset.c225
-rw-r--r--hpiutil/hpisel.c934
-rw-r--r--hpiutil/hpisensor.c467
-rw-r--r--hpiutil/hpiutil.spec199
-rw-r--r--hpiutil/hpiwdt.c272
-rwxr-xr-xhpiutil/mkrpm135
-rwxr-xr-xhpiutil/upd24
-rwxr-xr-xinstall-sh323
-rw-r--r--kern/alarms.h43
-rw-r--r--kern/bmcpanic-2.4.18.patch997
-rw-r--r--kern/bmcpanic-2.4.19.patch997
-rw-r--r--kern/bmcpanic-2.4.20.patch1000
-rw-r--r--kern/bmcpanic-2.5.44.patch795
-rw-r--r--kern/bmcpanic-2.5.62.patch830
-rw-r--r--kern/bmcpanic-2.6.0.patch162
-rw-r--r--kern/ipmi_kcs.patch1592
-rw-r--r--kern/linux-ipmi-2.4.20-v17.diff6647
-rw-r--r--kern/linux-ipmi-2.5.44-v12.diff7362
-rw-r--r--kern/linux-ipmi-emu-2.4.20-v17.diff2776
-rw-r--r--kern/openipmi-emu-rh80.patch1904
-rw-r--r--kern/openipmi-rh80.patch6633
-rw-r--r--lib/Makefile73
-rw-r--r--lib/ipmilib.mak37
-rw-r--r--lib/lanplus/Makefile.am55
-rw-r--r--lib/lanplus/Makefile.in532
-rw-r--r--lib/lanplus/README19
-rw-r--r--lib/lanplus/asf.h82
-rw-r--r--lib/lanplus/helper.c480
-rw-r--r--lib/lanplus/inc/config.h144
-rw-r--r--lib/lanplus/inc/inttypes-win.h30
-rw-r--r--lib/lanplus/inc/ipmitool/bswap.h53
-rw-r--r--lib/lanplus/inc/ipmitool/helper.h102
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi.h267
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_cc.h76
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_channel.h229
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_chassis.h55
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_constants.h136
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_entity.h47
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_event.h60
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_firewall.h106
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_fru.h381
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_fwum.h46
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_hpmfwupg.h45
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_intf.h224
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_isol.h56
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_kontronoem.h49
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_lanp.h132
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_main.h42
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_mc.h103
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_oem.h47
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_pef.h784
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_picmg.h90
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_raw.h44
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_sdr.h876
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_sel.h542
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_sensor.h84
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_session.h125
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_sol.h84
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_strings.h60
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_sunoem.h57
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_tsol.h46
-rw-r--r--lib/lanplus/inc/ipmitool/ipmi_user.h89
-rw-r--r--lib/lanplus/inc/ipmitool/log.h74
-rw-r--r--lib/lanplus/ipmi_strings.c348
-rw-r--r--lib/lanplus/ipmiplus.mak67
-rw-r--r--lib/lanplus/lanplus.c4036
-rw-r--r--lib/lanplus/lanplus.h135
-rw-r--r--lib/lanplus/lanplus_crypt.c1038
-rw-r--r--lib/lanplus/lanplus_crypt.h79
-rw-r--r--lib/lanplus/lanplus_crypt_impl.c320
-rw-r--r--lib/lanplus/lanplus_crypt_impl.h66
-rw-r--r--lib/lanplus/lanplus_defs.h376
-rw-r--r--lib/lanplus/lanplus_dump.c174
-rw-r--r--lib/lanplus/lanplus_dump.h45
-rw-r--r--lib/lanplus/lanplus_strings.c45
-rw-r--r--lib/lanplus/libipmi_lanplus.la35
-rw-r--r--lib/lanplus/rmcp.h88
-rw-r--r--lib/libimbapi64.a.redhatbin0 -> 47244 bytes
-rw-r--r--lib/libimbapi64.a.susebin0 -> 11644 bytes
-rwxr-xr-xltconfig3114
-rw-r--r--ltmain.sh6911
-rwxr-xr-xmissing360
-rwxr-xr-xmkinstalldirs158
-rw-r--r--scripts/Makefile381
-rw-r--r--scripts/Makefile.am60
-rw-r--r--scripts/Makefile.in381
-rwxr-xr-xscripts/checksel30
-rw-r--r--scripts/checksel.cmd15
-rwxr-xr-xscripts/evt.sh45
-rwxr-xr-xscripts/ialarms2
-rw-r--r--scripts/ialarms.cmd1
-rwxr-xr-xscripts/icmd2
-rw-r--r--scripts/icmd.cmd1
-rwxr-xr-xscripts/iconfig2
-rw-r--r--scripts/iconfig.cmd1
-rw-r--r--scripts/idiscover.cmd1
-rwxr-xr-xscripts/ifirewall2
-rwxr-xr-xscripts/ifru2
-rw-r--r--scripts/ifru.cmd1
-rwxr-xr-xscripts/ifwum2
-rwxr-xr-xscripts/igetevent2
-rw-r--r--scripts/igetevent.cmd1
-rwxr-xr-xscripts/ihealth2
-rw-r--r--scripts/ihealth.cmd1
-rwxr-xr-xscripts/ihpm2
-rwxr-xr-xscripts/ilan2
-rw-r--r--scripts/ilan.cmd1
-rwxr-xr-xscripts/init.sh36
-rwxr-xr-xscripts/install-solaris.sh20
-rw-r--r--scripts/install.cmd26
-rw-r--r--scripts/install.vbs47
-rwxr-xr-xscripts/ipdiff.sh31
-rwxr-xr-xscripts/ipicmg2
-rwxr-xr-xscripts/ipmi.init.basic80
-rwxr-xr-xscripts/ipmi_if.sh66
-rwxr-xr-xscripts/ipmi_info124
-rw-r--r--scripts/ipmi_port.service15
-rwxr-xr-xscripts/ipmi_port.sh187
-rw-r--r--scripts/ipmiutil.env22
-rwxr-xr-xscripts/ipmiutil.pre12
-rwxr-xr-xscripts/ipmiutil.setup47
-rwxr-xr-xscripts/ipmiutil_asy155
-rw-r--r--scripts/ipmiutil_asy.service14
-rwxr-xr-xscripts/ipmiutil_evt158
-rw-r--r--scripts/ipmiutil_evt.service15
-rwxr-xr-xscripts/ipmiutil_wdt146
-rwxr-xr-xscripts/ipmiutil_wdt.cmd10
-rw-r--r--scripts/ipmiutil_wdt.service14
-rwxr-xr-xscripts/ireset2
-rw-r--r--scripts/ireset.cmd1
-rwxr-xr-xscripts/isel2
-rw-r--r--scripts/isel.cmd1
-rwxr-xr-xscripts/isensor2
-rw-r--r--scripts/isensor.cmd1
-rwxr-xr-xscripts/iserial2
-rw-r--r--scripts/iserial.cmd1
-rwxr-xr-xscripts/isol2
-rw-r--r--scripts/isol.cmd1
-rwxr-xr-xscripts/iwdt2
-rw-r--r--scripts/iwdt.cmd1
-rwxr-xr-xscripts/setlib.sh38
-rw-r--r--scripts/showsel.mc29
-rw-r--r--scripts/showsel.reg10
-rw-r--r--scripts/showselun.reg4
-rwxr-xr-xscripts/startsol16
-rw-r--r--scripts/uninstall.cmd31
-rw-r--r--scripts/uninstall.vbs63
-rwxr-xr-xsetver271
-rw-r--r--stamp-h1
-rw-r--r--stamp-h.in1
-rw-r--r--test/Kconfig12
-rw-r--r--test/Makefile325
-rw-r--r--test/Makefile-2463
-rw-r--r--test/Makefile-269
-rw-r--r--test/dopanic.833
-rw-r--r--test/dopanic_drv.c51
-rwxr-xr-xtest/ipmievt.sh45
-rwxr-xr-xtest/make26017
-rwxr-xr-xtest/panicsel-c.sh19
-rwxr-xr-xtest/panicsel-k.sh13
-rw-r--r--test/panicsel_apptool_test.sh550
-rw-r--r--test/panicsel_test_needreboot.sh162
-rwxr-xr-xtest/retro.sh37
-rw-r--r--test/sensor-CG2100.txt148
-rw-r--r--test/sensor-TIGW1U.txt106
-rwxr-xr-xtest/testipmi.sh400
-rw-r--r--test/unittest.cmd125
-rwxr-xr-xtest/unittest.sh254
-rw-r--r--util/AnsiTerm.cpp1892
-rw-r--r--util/AnsiTerm.h316
-rw-r--r--util/Makefile.am200
-rw-r--r--util/Makefile.am-so241
-rw-r--r--util/Makefile.in766
-rw-r--r--util/Makefile.sample28
-rw-r--r--util/ialarms.c689
-rw-r--r--util/icmd.c366
-rw-r--r--util/iconfig.c2680
-rw-r--r--util/idcmi.c976
-rw-r--r--util/idcmi.h69
-rw-r--r--util/idiscover.c1055
-rw-r--r--util/iekanalyzer.c4131
-rw-r--r--util/iekanalyzer.h521
-rw-r--r--util/ievents.c2505
-rw-r--r--util/ievents.h64
-rw-r--r--util/ifirewall.c1154
-rw-r--r--util/ifirewall.h111
-rwxr-xr-xutil/ifru.c2123
-rw-r--r--util/ifru.h13
-rw-r--r--util/ifru_picmg.c486
-rw-r--r--util/ifruset.c1658
-rw-r--r--util/ifwum.c1697
-rw-r--r--util/ifwum.h76
-rw-r--r--util/igetevent.c1439
-rw-r--r--util/ihealth.c1153
-rw-r--r--util/ihpm.c4003
-rw-r--r--util/ihpm.h117
-rw-r--r--util/ilan.c5149
-rw-r--r--util/imb_api.h708
-rw-r--r--util/imbapi.c2594
-rw-r--r--util/ipicmg.c1911
-rw-r--r--util/ipicmg.h313
-rw-r--r--util/ipmi_port.c146
-rw-r--r--util/ipmi_sample.c312
-rw-r--r--util/ipmi_sample.mak57
-rw-r--r--util/ipmi_sample_evt.c445
-rw-r--r--util/ipmibmc.c231
-rw-r--r--util/ipmicmd.c1429
-rw-r--r--util/ipmicmd.h543
-rw-r--r--util/ipmidir.c1513
-rw-r--r--util/ipmidir.h301
-rw-r--r--util/ipmilan.c2430
-rw-r--r--util/ipmilan.h83
-rw-r--r--util/ipmilan2.c68
-rw-r--r--util/ipmilan2.h62
-rw-r--r--util/ipmilanplus.c790
-rw-r--r--util/ipmilanplus.h64
-rw-r--r--util/ipmild.c250
-rw-r--r--util/ipmilipmi.c182
-rw-r--r--util/ipmims.cpp638
-rw-r--r--util/ipmimv.c784
-rw-r--r--util/ipmiutil.c229
-rw-r--r--util/ipmiutil.h66
-rw-r--r--util/ipmiutil.mak424
-rw-r--r--util/ipmiutil2-64.mak425
-rw-r--r--util/ipmiutil2.mak425
-rw-r--r--util/ipmiutil64.mak423
-rw-r--r--util/ipmiutillib.def31
-rw-r--r--util/ireset.c751
-rw-r--r--util/isel.c884
-rw-r--r--util/iseltime.c260
-rw-r--r--util/isensor.c3680
-rw-r--r--util/isensor.h176
-rw-r--r--util/iserial.c1592
-rw-r--r--util/isol.c1347
-rw-r--r--util/isolwin.c293
-rw-r--r--util/itsol.c725
-rw-r--r--util/itsol.h66
-rw-r--r--util/iwdt.c415
-rw-r--r--util/md2.c99
-rw-r--r--util/md2.h269
-rw-r--r--util/md5.c413
-rw-r--r--util/mem_if.c900
-rw-r--r--util/mem_if_cpp.cpp5
-rw-r--r--util/oem_dell.c6095
-rw-r--r--util/oem_dell.h629
-rw-r--r--util/oem_fujitsu.c773
-rw-r--r--util/oem_fujitsu.h130
-rw-r--r--util/oem_hp.c149
-rw-r--r--util/oem_intel.c1842
-rw-r--r--util/oem_intel.h79
-rw-r--r--util/oem_kontron.c1107
-rw-r--r--util/oem_kontron.h80
-rw-r--r--util/oem_newisys.c129
-rw-r--r--util/oem_quanta.c142
-rw-r--r--util/oem_sun.c1058
-rw-r--r--util/oem_sun.h137
-rw-r--r--util/oem_supermicro.c595
-rw-r--r--util/oem_supermicro.h56
-rw-r--r--util/subs.c848
351 files changed, 214491 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..2d377e6
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,10 @@
+ipmiutil:
+ Andy Cress <arcress at users.sourceforge.net>
+util/AnsiTerm.cpp
+ Robert Nelson <robertnelson at users.sourceforge.net>
+util/oem_dell.c
+ Harsha S <Harsha_S1 at dell.com>
+util/ihpm.c
+ Frederic.Lelievre@ca.kontron.com, Francois.Isabelle@ca.kontron.com,
+ Jean-Michel.Audet@ca.kontron.com, MarieJosee.Blais@ca.kontron.com
+
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..13a56a9
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,31 @@
+
+ The BSD 2.0 License
+
+ Copyright (c) 2001-2008 Intel Corporation
+ (c) 2009-2012 Kontron America, Inc.
+ (c) 2013 Andy Cress <arcress at users.sourceforge.net>
+ 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.
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..ebf3c29
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,3981 @@
+-----------------------------
+ ipmiutil project ChangeLog
+ (formerly panicsel project)
+ CHANGE HISTORY:
+ (oldest to newest)
+-----------------------------
+ 10/24/01 ARCress ver 0.8.1
+ panicsel kernel patches submitted (ksyms.c, panic.c)
+ 11/02/01 ARCress ver 0.8.2
+ mkrpm - changed mkrpm to isolate $HOME
+ panicsel.spec - changed to edit lilo.conf for panic timeout
+ 11/07/01 ARCress ver 0.8.3
+ added showsel.8 & selpef.8 man pages
+ 11/15/01 ARCress ver 0.8.4
+ fixed panicsel.spec for 'file exists' errors (bug 32)
+ 11/16/01 ARCress ver 0.8.5
+ fixed panicsel.spec to require isc package (bug 32)
+ fixed panicsel.spec for extra debug output (bug 38)
+ 11/19/01 ARCress ver 0.9.0-1
+ Updated panicsel kernel module to use special open source ipmi driver.
+ Enhanced panicsel utilities also (showsel & selpef).
+ Utilities still do require the /dev/imb driver from ISC, however.
+ 11/28/01 ARCress ver 0.9.0-2
+ Modified LICENSE file to include official ISC license text.
+ 12/06/01 ARCress ver 0.9.0-3
+ Updated README & panicsel.spec for better documentation
+ 12/14/01 ARCress ver 1.0.0
+ Updated man pages for cosmetic issues
+ 01/16/02 ARCress ver 1.1.0
+ Added hwreset, moved to kernel 2.4.16
+ 02/06/02 ARCress ver 1.1.1
+ Changed selpef to pefconfig, some functions added.
+ 03/05/02 ARCress ver 1.1.2
+ Updated pefconfig to set all LAN Params,
+ added tmconfig (but not currently included in rpm),
+ updated hwreset with -s option.
+ updated all utils to use either Intel or valinux IPMI.
+ 04/16/02 ACress ver 1.1.3
+ showsel: decode time field in SEL records
+ showsel: add display of avail space in SEL and ability to clear SEL
+ pefconfig: add SetUser capability if that option is specified
+ tmconfig: add shared BasicMode/BiosConsole option (-s), which is
+ supported in TSRLT2 P10 BIOS build 44 and greater.
+ 05/09/02 ACress ver 1.1.4
+ pefconfig: fixed ccode=c7 on param 16/18
+ pefconfig: fixed bug 504 with gwy mac = 0
+ bmc_panic (kernel): added BMCPANIC_ACTION to power down/power cycle.
+ panicsel rpm: changed pathnames to conform to OSD feedback
+ tmconfig: updates based on customer feedback
+ 05/28/02 ACress ver 1.1.5
+ all: fixed imbapi.c/DeviceIoControl problem with buffer >41 bytes
+ all: changed LICENSE to BSD
+ 05/31/02 ACress ver 1.2.0
+ pefconfig: get community name from snmpd.conf
+ pefconfig: set dest type for no ack, no retry
+ pefconfig: special handling to set preset PEF entries
+ 07/03/02 ACress ver 1.2.1
+ all: added more usage text
+ tmconfig: added -d option to disable serial configuration
+ 08/02/02 ACress ver 1.2.2
+ consolidated inc/* header files into imb_api.h with BSD license
+ fixed tmconfig -c password memcpy
+ moved common ipmi_cmd() code to ipmicmd.c
+ 08/27/02 ACress ver 1.2.3
+ pefconfig: fixed 0xc7 error on SETUSER_ACCESS when using -P
+ pefconfig: show a message if no alert destination specified
+ sensor.c: added pre-alpha version of this utility
+ 09/12/02 ARCress ver 1.2.4
+ UserGuide, man pages: updated URLs for sourceforge
+ added TODO file
+ 10/09/02 ARCress ver 1.2.5
+ pefconfig: decode Dest address IP in decimal
+ showsel: added -v (version) option
+ sensor: added decodeValue routine
+ bmc_panic: fixed compile warnings in bmc_ipmi.c & bmc_selmsg.c
+ 10/30/02 ARCress ver 1.2.6
+ sensor: added expon routine
+ sensor: added SDR types 08 & 14
+ added fruconfig utility
+ ipmicmd: added ipmi_cmd_raw subroutine, changed CMDMASK
+ updated UserGuide
+ added kern/alarms.h to document alarms panel LEDs
+ added kern/bmcpanic19.patch for lk 2.4.19
+ 12/10/02 ARCress ver 1.2.7
+ tmconfig: fixed -c for Langley-Pr TMode
+ tmconfig: several changes to parameters
+ pefconfig: fixed -C handling
+ 02/04/03 ARCress ver 1.2.8
+ fruconfig: fixed write_fru, v1.0 release
+ added man pages fruconfig.8 & sensor.8, updated UserGuide
+ bmclan.mib: added MIB for BMC LAN SNMP traps (but no OS Crit def yet)
+ ipmicmd.c/ipmimv.c: added support for MontaVista OpenIPMI driver
+ kern: added bmcpanic-2.5.44.patch and linux-ipmi-2.5.44-v12.diff
+ 02/26/03 ARCress ver 1.2.9
+ showsel: more descriptive messages if empty, or nearly full.
+ trimmed output to fit more on one line,
+ decode panic type bits for OS Critical Stop
+ bmclan.mib: added OS Critical Stop definition
+ pefconfig: show/set PEF Control value, etc.
+ fruconfig: added GetSystemGUID also
+ sensor: schulz change for float & HP netserver 1000r
+ guomin change for simpler output with -l
+ alarms: alarms handling utility added
+ wdt: watchdog timer utility added
+ test/watchdogtest: added /dev/watchdog test tool
+ test/panicsel-k.sh: pattern is "bmc_panic" now.
+ kern/bmcpanic-2.4.18.patch: reworked for ipmi_send_recv,
+ added some type bits
+ kern/bmcpanic-2.4.19.patch: reworked as above
+ kern/bmcpanic-2.4.20.patch: new
+ 03/26/03 ARCress ver 1.3.0
+ fruconfig: more bounds checking
+ showsel: added savid for more efficient read loop if -w
+ imb_api.h: morphed comments for some crazy compilers
+ imbapi.c: morphed comments for some crazy compilers
+ kern/bmcpanic-2.5.62.patch: new, from guomin
+ Makefiles & .spec file: changed to use autoconf/automake
+ 04/08/03 ARCress ver 1.3.1
+ pefconfig 1.15: added -i option for eth interface
+ imbapi.c: fix compile warnings, fix license text error
+ ipmimv.c: fix problem with crontab or null-stdin invocations
+ alarms.c: 1.1: added -i for Chassis ID function
+ hwreset.c: 1.6: added -o for soft shutdown OS
+ man pages: updated, added alarms.8 & wdt.8
+ UserGuide: updated with new man page info
+ 05/03/03 ARCress ver 1.3.2
+ imbapi.c: clean up misc compile warnings
+ alarms.c: only try to set ID on/off if option specified
+ fruconfig.c: switched board part num & serial num
+ showsel.c: changed display ordering
+ ipmicmd.c: added GET_POWERON_HOURS
+ ipmicmd.h: added GET_POWERON_HOURS
+ sensor.c: added Power On Hours
+ hwreset.c: changed boot options to leave console redir same
+ 06/24/03 ARCress ver 1.3.3
+ fruconfig.c: added Chassis fields
+ fruconfig.c: added errno.h
+ pefconfig.c: fixed EnablePef if startup delay not supported
+ pefconfig.c: added errno.h
+ wdt.c: progver 1.2 includes EMSGSIZE fix
+ ipmimv.c: ignore EMSGSIZE errno for get_wdt command
+ showsel.c: fix -w if log gets cleared
+ ipmicmd.c: always add an extra byte to _mv sresp for cc
+ 07/24/03 ARCress
+ hpiutil-1.0.4.tar.gz: added parallel HPI utilities
+ 07/30/03 ARCress ver 1.3.4
+ pefconfig v1.18: add SerialOverLan configuration
+ mod to SetUser, added GetBmcEthDevice,
+ use 'arping -I' if eth1.
+ ipmicmd.c: added serial-over-lan commands,
+ added GetThresholds, fix for ipmi_cmd_raw,
+ changed some error messages
+ sensor v1.8: add -t option for thresholds,
+ added sample Discovery routine (unfinished)
+ added ipmi_getdeviceid for completeness
+ 08/18/03 ARCress ver 1.3.5
+ pefconfig v1.19: add SetLanParam(2) to 0x17 for SSU bug
+ showsel v1.14: Decode OEM event records for panic string
+ kern/bmcpanic-2.6.0.patch: changes to OpenIPMI for kernel 2.6.0
+ 09/18/03 ARCress ver 1.3.6
+ ipmicmd.c: added debug messages for fDriverTyp first time
+ sensor v1.9: show hex for most SDR OEM subtypes
+ fix bug in GetSDR multi-part gets (usu OEM SDRs)
+ stop if SDR Repository is empty
+ showsel v1.15: add more sens_desc strings
+ pefconfig v1.21: Don't enable a PEF entry if it is empty,
+ added -L lan_ch parameter,
+ scan for lan_ch in GetBmcEthDevice
+ tmconfig v1.13: isolate ser_ch, add -n option to specify chan#
+ UserGuide: added links for other IPMI drivers,
+ updated with new man page details
+ sensor.8 added option -t
+ pefconfig.8 added option -L
+ tmconfig.8 added option -n
+ 10/29/03 ARCress ver 1.3.7
+ pefconfig v1.21 added option -D for DHCP
+ pefconfig.8 added option -D
+ sensor v1.10 added options to set thresholds
+ sensor v1.11 fixed offset for show thresholds
+ sensor.8 documented threshold options
+ showsel v1.16 add more sens_desc strings (for boot)
+ wdt v1.3 fixed cc error in set_wdt (idata size)
+ 12/05/03 ARCress ver 1.3.8
+ pefconfig v1.22 fixed auth type enables for ServerConfig
+ 01/15/04 ARCress ver 1.4.0
+ ipmicmd.c added more SEvt commands
+ ipmicmd.h added more SEvt commands
+ sensor v1.12 fixed SetThreshold to set hysteresis
+ sensor.8 more desription on set threshold parameters
+ UserGuide updates sensor man page, added completion codes
+ README updated with current man page filenames
+ showsel v1.17 more sens_desc for Fans
+ 01/20/04 ARCress ver 1.4.1
+ imbapi.c added WIN32 flags
+ imb_api.h added WIN32 flags
+ ipmicmd.c added WIN32 flags
+ alarms v1.2 added mBMC code, Chesnee disk LEDs, & WIN32
+ showsel v1.18 added WIN32 flags, added header display
+ sensor v1.13 changed field order, added header display
+ check for sdr sz below min, added WIN32.
+ 03/23/04 ARCress ver 1.4.2
+ showsel v1.19 ClockSync description changed
+ wdt v1.4 fixed cc=0xcc if pretimeout not zero.
+ pefconfig v1.24 changed default pefnum for mBMC to 10
+ sensor v1.16 Added SDR type 3 parsing for mBMC,
+ Added check for superuser, more mBMC logic
+ 04/08/04 ARCress ver 1.4.3
+ checksel New script using showsel to write to syslog and clear if low
+ showsel v1.20 change pattern matching for thresholds,
+ added sens_desc for ID Button
+ added sens_desc for HSC, System Events, Power, Inter.
+ 04/30/04 ARCress ver 1.4.4
+ showsel v1.21 added threshold OK descriptions,
+ change header (time is local, not GMT)
+ sensor v1.17 added -r option for raw SDR output
+ ipmimv.c increased timeout from 5 sec to 10 sec
+ pefconfig v1.25 fixed lan_ch detection for some /dev/ipmi0 cases
+ 06/10/04 ARCress ver 1.4.5
+ ipmimv.c only open/close device once per application for
+ mv/openipmi driver, rely on each app calling ipmi_close.
+ *.c changes for ipmi_close, changes for WIN32
+ doc/mk.bat added, sample build script for WIN32
+ sensor v1.18 fixed sresp in GetSDR for WIN32
+ showsel v1.22 added ReportEvent for -w option with WIN32
+ v1.23 use gmtime instead of localtime for WIN32
+ pefconfig v1.27 added channel access params for ia64, added WIN32
+ 07/14/04 ARCress ver 1.4.6 panicsel
+ pefconfig.8 added more explanation with alert dest ip parameter.
+ pefconfig v1.28 added parsing for community on trapsink line,
+ show error message if GetDeviceID fails for WIN32.
+ tmconfig v1.15 allow -p for user 1 if no username specified (fSetPsw),
+ show error message if GetDeviceID fails for WIN32.
+ sensor v1.19 added -a to reArm sensor
+ UserGuide fix description of checksel
+ 07/23/04 ARCress ver 1.4.7 panicsel
+ pefconfig v1.29 use lan_ch variable to set Alert Policy Table,
+ which fixes a problem for TIGPT1U platforms.
+ bmclanpet.mib new MIB file added for PET
+ bmclanaol.mib renamed from bmclan.mib for alert-on-LAN
+ 08/05/04 ARCress ver 1.4.8 panicsel/ipmiutil
+ panicsel.spec redirect stderr to $tmpsel from pefconfig command.
+ For SuSE, symlink snmpd.conf to common location.
+ Also added icmd & icmd.8 to rpm.
+ hwreset v1.9 implement special OS shutdown method for Langleys,
+ make sure to show error if ccode != 0
+ icmd v1.2 fix for mv driver type in ipmicmd.c (thanks Kevin Gao)
+ doc/icmd.8 new man page added
+ doc/UserGuide added icmd description
+ added Use Cases for sensor thresholds and for
+ pefconfig with gpg decryption of password.
+ doc/Makefile copy icmd.8 for make install
+ util/ipmimv.c handle alternate device filenames for some 2.6 kernels
+ showsel v1.24 add more decoding for Power events
+ 08/24/04 ARCress ver 1.4.9 ipmiutil
+ sensor v1.20 add decoding for DIMM status (compact SDRs)
+ pefconfig 1.30 fixed decoding of PE Table entries,
+ added option -e for completeness,
+ added more messages to GetUser.
+ pefconfig.8 added more explanation of options.
+ UserGuide added separate References section 2.2
+ added section 4.5 on interpreting SNMP traps
+ from BMC LAN events.
+ added section 4.3 for watchdog usage
+ ipmiutil.spec link MIBs into /usr/share/snmp/mibs
+ alarms.c added more comments about alarm status byte
+ 10/29/04 ARCress ver 1.5.0 ipmiutil
+ pefconfig 1.31 added Get_Mac, etc. logic for WIN32.
+ pefconfig 1.32 added -N & -R
+ pefconfig.8 describe format for MAC address params.
+ UserGuide describe format for pefconfig MAC address params.
+ hpiutil/* misc changes, see hpiutil/ChangeLog
+ alarms 1.4 make sure we always write 1s for relays
+ ipmignu.c new file, to support GNU FreeIPMI lib
+ ipmicmd.c changes to support gnu lib
+ util/*.c changes to add -N nodename -R rmt_passwd
+ freeipmi/* new include files, lib files
+ doc/*.8 add -N -R descriptions
+ doc/UserGuide add -N -R descriptions
+ 11/09/04 ARCress ver 1.5.1 ipmiutil
+ ipmignu.c use MD5 instead of MD2 for ipmi_lan,
+ changes for comp code in _kcs_cmd & _lan_cmd
+ added sig_timeout for _kcs_cmd & _lan_cmd
+ ipmiutil.spec create /var/lib/freeipmi/ipckey in postinstall
+ 11/16/04 ARCress ver 1.5.2 ipmiutil
+ ipmignu.c added username logic, added sig_abort for ctl-C
+ util/*.c added -U option
+ doc/*.8 added -U option description
+ showsel.c added more watchdog2 decoding
+ 11/23/04 ARCress ver 1.5.3 ipmiutil
+ ipmignu.c added ipmi_lan ping before open_session,
+ added connect states for timeouts.
+ sensor.8 added -w option
+ sensor v1.22 added more compact sensor decoding, and -w option
+ showsel v1.28 added more decoding for crit_int, slots, etc.
+ changed firmware error decoding
+ pefconfig 1.34 added -u option to configure a lan username
+ fruconfig 1.9 version with ipmignu.c changes
+ tmconfig v1.17 version with ipmignu.c changes
+ hwreset v1.11 version with ipmignu.c changes
+ alarms v1.5 version with ipmignu.c changes
+ icmd.c v1.4 version with ipmignu.c changes
+ wdt v1.7 version with ipmignu.c changes
+ 12/08/04 ARCress ver 1.5.4 ipmiutil
+ hwreset v1.12 fix bug 1075550 with -o -N, skip -o if not local
+ sensor v1.23 added sens_type to display output
+ wdt v1.8 add counter & pretimeout display in show_wdt
+ icmd v1.5 changed usage order, put bus first
+ imbapi.c IMB_MEMORY compile flag, skip unneeded routines
+ doc/bmc*.mib removed outdated license text
+ hpiutil/hpiwdt v1.1 - fixed RPT loop, added more decoding,
+ added flags for HPI_A/HPI_B.
+ hpiutil/hpireset v1.1 - added HPI_A/B flags
+ hpiutil/hpifru v1.3 - added HPI_A/B flags
+ 01/11/05 ARCress ver 1.5.5 ipmiutil
+ doc/bmc*.mib added BSD license text for clarity
+ Makefile.am consolidate PKGDIR
+ setver discovers PKGDIR based on MACHTYPE
+ sensor v1.25 added support for device sdrs also,
+ fixed sens_cap byte,
+ change display order in ShowThresh, highest to lowest,
+ change signed exponent type in decodeValue
+ pefconfig 1.35 allow BMC LAN check if fIPMI10
+ 01/13/05 ARCress ver 1.5.6 ipmiutil
+ hpiutil/* changes for hpiutil-1.1.8 and HPI_A/B porting
+ fruconfig 1.10 add logic to scan SDRs for all FRU devices,
+ and interpret them.
+ sensor 1.26 added time display if -w
+ 01/31/05 ARCress ver 1.5.7 ipmiutil
+ util/*.c additional WIN32 compile flags for -N/-U/-R
+ sensor 1.27 mod for Power Redundancy SDR status
+ fruconfig 1.12 display formatted SystemGUID (with dashes)
+ pefconfig 1.36 handle IPMI 2.0 versions
+ tmconfig 1.18 handle IPMI 2.0 versions
+ 02/04/05 ARCress ver 1.5.8 ipmiutil
+ doc/Makefile change for /usr/share/man
+ doc/ipmiutil.spec change for /usr/share/man, change for rpm -U
+ fruconfig 1.13 fixed fwords bitmask in load_fru,
+ added more SPD decoding
+ 03/10/05 ARCress ver 1.6.0 ipmiutil
+ Makefile.am better order of cleanup for 'make tarball'
+ util/Makefile.am added getevent, xmlconfig
+ getevent.c new file, getevent utility, not always supported.
+ xmlconfig.c new file, xmlconfig utility, similar to pefconfig.
+ ipmicmd.c added more runtime debug to device opens
+ alarms 1.6 add new bus id for Intel TIGI2U
+ fruconfig 1.14 decode FRU Board Mfg DateTime
+ pefconfig 1.37 if DHCP, can set DHCP Server via -I param,
+ added IPMI 2.0 checking,
+ show Serial-Over-Lan params
+ fix -L with lan_ch_parm. mods to GetBmcEthDevice
+ sensor 1.29 added FloatToRaw for -h/-l threshold set funcs,
+ added better Phys Security sensor decoding.
+ added -v to show max/min & hysteresis.
+ showsel 1.29 made decode_sel_entry a subroutine,
+ added logic for OEM 0xc0 record types.
+ ipmild.c new file for supporting LanDesk driver (stub),
+ when ldipmi API lib is clean, this can be finished.
+ ipmicmd.c changes to add ipmi*_ld routines
+ ipmimv.c fix /dev/ipmi0 IPMB requests (to other than BMC_SA)
+ doc/tmconfig.8 added more in examples
+ doc/ipmiutil.spec check for any existing version of libfreeipmi & use it
+ 03/25/05 ARCress ver 1.6.1 ipmiutil
+ fruconfig 1.15 show Asset Tag Length earlier
+ pefconfig 1.39 fix GetBmcEthDevice for invalid MAC compares
+ tmconfig 1.19 show ser_ch being used, fix -n ser_ch
+ sensor 1.30 show BMC_TAM tag if configured in OEM SDRs
+ freeipmi/* upgraded files to freeipmi 0.1.3 (libfreeipmi.so.1)
+ 04/21/05 ARCress ver 1.6.2 ipmiutil
+ hwreset 1.13 try netapp_reset commands for platforms that use
+ this if chassis_reset gets an error.
+ alarms 1.7 add check for BMC TAM if trying to set alarms.
+ bmclanaol.mib fixed duplicate pET_AlertOnLan trap names
+ sensor 1.31 added battery type to decode_comp_reading
+ sensor 1.32 add error message if -n sensor_num not found
+ added more decoding for Power Redund sensor
+ 05/24/05 ARCress ver 1.6.3 ipmiutil
+ hpiutil/* 1.1.10 updates for hpiutil-1.1.10
+ ipmicmd.c - added LINK_LANDESK flags
+ imbapi.c - added LINK_LANDESK flags
+ imb_api.h - added LINK_LANDESK flags
+ ipmild.c - added LINK_LANDESK flags
+ hwreset 1.14 - added -u option for power up
+ getevent 0.4 - fixed bmc_enable bits, gets events ok now
+ showsel 1.30 - fixed -w SegFault with StartWriting/fscanf w GNU KCS
+ fruconfig 1.16 - dont try write_asset if show_fru gets an error
+ freeipmi/libf* - fixed ipmi_lan_open_session bug in freeipmi-0.1.3
+ freeipmi/ipmilan.patch - saved ipmi_lan patch for 0.1.3
+ README - added How to build with LanDesk support
+
+ 06/10/05 ARCress ver 1.6.4 ipmiutil
+ ipmignu.c - return NOTSUPPORTED if slave addr != BMC_SA
+ ipmignustub.c - add parameter sa to ipmicmd_gnu()
+ doc/UserGuide - inserted ipmiutil for Windows as section 5.0
+ doc/showsel.mc - new, showsel messages for windows syslog
+ events.c - new, moved decode_sel_event() here from showsel.c
+ getevent 0.5 - added call to decode_sel_event
+ showsel 1.31 - moved decode_sel_event to events.c
+ pefconfig 1.40 - Change priorities when setting my MAC in BMC
+
+ 06/24/05 ARCress ver 1.6.5 ipmiutil
+ tmconfig 1.21 - show multiple alert destinations
+ pefconfig 1.41 - show multiple alert destinations,
+ and handle fSOL20 commands
+ sensor 1.33 - handle ATCA platforms
+ fruconfig 1.17 - handle DeviceSDRs and ATCA
+ alarms 1.8 - added new code for PICMG/ATCA
+ alarms.8 - added explanation about Power LED wrt System Faults
+
+ 07/07/05 ARCress ver 1.6.6 ipmiutil
+ pefconfig 1.42 - Fix GetBmcEthDevice for TIGI2U with IMM GCM
+
+ 08/08/05 ARCress ver 1.6.7 ipmiutil
+ doc/ipmiutil.spec - rm getevent & xmlconfig before build rpm,
+ test if BMC LAN already configured before pefconfig
+ util/Makefile.am - add ipmild.o if no freeipmi
+ depcomp - new file added
+ util/ipmicmd.c - test for ldipmi first, to avoid LanDesk hang bug
+ sensor 1.34 - check if reading is in init state
+ pefconfig 1.43 - Mods to handle Intel NSI2U miniBMC,
+ pefconfig 1.44 - added -t option to test if BMC LAN configured
+ doc/UserGuide - added alarms.8 update wrt Power LED
+
+ 09/01/05 ARCress ver 1.6.8 ipmiutil
+ cleanup of comments to consistently use users.sf.net email address.
+ tmconfig 1.22 - truncate extra string chars
+ pefconfig 1.45 - truncate extra string chars,
+ README - added reference to INSTALL for build
+ INSTALL - added more build notes
+ doc/mksel.bat - new, special make for showsel.exe & showselmsg.dll
+ Makefile.am - make rpm update for --buildroot
+ util/Makefile.am - fixed missing -DLINUX error in 1.6.7
+ doc/ipmiutil.spec - make rpm update for RPM_BUILD_ROOT
+ fruconfig 1.18 - add -s option to set Product Serial Num also
+
+ 09/09/05 ARCress
+ getevent 0.6 - add event type filtering using sensor type
+ pefconfig 1.46 - enable mBMC PEF entries 26 thru 30
+ sensor 1.35 - dont check superuser if fipmi_lan
+ showsel 1.33 - dont check superuser if fipmi_lan
+
+ 09/16/05 ARCress
+ pefconfig.c - updated findmatch() for special case
+ xmlconfig.c - updated findmatch() for special case
+
+ 03/02/06 ARCress ver 1.6.9 ipmiutil
+ sensor 1.36 - check PowerOnHours completion code (01/18/06),
+ added -i option to only show one sensor index
+ ipmignu.c - changes to enable new libfreeipmi.so.1 w ipmi_cmd_raw,
+ use OLDLIB compile flag until this is complete.
+ *.c - rename ipmi_close & ipmi_cmd_raw to avoid conflicts
+ with new freeipmi lib symbols.
+ ipmiutil.spec - always copy checksel to /etc/cron.daily if ipmi works
+ events.c - handle more PowerUnit 0b vs. 6f event types
+
+ 04/13/06 ARCress ver 1.6.10 ipmiutil
+ sensor 1.37 - added -p option to persist/save thresholds
+ getevent 1.0 - added loop and -o for runOnce
+ alarms 1.9 - added BUS_ID7 for Harbison platform
+ pefconfig 1.47 - exit early if -d
+ hwreset 1.15 - added -p, -m, -e options
+ wdt 1.9 - fix -t if nsec > 255
+ icmd 1.6 - increment istart for -U -R (Thanks to Ernie Hansen)
+ bmchealth 0.2 - new file
+ doc/ipmiutil.spec - include getevent in rpm
+ doc/getevent.8 - new file
+ doc/bmchealth.8 - new file
+ doc/Makefile - add getevent.8
+
+05/18/06 ARCress ver 1.7.0 ipmiutil
+ tmconfig 1.23 - add -B baud option
+ bmchealth 0.3 - add get_chan_auth results, also -h option
+ doc/tmconfig.8 - document -B baud and -t options
+ doc/hwreset.8 - document -p -m -e options
+ doc/sensor.8 - document -i -p options
+ doc/pefconfig.8 - document -t option
+ doc/UserGuide - updated, added getevent, bmchealth
+ lib/Makefile - pick correct libipmiapi.a if present
+ Makefile.am - invoke lib/Makefile
+ util/ipmilan.c - new logic for built-in IPMI LAN interface
+ util/md2.c - new for ipmilan.c
+ util/md5.c - new for ipmilan.c
+ util/ipmicmd.c - invoke ipmilan logic ifdef BUILTIN_LAN
+ freeipmi/libfreeipmi.so-x86_64 - updated build
+
+06/19/06 ARCress ver 1.7.1 ipmiutil
+ util/ipmilan.c - fix seq_num wrap for longer lan sessions
+ util/sensor.c - fix PowerOnHours with 64-bit OSs.
+
+06/20/06 ARCress ver 1.7.2 ipmiutil
+ util/ipmilan.c - add rmcp_ping routine
+ bmchealth 0.6 - more vendor strings, add ping_node() stub for now
+ pefconfig 1.48 - fix strcmp(gcm), show all 4 alert policies,
+ add PefDesc() for misc vendor pefdesc, add -a.
+
+07/28/06 ARCress ver 1.7.3 ipmiutil
+ wdt 1.10 - added -l dontlog and -a action options
+ showsel 1.34 - added -l for last N records,
+ added more decoding for Memory, Audit types
+ sensor 1.39 - added -L for looping, handle fdevsdrs if rc==c1,
+ include SDR type 10h in parsing.
+ getevent 1.1 - specific no data message for cc=0x80,
+ include special getevent_mv() for OpenIPMI,
+ added msgout() routine
+ util/ipmicmd.c - add no data message to decode_cc,
+ better separate each driver implementation
+ util/ipmiia.c - new, separate for IA IMB driver
+ util/ipmiva.c - new, separate for VA driver
+ util/ipmilan.c - fix _lan_cmd returning an extra byte
+ util/ipmignu.c - support for freeipmi-0.2.3 lib, which supports ssif
+ via /dev/i2c-0 (i2c-core, i2c-i801, i2c-dev modules)
+ This ssif code does not yet work for all IPMI commands.
+ Note that the freeipmi-0.2.3 lan code has a naming
+ conflict with ipmi_cmd, so further code changes would
+ be required if one wanted to switch from Built-in LAN
+ to GNU_LAN.
+ util/ipmimv.c - added getevent_mv routine
+ util/events.c - added message for Chassis Intrusion
+ util/*.c - add -E option for IPMI_PASSWORD, use -P like -R,
+ add -V, -T options for IPMI LAN
+ doc/*.8 - updated man pages for changed options
+ doc/UserGuide - updated for changed options
+
+08/17/06 ARCress ver 1.7.4 ipmiutil
+ doc/ipmiutil.spec - fix for detecting existing libfreeipmi during install
+ util/ipmicmd.h - added decode_cc prototype
+ util/ipmicmd.c - only show no driver msg if not fipmi_lan
+ util/ipmilan.c - added decode_cc to default case, fix MASK_AUTHTYPEs,
+ added poke2 & command retries
+ pefconfig 1.49 - added Alcolu 0x0028 prod_id to fnotshared
+ getevent 1.2 - added -s for SEL method
+ fruconfig 1.19 - don't show Asset Tag Length by default
+ alarms 1.10
+ bmchealt 0.7
+ hwreset 1.17
+ icmd 1.7
+ sensor 1.40
+ showsel 1.35
+ tmconfig 1.24
+ wdt 1.11
+ xmlconfig 0.3
+
+08/22/06 ARCress ver 1.7.5 ipmiutil
+ ipmidir.c - new, for direct raw I/Os (if no driver)
+ ipmidir.h - new
+ ipmilan.c - keep going even if ping failure
+ imbapi.c - more DEBUG output
+ doc/ipdiff.sh - new script to allocate non-shared BMC LAN IP addresses
+ alarms 1.11
+ bmchealth 0.8
+ fruconfig 1.20
+ getevent 1.3
+ hwreset 1.18
+ icmd 1.8
+ pefconfig 1.50
+ sensor 1.41
+ showsel 1.36 - PowerUnit decoding for data1=0x43
+ tmconfig 1.25
+ wdt 1.12 - fixed typo for -r/-a options
+ xmlconfig 0.4
+
+09/12/06 ARCress ver 1.7.6 ipmiutil
+ ipmiutil.spec - save a sensor snapshot as sensor_out.txt
+ pefconfig.8 - added EXAMPLES
+ UserGuide - added pefconfig EXAMPLES
+ tmconfig.c - use authmask to set Serial Param(2)
+ pefconfig.c - use -B for baud_sol, move alert_max to -X.
+ ipmidir.c - streamlined debug messages
+ showsel.c - fixed wrap condition for showsel -l option
+ getevent.c - handle empty SEL for getevent -s option
+ ipmiutil-1.7.6:
+ alarms.c ver 1.12
+ bmchealth.c ver 0.9
+ fruconfig.c ver 1.21
+ getevent.c ver 1.4
+ hwreset.c ver 1.19
+ icmd.c ver 1.9
+ pefconfig.c ver 1.51
+ sensor.c ver 1.42
+ showsel.c ver 1.37
+ tmconfig.c ver 1.26
+ wdt.c ver 1.13
+ xmlconfig.c ver 0.5
+
+10/02/06 ARCress ver 1.7.7 ipmiutil
+ test/ipmievt.sh - new, causes Baseboard Temp events with sensor thresholds
+ doc/ipmi_if.sh - gather more info from dmidecode to ipmi_if.txt
+ util/hwreset.c - soft reset stuff, special handling for Tyan systems.
+ util/pefconfig.c - added -q for user number,
+ use bmcmymac if valid, use bmcmyip if ok,
+ enhanced Get_IPMac_Addr for Windows
+ util/tmconfig.c - added -q for user number, added -f for Flow Control,
+ adjust Mode if known, clear SerialParam(3) if -d
+ util/ipmidir.c - improved detection for DRV_SMB base address
+ util/events.c - support WIN32 if TEST compile flag
+ freeipmi/*.h - removed unused include files
+ ipmiutil-1.7.7:
+ alarms.c ver 1.13
+ bmchealth.c ver 0.10
+ fruconfig.c ver 1.22
+ getevent.c ver 1.5
+ hwreset.c ver 1.20
+ icmd.c ver 1.10
+ pefconfig.c ver 1.52
+ sensor.c ver 1.43
+ showsel.c ver 1.38
+ tmconfig.c ver 1.27
+ wdt.c ver 1.14
+ xmlconfig.c ver 0.6
+
+
+10/19/06 ARCress ver 1.7.8 ipmiutil
+ util/pefconfig.c - use bmcdestip if valid,
+ FindEthNum updates, always use gwy interface for mac,
+ add -# alias for -q usernum (max =15)
+ util/tmconfig.c - add -# alias for -q usernum (max =15)
+ util/sensor.c - check Repository Info whether Reserve supported or not,
+ and use Reserve whenever possible.
+ util/bmchealth.c - more vendor names
+ util/hwreset.c - added -D for soft power down
+ util/ipmilan.c - special for Dell BMC with no MsgAuth support
+ doc/UserGuide - more sensor details, decimal completion codes, etc.
+ ipmiutil-1.7.8:
+ alarms.c ver 1.14
+ bmchealth.c ver 1.0
+ fruconfig.c ver 1.23
+ getevent.c ver 1.6
+ hwreset.c ver 1.21
+ icmd.c ver 1.11
+ pefconfig.c ver 1.53
+ sensor.c ver 1.44
+ showsel.c ver 1.39
+ tmconfig.c ver 1.28
+ wdt.c ver 1.15
+ xmlconfig.c ver 0.7
+
+
+10/24/06 ARCress ver 1.7.9 ipmiutil
+ util/bmchealth.c - add -g for system GUID
+ util/ipmilan.c - streamline some debug messages
+ util/alarms.c - do not abort if no Telco Alarms, still allow -i
+ util/pefconfig.c - fix 0xc7 error with SOL AccumInterval
+ ipmiutil-1.7.9:
+ alarms.c ver 1.15
+ bmchealth.c ver 1.1
+ fruconfig.c ver 1.24
+ getevent.c ver 1.7
+ hwreset.c ver 1.22
+ icmd.c ver 1.12
+ pefconfig.c ver 1.54
+ sensor.c ver 1.45
+ showsel.c ver 1.40
+ tmconfig.c ver 1.29
+ wdt.c ver 1.16
+ xmlconfig.c ver 0.8
+
+12/08/06 ARCress ipmituil-1.7.10 changes
+ util/idiscover.c - new
+ util/isolconsole.c - new, renamed from solconsole.c (just a framework)
+ util/ipmilan.c - Change ASF ping IANA number to HI-LO ordering (1601296)
+ util/pefconfig.c - display user names, EnablePef mods for non-Intel
+ util/tmconfig.c - display user names
+ util/ipmicmd.c - added ipmi_getpicmg(), ipmi_cmd_mc()
+ util/ipmilan.c - added ipmi_cmd_ipmb() for IPMB indirect cmds
+ util/*.c - test for fpicmg (ATCA)
+ util/sensor.c - add -m, -c and child MC logic for ATCA
+ util/fruconfig.c - add -m option for ATCA child MCs.
+ util/Makefile.am - mods for idiscover, isolconsole
+ mods for configure/landesk feature
+ doc/ipmiutil.spec - create new util names with i*
+ configure.in - mods for --enable-landesk=yes
+ Makefile.am - fix make tarball for libipmiapi32.a (bug 1610481)
+ ipmiutil-1.7.10 contains:
+ alarms.c (ialarms) ver 1.16
+ bmchealth.c (ihealth) ver 1.2
+ fruconfig.c (ifruconfig) ver 1.25
+ getevent.c (igetevent) ver 1.8
+ hwreset.c (ireset) ver 1.23
+ icmd.c (icmd) ver 1.13
+ pefconfig.c (ilanconfig) ver 1.55
+ sensor.c (isensor) ver 1.46
+ showsel.c (ishowsel) ver 1.41
+ tmconfig.c (iserconfig) ver 1.30
+ wdt.c (iwatchdog) ver 1.17
+ xmlconfig.c (n/a) ver 0.9
+
+01/09/07 ARCress ipmiutil-1.8.0 changes
+ util/events.c - added Power Unit 0x8B events
+ util/sensor.c - more ShowTAM decoding
+ util/ipmilanplus.c - new for v2.0 RMCP+ via ipmitool plugin
+ util/ipmilan2.c - new for internal v2.0 RMCP+ (incomplete, not used)
+ util/ipmicmd.c - added logic for calling lan2
+ util/ipmiutil.c - new, meta-command code
+ util/*.c - mods for -DMETACOMMAND
+ util/Makefile.am - mods to build with -DMETACOMMAND and ipmilanplus.c
+ doc/ipmiutil.8 - new man page
+ doc/ipmiutil.spec - add ipmiutil METACOMMAND
+ doc/*.8 - add -F option
+ doc/UserGuide - add ipmiutil, -F option, reorder man pages
+ doc/mk*.bat - updates for lanplus
+ lib/Makefile - added make for lib/lanplus subdir
+ lib/lanplus/* - new for ipmitool-1.8.7 plugin library
+ ipmiutil-1.8.0 contains:
+ ipmiutil.c (ipmiutil) ver 1.0
+ alarms.c (ialarms) ver 1.17
+ bmchealth.c (ihealth) ver 1.3
+ fruconfig.c (ifruconfig) ver 1.26
+ getevent.c (igetevent) ver 1.9
+ hwreset.c (ireset) ver 1.24
+ icmd.c (icmd) ver 1.14
+ pefconfig.c (ilanconfig) ver 1.56
+ sensor.c (isensor) ver 1.47
+ showsel.c (ishowsel) ver 1.42
+ tmconfig.c (iserconfig) ver 1.31
+ wdt.c (iwatchdog) ver 1.18
+ xmlconfig.c (n/a) ver 0.10
+
+01/12/07 ARCress ipmiutil-1.8.1 changes
+ util/ipmilanplus.c - return proper rsp len to fix Win fruconfig bug
+ util/ipmicmd.c - added show_driver_type() and debug output
+ util/hwreset.c - Linux -o allow init6 or init0, alt -o if WIN32
+ util/bmchealth.c - added some product strings, added Power State
+ util/events.c - add a '#' before sensor number for easier parsing,
+ change Watchdog 1/2 to Watchdog_1/2 for parsing,
+ more BMC System Event descriptions,
+ util/pefconfig.c - show nice error message if pefconfig -e -N
+ doc/pefconfig.8 - change examples to show pefconfig -e
+ doc/getevent.8 - more explanation of methods
+ doc/ipmi_if.sh - new syntax for tail/head -n
+ doc/showsel.reg - new, add registry entries for this EventLog service
+ doc/UserGuide - mention showsel.reg, updated man pages
+ ipmiutil-1.8.1 contains:
+ ipmiutil.c (ipmiutil) ver 1.1
+ alarms.c (ialarms) ver 1.18
+ bmchealth.c (ihealth) ver 1.4
+ fruconfig.c (ifruconfig) ver 1.27
+ getevent.c (igetevent) ver 1.10
+ hwreset.c (ireset) ver 1.25
+ icmd.c (icmd) ver 1.15
+ pefconfig.c (ilanconfig) ver 1.57
+ sensor.c (isensor) ver 1.48
+ showsel.c (ishowsel) ver 1.43
+ tmconfig.c (iserconfig) ver 1.32
+ wdt.c (iwatchdog) ver 1.19
+ xmlconfig.c (ixmlconfig) ver 0.11
+
+01/23/07 ARCress ipmiutil-1.8.2 changes
+ util/showsel.c - always show error if cannot open idx file with -w
+ util/pefconfig.c - fixed -d bug where freadonly flag was =1.
+ util/ipmilanplus.c - added HAVE_LANPLUS compile flag
+ util/Makefile.am - added --disable-lanplus option
+ configure.in - added --disable-lanplus option
+ win32.zip - added libeay32.dll from openssl build
+ ipmiutil-1.8.2 contains:
+ ipmiutil.c (ipmiutil) ver 1.2
+ alarms.c (ialarms) ver 1.19
+ bmchealth.c (ihealth) ver 1.5
+ fruconfig.c (ifruconfig) ver 1.28
+ getevent.c (igetevent) ver 1.11
+ hwreset.c (ireset) ver 1.26
+ icmd.c (icmd) ver 1.16
+ pefconfig.c (ilanconfig) ver 1.58
+ sensor.c (isensor) ver 1.49
+ showsel.c (ishowsel) ver 1.44
+ tmconfig.c (iserconfig) ver 1.33
+ wdt.c (iwatchdog) ver 1.20
+ xmlconfig.c (ixmlconfig) ver 0.12
+
+02/08/07 ARCress ipmiutil-1.9.0 changes
+ util/fruconfig.c - dont show baseboard FRU twice via DLR
+ util/ipmicmd.c - added parse_lan_options, print_lan_opt_usage
+ added -Y option to prompt for password using getline()
+ util/ipmicmd.h - added parse_lan_options, print_lan_opt_usage
+ util/*.c - call parse_lan_options, print_lan_opt_usage
+ util/isolconsole.c - added v2 console functionality,
+ works fine in Linux, stdin problems in Windows.
+ util/ipmiutil.c - added sol console to dispatch table
+ util/ipmidir.c - more max recv len checking
+ ipmiutil-1.9.0 contains:
+ ipmiutil.c (ipmiutil) ver 1.3
+ alarms.c (ialarms) ver 1.20
+ bmchealth.c (ihealth) ver 1.6
+ fruconfig.c (ifruconfig) ver 1.29
+ getevent.c (igetevent) ver 1.12
+ hwreset.c (ireset) ver 1.27
+ icmd.c (icmd) ver 1.17
+ pefconfig.c (ilanconfig) ver 1.59
+ sensor.c (isensor) ver 1.50
+ showsel.c (ishowsel) ver 1.45
+ tmconfig.c (iserconfig) ver 1.34
+ wdt.c (iwatchdog) ver 1.21
+ xmlconfig.c (ixmlconfig) ver 0.13
+ isolconsole.c (isolconsole) ver 0.9
+
+02/16/07 ARCress ipmiutil-1.9.1 changes
+ util/fruconfig.c - put -m option back for ATCA
+ util/sensor.c - put -c & -m option back for ATCA
+ util/icmd.c - fix bug w arg options to use optind, add -m
+ util/ipmidir.c - bug fix: skip unsafe mmap code if 64-bit
+ ipmiutil-1.9.1 contains:
+ ipmiutil.c (ipmiutil) ver 1.4
+ alarms.c (ialarms) ver 1.21
+ bmchealth.c (ihealth) ver 1.7
+ fruconfig.c (ifruconfig) ver 1.30
+ getevent.c (igetevent) ver 1.13
+ hwreset.c (ireset) ver 1.28
+ icmd.c (icmd) ver 1.18
+ pefconfig.c (ilanconfig) ver 1.60
+ sensor.c (isensor) ver 1.51
+ showsel.c (ishowsel) ver 1.46
+ tmconfig.c (iserconfig) ver 1.35
+ wdt.c (iwatchdog) ver 1.22
+ xmlconfig.c (ixmlconfig) ver 0.14
+ isolconsole.c (isolconsole) ver 0.10
+
+02/23/07 ARCress ipmiutil-1.9.2 changes
+ util/pefconfig.c - add Get/SetPayloadAccess for 2.0 SOL
+ util/isolconsole.c - add -e for no encryption, fix Windows stdin
+ util/ipmilan.c - add some 1.5 SOL code
+ util/ipmilanplus.c - set cipher_suite = 3 for open session request
+ util/sensor.c - add CPU Proc Hot decoding for evtype==5
+ util/ipmiutil.c - use sub-command names as i_* routines
+ util/*.c - changed to i_* naming
+ doc/ipmiutil.spec - link to i_* command names, add isolconsole
+ ipmiutil-1.9.2 contains:
+ ipmiutil.c (ipmiutil) ver 1.5
+ alarms.c (i_alarms) ver 1.22
+ bmchealth.c (i_health) ver 1.8
+ fruconfig.c (i_fru) ver 1.31
+ getevent.c (i_getevt) ver 1.14
+ hwreset.c (i_reset) ver 1.29
+ icmd.c (i_cmd) ver 1.19
+ pefconfig.c (i_lan) ver 1.61
+ sensor.c (i_sensor) ver 1.52
+ showsel.c (i_sel) ver 1.47
+ tmconfig.c (i_serial) ver 1.36
+ wdt.c (i_wdt) ver 1.23
+ xmlconfig.c (i_xml) ver 0.15
+ isolconsole.c (i_sol) ver 1.0
+
+03/15/07 ARCress ipmiutil-1.9.3 changes
+ test/Makefile - better kernel module make for Linux 2.4 and 2.6
+ test/dopanic_drv.c - renamed from dopanic.c
+ test/dopanic.c - deleted
+ test/dopanic.8 - new man page
+ test/ipmi_evt.sh - comments about ibasetemp
+ lib/Makefile - mods for libipmi_lanplus.so
+ lib/lanplus/lanplus.c - check null rsp in open_session
+ lib/lanplus/Makefile.am - mods for libipmi_lanplus.so,
+ dynamic lib*.so rather than static lib*.a
+ doc/Makefile - install wdt.sh in data dir
+ doc/ipmiutil.spec - add wdt.sh to rpm, add libipmi_lanplus.*
+ beforeconf.sh - new: for lt files, aclocal, autoconf
+ util/Makefile.am - fixed make libipmiutil.a, libipmi_lanplus.so
+ util/*.c - added show_outcome() at the end
+ ipmiutil-1.9.3 contains:
+ ipmiutil.c (ipmiutil) ver 1.6
+ alarms.c (i_alarms) ver 1.23
+ bmchealth.c (i_health) ver 1.9
+ fruconfig.c (i_fru) ver 1.32
+ getevent.c (i_getevt) ver 1.15
+ hwreset.c (i_reset) ver 1.30
+ icmd.c (i_cmd) ver 1.20
+ pefconfig.c (i_lan) ver 1.62
+ sensor.c (i_sensor) ver 1.53
+ showsel.c (i_sel) ver 1.48
+ tmconfig.c (i_serial) ver 1.37
+ wdt.c (i_wdt) ver 1.24
+ xmlconfig.c (i_xml) ver 0.16
+ isolconsole.c (i_sol) ver 1.1
+
+04/06/07 ARCress ipmiutil-1.9.4 changes
+ util/isolconsole.c - added #else for HAVE_LANPLUS,
+ more vt100-to-ansi handling,
+ added -r for raw termio if Windows ANSI
+ util/ipmicmd.c - fix spacing in dump_buf
+ lib/lanplus/lanplus.c - abort if bad HMAC from RAKP2
+ doc/ipmiutil.spec - fix libcrypto.so.4 for MVL
+ util/getevent.c - interpret cc==0x80 as timeout message
+ util/ipmimv.c - handle MV bug: missing 3 bytes
+ util/showsel.c - also show OEM records if -s
+ ipmiutil-1.9.4 contains:
+ ipmiutil.c (ipmiutil) ver 1.7
+ alarms.c (i_alarms) ver 1.24
+ bmchealth.c (i_health) ver 1.10
+ fruconfig.c (i_fru) ver 1.33
+ getevent.c (i_getevt) ver 1.16
+ hwreset.c (i_reset) ver 1.31
+ icmd.c (i_cmd) ver 1.21
+ pefconfig.c (i_lan) ver 1.63
+ sensor.c (i_sensor) ver 1.54
+ showsel.c (i_sel) ver 1.49
+ tmconfig.c (i_serial) ver 1.38
+ wdt.c (i_wdt) ver 1.25
+ xmlconfig.c (i_xml) ver 0.17
+ isolconsole.c (i_sol) ver 1.2
+
+04/20/07 ARCress ipmiutil-1.9.5 changes
+ util/events.c - add -p for PET format events
+ util/Makefile.am - do "make events" to build events util
+ util/ipmimv.c - check for ASYNC_EVENTs in ipmicmd_mv
+ util/ipmilan.c - some 1.5 SOL data mods, decode_rv mods
+ util/ipmicmd.c - some 1.5 SOL data mods, show_outcome(decode_rv)
+ util/isolconsole.c - some 1.5 SOL data mods, more win termio
+ util/alarms.c - add -d for enclosure slot LEDs
+ ipmiutil-1.9.5 contains:
+ ipmiutil.c (ipmiutil) ver 1.8
+ alarms.c (i_alarms) ver 1.25
+ bmchealth.c (i_health) ver 1.11
+ fruconfig.c (i_fru) ver 1.34
+ getevent.c (i_getevt) ver 1.17
+ hwreset.c (i_reset) ver 1.32
+ icmd.c (i_cmd) ver 1.22
+ pefconfig.c (i_lan) ver 1.64
+ sensor.c (i_sensor) ver 1.55
+ showsel.c (i_sel) ver 1.50
+ tmconfig.c (i_serial) ver 1.39
+ wdt.c (i_wdt) ver 1.26
+ xmlconfig.c (i_xml) ver 0.18
+ isolconsole.c (i_sol) ver 1.3
+
+05/10/07 ARCress ipmiutil-1.9.6 changes
+ doc/UserGuide - added section 4.7 How to configure IPMI LAN,
+ updated Windows build instructions
+ doc/pefconfig.8 - add -l option description
+ doc/wdt.sh - fix cron entry to run every 60 seconds
+ doc/idiscover.8 - new
+ test/ipmievt.sh - automatically set ibasetemp via $sensorfil
+ util/ipmilan.c - more 1.5 SOL data mods, not working yet
+ util/ipmi*.c - cleanup, use common ipmi_cmdraw* routines
+ util/ipmiia.c - no longer used, see imbapi.c
+ util/Makefile.am - remove ipmiia.c
+ util/pefconfig.c - add -l to configure LAN but not PEF,
+ fix 1714748 for getopt missing X param
+ util/idiscover.c - add -g and -a functionality, and WIN32
+ * Improvements for Windows build:
+ lib/lanplus/*.c - change to inttypes-win.h if WIN32
+ lib/lanplus/inc/ipmitool/*.h - change to inttypes-win.h
+ lib/lanplus/inc/inttypes-win.h - new
+ lib/lanplus/ipmiplus.mak - new
+ lib/ipmilib.mak - new
+ util/ipmiutil.mak - new
+ buildwin.cmd - new
+ INSTALL - updated Windows build instructions
+ ipmiutil-1.9.6 contains:
+ ipmiutil.c (ipmiutil) ver 1.9
+ alarms.c (i_alarms) ver 1.26
+ bmchealth.c (i_health) ver 1.12
+ fruconfig.c (i_fru) ver 1.35
+ getevent.c (i_getevt) ver 1.18
+ hwreset.c (i_reset) ver 1.33
+ icmd.c (i_cmd) ver 1.23
+ pefconfig.c (i_lan) ver 1.65
+ sensor.c (i_sensor) ver 1.56
+ showsel.c (i_sel) ver 1.51
+ tmconfig.c (i_serial) ver 1.40
+ wdt.c (i_wdt) ver 1.27
+ xmlconfig.c (i_xml) ver 0.19
+ isolconsole.c (i_sol) ver 1.4
+ idiscover.c (i_discover) ver 1.0
+ PENDING ISSUES in ipmiutil-1.9.6:
+ Handle Windows command prompt terminal emulation for SOL
+ The Windows isolconsole.exe works, but the terminal emulation logic is
+ not finished. It works ok to Linux command-line and vi, but looks
+ bad for BIOS/POST. This is in progress. There are other (non-open)
+ tools available for Windows (e.g. Intel dpccli) in the interim.
+ The Linux isolconsole works fine, this relates to Windows client SOL.
+ Add older 1.5 SOL protocol capability
+ For isolconsole with IPMI 1.5, the older (Intel-only) 1.5 SOL protocol
+ is implemented and will connect, but the 1.5 SOL data packets are not
+ right yet. This is in progress. Note that the standard IPMI 2.0 SOL
+ protocol is entirely separate and still works fine.
+
+
+05/29/07 ARCress ipmiutil-1.9.7 changes
+ doc/UserGuide - added idiscover, SOL section 4.8,
+ and more Windows build detail
+ doc/ipmiutil.spec - added ipmi_port init handling, %buildroot changes
+ doc/ipmi_port.sh - init script for ipmi_port
+ doc/Makefile - add ipmi_port.sh
+ util/bmchealth.c - add more manufacturers
+ util/ipmidir.c - allow "Register Spacing:" in ipmi_if.txt
+ util/ipmi_port.c - new, allocate RMCP port for port mapper
+ util/getevent.c - add -b for background
+ util/tmconfig.c - add -i for inactivity timeout
+ util/pefconfig.c - use serial baud for SOL baud by default,
+ add Windows iphlpapi calls for detection.
+ util/ipmiutil.mak - add iphlpapi.lib for pefconfig
+ util/pefconfig.c-nohlp - new, without Windows iphlpapi.*
+ util/ipmiutil.mak-nohlp - new, without Windows iphlpapi.lib
+ util/isolconsole.c - fix Enter key confusion w BIOS menus (use CR+LF)
+ util/Makefile.am - build events and ipmi_port by default
+ lib/lanplus/lanplus.c - fixed assert(0) in ipmi_lan_poll_recv,
+ and set rmcp_hdr __rsvd=0 for WIN32
+ Makefile.am - use default buildroot
+ ipmiutil-1.9.7 contains:
+ ipmiutil.c (ipmiutil) ver 1.10
+ alarms.c (i_alarms) ver 1.27
+ bmchealth.c (i_health) ver 1.13
+ fruconfig.c (i_fru) ver 1.36
+ getevent.c (i_getevt) ver 1.19
+ hwreset.c (i_reset) ver 1.34
+ icmd.c (i_cmd) ver 1.24
+ pefconfig.c (i_lan) ver 1.66
+ sensor.c (i_sensor) ver 1.57
+ showsel.c (i_sel) ver 1.52
+ tmconfig.c (i_serial) ver 1.41
+ wdt.c (i_wdt) ver 1.28
+ isolconsole.c (i_sol) ver 1.5
+ idiscover.c (i_discover) ver 1.1
+
+07/03/07 ARCress ipmiutil-1.9.8 changes
+ util/pefconfig.c - Fix DHCP Server MAC detection,
+ detect ethN from gateway route sooner
+ util/events.c - Fix TEST with no args
+ util/ipmiutil.mak - add events.exe
+ util/Makefile.am - build libipmiutil.a by default
+ util/isolconsole.c - more fixes to Windows translation (-w)
+ (-w -l gives much better windows emulation, but
+ there are still some anomalies with it.)
+ util/ipmidir.c - loop safety limit in KCS wait_for*
+ lib/Makefile - mods for libipmi_lanplus.a
+ lib/lanplus/Makefile.am - build static libipmi_lanplus.a
+ doc/ipmiutil.spec - rpmlint tweaks, use ipmiutil meta-cmd
+ doc/wdt.sh - use ipmiutil meta-cmd
+ doc/checksel - use ipmiutil meta-cmd
+ ipmiutil-1.9.8 contains:
+ ipmiutil.c (ipmiutil) ver 1.11
+ alarms.c (i_alarms) ver 1.28
+ bmchealth.c (i_health) ver 1.14
+ fruconfig.c (i_fru) ver 1.37
+ getevent.c (i_getevt) ver 1.20
+ hwreset.c (i_reset) ver 1.35
+ icmd.c (i_cmd) ver 1.25
+ pefconfig.c (i_lan) ver 1.67
+ sensor.c (i_sensor) ver 1.58
+ showsel.c (i_sel) ver 1.53
+ tmconfig.c (i_serial) ver 1.42
+ wdt.c (i_wdt) ver 1.29
+ isolconsole.c (i_sol) ver 1.6
+ idiscover.c (i_discover) ver 1.2
+ ipmi_port.c (i_port) ver 0.2
+
+10/01/07 ARCress ipmiutil-2.0.0 changes
+ This release adds two major features:
+ 1) Windows SOL emulation (v100 terminal emulation)
+ 2) Remote soft-shutdown (using hwreset & getevent -a)
+ util/isolwin.c - new, Windows SOL emulation routines,
+ added sleep to input thread, scrolling,
+ significant SOL emulation mods
+ util/isolconsole.c - calls to isolwin.c, arrow/function key handling
+ util/hwreset.c - show Power State also, as in bmchealth,
+ added remote shutdown request (-o -N)
+ util/sensor.c - fix interpretation of Battery sensors
+ util/ipmilan.c - show_LastError if not debug, more detail
+ show connected nodename & IP, added NON_GPL flag,
+ fix for Dell 1855 authcodes.
+ util/ipmicmd.c - add show_LastError to show_outcome()
+ util/ipmiva.c - added NON_GPL/VAOK compile flags
+ util/idiscover.c - fixed receive/send thread order
+ util/getevent.c - handle remote shutdown via -a using IMB
+ util/pefconfig.c - dont detect gcm by default for Caneland
+ util/ipmicmd.c - added -J for cipher_suite option
+ util/Makefile.am - add GPL_CFLAGS for nongpl
+ util/ipmiutil.mak - add NON_GPL option, add isolwin.obj
+ util/ipmilanplus.c - detect IBMC as not 'intelplus'
+ lib/lanplus/lanplus.c - show connected nodename & IP
+ doc/getevent.8 - added -a option
+ doc/hwreset.8 - added note for -o -N option
+ doc/UserGuide - updates for getevent,hwreset
+ doc/ipmi_port.sh - do not start ipmi_port if dpcproxy is running
+ configure.in - add --enable-nongpl option
+ ipmiutil-2.0.0 contains:
+ ipmiutil.c (ipmiutil) ver 2.0
+ alarms.c (ipmiutil alarms) ver 1.29
+ bmchealth.c (ipmiutil health) ver 1.15
+ fruconfig.c (ipmiutil fru) ver 1.38
+ getevent.c (ipmiutil getevt) ver 2.0
+ hwreset.c (ipmiutil reset) ver 2.0
+ icmd.c (ipmiutil cmd) ver 1.26
+ pefconfig.c (ipmiutil lan) ver 1.68
+ sensor.c (ipmiutil sensor) ver 1.59
+ showsel.c (ipmiutil sel) ver 1.54
+ tmconfig.c (ipmiutil serial) ver 1.43
+ wdt.c (ipmiutil wdt) ver 2.0
+ isolconsole.c (ipmiutil sol) ver 1.7
+ idiscover.c (ipmiutil discover) ver 1.2
+ ipmi_port.c (ipmi_port) ver 0.5
+
+10/10/07 ARCress ipmiutil-2.0.1 changes
+ util/events.c - handle -p using file_grep in Windows
+ util/ipmilanplus.c - fixed bug detecting icts oem flag for many vendors
+ util/ipmicmd.c - fixed logmsg/openlog(NULL) bug, add EFI ifdefs
+ util/ipmilan.c - bug fixes for 1.5 SOL routines
+ util/isolconsole.c - detect SuperMicro & use shorter SOL keepalive timeout
+ util/wdt.c - add EFI ifdefs
+ ipmiutil-2.0.1 contains:
+ ipmiutil.c (ipmiutil) ver 2.1
+ alarms.c (ipmiutil alarms) ver 1.30
+ bmchealth.c (ipmiutil health) ver 1.16
+ fruconfig.c (ipmiutil fru) ver 1.39
+ getevent.c (ipmiutil getevt) ver 2.1
+ hwreset.c (ipmiutil reset) ver 2.1
+ icmd.c (ipmiutil cmd) ver 1.27
+ pefconfig.c (ipmiutil lan) ver 1.69
+ sensor.c (ipmiutil sensor) ver 1.60
+ showsel.c (ipmiutil sel) ver 1.55
+ tmconfig.c (ipmiutil serial) ver 1.44
+ wdt.c (ipmiutil wdt) ver 1.31
+ isolconsole.c (ipmiutil sol) ver 2.1
+ idiscover.c (ipmiutil discover) ver 1.2
+ ipmi_port.c (ipmi_port) ver 0.5
+
+
+10/22/07 ARCress ipmiutil-2.0.2 changes
+ util/ipmidir.c - fix bug in ipmi_if.txt Base Address parsing
+ util/sensor.c - fix HSC drive slot sensor reading interpretation,
+ avoid HSC sensor errors over IPMI LAN.
+ util/events.c - added 8b 05 event decoding to redund_str
+ util/pefconfig.c - added osmyip,osmymac for alertname==localhost
+ ipmiutil-2.0.2 contains:
+ ipmiutil.c (ipmiutil) ver 2.2
+ alarms.c (ipmiutil alarms) ver 1.31
+ bmchealth.c (ipmiutil health) ver 1.17
+ fruconfig.c (ipmiutil fru) ver 1.40
+ getevent.c (ipmiutil getevt) ver 2.2
+ hwreset.c (ipmiutil reset) ver 2.2
+ icmd.c (ipmiutil cmd) ver 1.28
+ pefconfig.c (ipmiutil lan) ver 1.70
+ sensor.c (ipmiutil sensor) ver 2.2
+ showsel.c (ipmiutil sel) ver 1.56
+ tmconfig.c (ipmiutil serial) ver 1.45
+ wdt.c (ipmiutil wdt) ver 1.32
+ isolconsole.c (ipmiutil sol) ver 2.2
+ idiscover.c (ipmiutil discover) ver 1.2
+ ipmi_port.c (ipmi_port) ver 0.5
+
+11/01/07 ARCress ipmiutil-2.0.3 changes
+ util/sensor.c - handle & recover from GetSDR error 0xC5
+ util/pefconfig.c - fixed PEF entry for Power Redundancy Lost
+ util/events.c - decode special System Boot event for S5000
+ decode PET Power Redundancy correctly
+ ipmiutil-2.0.3 contains:
+ ipmiutil.c (ipmiutil) ver 2.3
+ alarms.c (ipmiutil alarms) ver 1.32
+ bmchealth.c (ipmiutil health) ver 1.18
+ fruconfig.c (ipmiutil fru) ver 1.41
+ getevent.c (ipmiutil getevt) ver 2.3
+ hwreset.c (ipmiutil reset) ver 2.3
+ icmd.c (ipmiutil cmd) ver 1.29
+ pefconfig.c (ipmiutil lan) ver 2.3
+ sensor.c (ipmiutil sensor) ver 2.3
+ showsel.c (ipmiutil sel) ver 1.57
+ tmconfig.c (ipmiutil serial) ver 1.46
+ wdt.c (ipmiutil wdt) ver 1.33
+ isolconsole.c (ipmiutil sol) ver 2.3
+ idiscover.c (ipmiutil discover) ver 1.2
+ ipmi_port.c (ipmi_port) ver 0.5
+
+11/16/07 ARCress ipmiutil-2.0.4 changes
+ util/pefconfig.c - add a custom PEF entry via -j, set PEF severity,
+ better IsMacValid checking to allow broadcast MAC.
+ ipmiutil-2.0.4 contains:
+ ipmiutil.c (ipmiutil) ver 2.4
+ alarms.c (ipmiutil alarms) ver 1.33
+ bmchealth.c (ipmiutil health) ver 1.19
+ fruconfig.c (ipmiutil fru) ver 1.42
+ getevent.c (ipmiutil getevt) ver 2.4
+ hwreset.c (ipmiutil reset) ver 2.4
+ icmd.c (ipmiutil cmd) ver 1.30
+ pefconfig.c (ipmiutil lan) ver 2.4
+ sensor.c (ipmiutil sensor) ver 2.4
+ showsel.c (ipmiutil sel) ver 1.58
+ tmconfig.c (ipmiutil serial) ver 1.47
+ wdt.c (ipmiutil wdt) ver 1.34
+ isolconsole.c (ipmiutil sol) ver 2.4
+ idiscover.c (ipmiutil discover) ver 1.2
+ ipmi_port.c (ipmi_port) ver 0.5
+
+12/17/07 ARCress ipmiutil-2.0.5 changes
+ doc/events.8 - new, documents the events utility
+ doc/ipmiutil.spec - add events.8
+ doc/Makefile - add events.8
+ util/alarms.c - do not try disk enclosure LEDs if ipmi_lan,
+ add "disk " to slot LED output.
+ util/bmchealth.c - added Aelita Software to manuf ids
+ util/bmchealth.c - added Chassis Status
+ util/events.c - additional usage text for -p, fix -p timestamp uchar,
+ handle PET temp ok events
+ util/pefconfig.c - add -g (2nd Gateway IP), -k (add PEF OK rules)
+ util/getevent.c - fixes for getevent -s with -N
+ ipmiutil-2.0.5 contains:
+ ipmiutil.c (ipmiutil) ver 2.5
+ alarms.c (ipmiutil alarms) ver 2.5
+ bmchealth.c (ipmiutil health) ver 2.5
+ fruconfig.c (ipmiutil fru) ver 1.43
+ getevent.c (ipmiutil getevt) ver 2.5
+ hwreset.c (ipmiutil reset) ver 2.5
+ icmd.c (ipmiutil cmd) ver 1.31
+ pefconfig.c (ipmiutil lan) ver 2.5
+ sensor.c (ipmiutil sensor) ver 2.5
+ showsel.c (ipmiutil sel) ver 1.59
+ tmconfig.c (ipmiutil serial) ver 1.48
+ wdt.c (ipmiutil wdt) ver 1.35
+ isolconsole.c (ipmiutil sol) ver 2.5
+ idiscover.c (ipmiutil discover) ver 1.2
+ ipmi_port.c (ipmi_port) ver 1.0
+ events.c (ievents) ver 2.5
+
+01/21/08 ARCress ipmiutil-2.0.6 changes
+ util/ipmicmd.c - added lan2i driver type for -F param
+ util/ipmilanplus.c - show more oem_active debug
+ util/sensor.c - added -u for unique sensor threshold values,
+ always show float when setting thresholds,
+ fixup in decoding Proc,PS Comp readings
+ util/events.c - fixed 0f/06 POST Code interpretation (Min Zhang),
+ fixed 07 interpretation if not Processor Status.
+ util/ipmidir.c - more DBG messages
+ ipmiutil-2.0.6 contains:
+ ipmiutil.c (ipmiutil) ver 2.6
+ alarms.c (ipmiutil alarms) ver 2.6
+ bmchealth.c (ipmiutil health) ver 2.6
+ fruconfig.c (ipmiutil fru) ver 1.44
+ getevent.c (ipmiutil getevt) ver 2.6
+ hwreset.c (ipmiutil reset) ver 2.6
+ icmd.c (ipmiutil cmd) ver 1.32
+ pefconfig.c (ipmiutil lan) ver 2.6
+ sensor.c (ipmiutil sensor) ver 2.6
+ showsel.c (ipmiutil sel) ver 1.60
+ tmconfig.c (ipmiutil serial) ver 1.49
+ wdt.c (ipmiutil wdt) ver 1.36
+ isolconsole.c (ipmiutil sol) ver 2.6
+ idiscover.c (ipmiutil discover) ver 1.2
+ ipmi_port.c (ipmi_port) ver 1.0
+ events.c (ievents) ver 2.6
+
+02/01/08 ARCress ipmiutil-2.0.7 changes
+ util/sensor.c - allow float input for -u thresholds,
+ handle -p with -u,
+ fix CPU Thermal reading if evtype==3
+ show updated volatile thresholds if -t,-v
+ doc/UserGuide - add section 1.1, update man pages
+ doc/sensor.8 - add -u float description
+ doc/ipmi_port.sh - also auto-restore any saved thresholds
+ ipmiutil-2.0.7 contains:
+ ipmiutil.c (ipmiutil) ver 2.7
+ alarms.c (ipmiutil alarms) ver 2.7
+ bmchealth.c (ipmiutil health) ver 2.7
+ fruconfig.c (ipmiutil fru) ver 1.45
+ getevent.c (ipmiutil getevt) ver 2.7
+ hwreset.c (ipmiutil reset) ver 2.7
+ icmd.c (ipmiutil cmd) ver 1.33
+ pefconfig.c (ipmiutil lan) ver 2.7
+ sensor.c (ipmiutil sensor) ver 2.7
+ showsel.c (ipmiutil sel) ver 1.61
+ tmconfig.c (ipmiutil serial) ver 1.50
+ wdt.c (ipmiutil wdt) ver 1.37
+ isolconsole.c (ipmiutil sol) ver 2.7
+ idiscover.c (ipmiutil discover) ver 1.2
+ ipmi_port.c (ipmi_port) ver 1.0
+ events.c (ievents) ver 2.7
+
+02/28/08 ARCress ipmiutil-2.0.8 changes
+ configure.in - add enable-standalone for boot media builds
+ util/showsel.c - make sure savid is unsigned for -w
+ util/fruconfig.c - WriteAsset size 128 -> 259 (Min Zhang)
+ util/imbapi.c - added skeleton DllMain()
+ util/showsel.c - add -r for raw hex bytes
+ doc/showsel.8 - add -r for raw hex bytes
+ lib/lanplus/lanplus_crypt_impl.c - debug for issue with d:\.rnd
+ ipmiutil-2.0.8 contains:
+ ipmiutil.c (ipmiutil) ver 2.8
+ alarms.c (ipmiutil alarms) ver 2.8
+ bmchealth.c (ipmiutil health) ver 2.8
+ fruconfig.c (ipmiutil fru) ver 1.46
+ getevent.c (ipmiutil getevt) ver 2.8
+ hwreset.c (ipmiutil reset) ver 2.8
+ icmd.c (ipmiutil cmd) ver 1.34
+ pefconfig.c (ipmiutil lan) ver 2.8
+ sensor.c (ipmiutil sensor) ver 2.8
+ showsel.c (ipmiutil sel) ver 2.8
+ tmconfig.c (ipmiutil serial) ver 1.51
+ wdt.c (ipmiutil wdt) ver 1.38
+ isolconsole.c (ipmiutil sol) ver 2.8
+ idiscover.c (ipmiutil discover) ver 1.2
+ ipmi_port.c (ipmi_port) ver 1.0
+ events.c (ievents) ver 2.8
+
+03/20/08 ARCress ipmiutil-2.0.9 changes
+ util/events.c - add -f to interpret raw SEL file,
+ handle OEM sens_type 0xF3 as SMI Timeout
+ util/sensor.c - interpret more type 0x0D HSC states
+ util/imbapi.c - fix for SendTimedLan(IpmiVersion) if IPMI 2.0
+ util/getevent.c - more debug messages for -a (imb mode)
+ doc/events.8 - document -f option
+ doc/UserGuide - updated with new man pages
+ ipmiutil-2.0.9 contains:
+ ipmiutil.c (ipmiutil) ver 2.9
+ alarms.c (ipmiutil alarms) ver 2.9
+ bmchealth.c (ipmiutil health) ver 2.9
+ fruconfig.c (ipmiutil fru) ver 1.47
+ getevent.c (ipmiutil getevt) ver 2.9
+ hwreset.c (ipmiutil reset) ver 2.9
+ icmd.c (ipmiutil cmd) ver 1.35
+ pefconfig.c (ipmiutil lan) ver 2.9
+ sensor.c (ipmiutil sensor) ver 2.9
+ showsel.c (ipmiutil sel) ver 2.9
+ tmconfig.c (ipmiutil serial) ver 1.52
+ wdt.c (ipmiutil wdt) ver 1.39
+ isolconsole.c (ipmiutil sol) ver 2.9
+ idiscover.c (ipmiutil discover) ver 1.2
+ ipmi_port.c (ipmi_port) ver 1.0
+ events.c (ievents) ver 2.9
+
+
+03/31/08 ARCress ipmiutil-2.1.0 changes
+ util/imbapi.c - decreased TIMEOUT
+ util/ipmiia.c - decreased TIMEOUT
+ util/pefconfig.c - warning if -I without -e
+ util/Makefile.am - only build ipmiutil, eliminate dups
+ doc/Makefile - copy scripts for dup utilities
+ doc/alarms doc/bmchealth doc/fruconfig - created scripts
+ doc/getevent doc/hwreset doc/icmd - created scripts
+ doc/isolconsole doc/pefconfig doc/sensor - created scripts
+ doc/showsel doc/tmconfig doc/wdt - created scripts
+ ipmiutil-2.1.0 contains:
+ ipmiutil.c (ipmiutil) ver 2.10
+ alarms.c (ipmiutil alarms) ver 2.10
+ bmchealth.c (ipmiutil health) ver 2.10
+ fruconfig.c (ipmiutil fru) ver 2.10
+ getevent.c (ipmiutil getevt) ver 2.10
+ hwreset.c (ipmiutil reset) ver 2.10
+ icmd.c (ipmiutil cmd) ver 2.10
+ pefconfig.c (ipmiutil lan) ver 2.10
+ sensor.c (ipmiutil sensor) ver 2.10
+ showsel.c (ipmiutil sel) ver 2.10
+ tmconfig.c (ipmiutil serial) ver 2.10
+ wdt.c (ipmiutil wdt) ver 2.10
+ isolconsole.c (ipmiutil sol) ver 2.10
+ idiscover.c (ipmiutil discover) ver 1.2
+ ipmi_port.c (ipmi_port) ver 1.0
+ events.c (ievents) ver 2.10
+
+04/25/08 ARCress ipmiutil-2.1.1 changes
+ util/*.c - add case 'J': for cipher suite option
+ doc/*.8 - add -J description to man pages
+ doc/UserGuide - update man pages in UserGuide
+ util/Makefile.am - subst gcc->$(CC)
+ util/alarms.c - if not TAM baseboard, skip no-alarm-panel msg
+ lib/lanplus/Makefile.am - subst gcc->$(CC)
+ lib/lanplus/lanplus.c - patch rsp len for dup output
+ lib/lanplus/lanplus.h - IMPI -> IPMI
+ lib/lanplus/helper.c - support fplog for printbuf if STATIC
+ lib/lanplus/inc/ipmitool/ipmi_intf.h - added transit_addr, devnum
+ lib/lanplus/Makefile.am - patch from tizianomueller for bug 1948890
+ util/ipmilanplus.c - ditto
+ util/ipmi_port.c - ditto
+ util/Makefile.am - ditto
+ util/Makefile.am-all - ditto
+ util/ipmilanplus.c - set SOL data timeout=2 for early retry issue,
+ lprintf changes for logging
+ util/isolconsole.c - more dbglog msgs for Linux with -z,
+ fix lost SOL RX packet with keepalive
+ util/ipmicmd.c - fix showsel -w openlog bug 1951680 (checksel)
+ ipmiutil-2.1.1 contains:
+ ipmiutil.c (ipmiutil) ver 2.11
+ alarms.c (ipmiutil alarms) ver 2.11
+ bmchealth.c (ipmiutil health) ver 2.11
+ fruconfig.c (ipmiutil fru) ver 2.11
+ getevent.c (ipmiutil getevt) ver 2.11
+ hwreset.c (ipmiutil reset) ver 2.11
+ icmd.c (ipmiutil cmd) ver 2.11
+ pefconfig.c (ipmiutil lan) ver 2.11
+ sensor.c (ipmiutil sensor) ver 2.11
+ showsel.c (ipmiutil sel) ver 2.11
+ tmconfig.c (ipmiutil serial) ver 2.11
+ wdt.c (ipmiutil wdt) ver 2.11
+ isolconsole.c (ipmiutil sol) ver 2.11
+ idiscover.c (ipmiutil discover) ver 1.2
+ ipmi_port.c (ipmi_port) ver 1.0
+ events.c (ievents) ver 2.11
+
+06/24/08 ARCress ipmiutil-2.1.2 changes
+ util/ipmilanplus.c - change debug lprintfs fro LOG_WARN to LOG_INFO,
+ fix crash in sol lprintf if send_sol fails,
+ set rsp->len = 0 in sol routines if error.
+ util/isolwin.c - fix white-on-white chars for BIOS setup
+ util/events.c - fix message output for -r, -p
+ ipmiutil-2.1.2 contains:
+ ipmiutil.c (ipmiutil) ver 2.12
+ alarms.c (ipmiutil alarms) ver 2.12
+ bmchealth.c (ipmiutil health) ver 2.12
+ fruconfig.c (ipmiutil fru) ver 2.12
+ getevent.c (ipmiutil getevt) ver 2.12
+ hwreset.c (ipmiutil reset) ver 2.12
+ icmd.c (ipmiutil cmd) ver 2.12
+ pefconfig.c (ipmiutil lan) ver 2.12
+ sensor.c (ipmiutil sensor) ver 2.12
+ showsel.c (ipmiutil sel) ver 2.12
+ tmconfig.c (ipmiutil serial) ver 2.12
+ wdt.c (ipmiutil wdt) ver 2.12
+ isolconsole.c (ipmiutil sol) ver 2.12
+ idiscover.c (ipmiutil discover) ver 1.2
+ ipmi_port.c (ipmi_port) ver 1.0
+ events.c (ievents) ver 2.12
+
+07/31/08 ARCress ipmiutil-2.1.3 changes
+ util/isolwin.c - handle more esc sequences, add FG_WHITE_LO if mode=0
+ util/isolconsole.c - handle receive packets from keepalive
+ util/ipmilanplus.c - check for receive packets in lan2_keepalive also
+ util/wdt.c - add -p for preaction, set pretime = time/2,
+ pass set/reset status to completion,
+ check reset if ret==0xc0(192) node busy
+ util/imbapi.c - add set_fps() for fpdbg if -Fimb
+ util/idiscover.c - add -r for repeat pings to each node
+ util/pefconfig.c - allow setting lan params remotely if using diff channel,
+ show SOL Payload Access for all 4 users,
+ show ':' before interpreted strings
+ util/tmconfig.c - show ':' before interpreted strings
+ util/bmchealth.c - added Bull, PigeonPt IANA numbers
+ util/sensor.c - allow -i to specify a range of sensors
+ util/ipmi_port.c - skip hello message if background
+ util/events.c - mystr[26] -> [50] for long ACPI messages
+ util/showsel.c - "SEL: :" -> "SEL:" with -w
+ util/ipmidir.c - check for invalid receive data length from BMC
+ util/ipmilan.c - ipmi_cmd_ipmb: increase get_message loop from 5 to 10ms,
+ check for receive buffer overflow (e.g. 180 bytes)
+ util/icmd.c - allow receive size up to 200 bytes
+ lib/lanplus/asf.h - __attribute__((packed)); -> #pragma pack(1) for gcc 4.3
+ lib/lanplus/rmcp.h - __attribute__((packed)); -> #pragma pack(1)
+ doc/bmclanpet.mib - fix mib compile issues on line 52 and 87
+ doc/wdt.8 - add -p for preaction
+ doc/sensor.8 - add -i and -L descriptions
+ doc/checksel - bash -> sh for bug 2032210
+ doc/ipmi_port.sh - bash -> sh, patch from Paul D Smith
+ doc/wdt.sh - bash -> sh
+ doc/UserGuide - updated man page text
+ hpiutil/hpiinit.sh - bash -> sh
+ ipmiutil-2.1.3 contains:
+ ipmiutil.c (ipmiutil) ver 2.13
+ alarms.c (ipmiutil alarms) ver 2.13
+ bmchealth.c (ipmiutil health) ver 2.13
+ fruconfig.c (ipmiutil fru) ver 2.13
+ getevent.c (ipmiutil getevt) ver 2.13
+ hwreset.c (ipmiutil reset) ver 2.13
+ icmd.c (ipmiutil cmd) ver 2.13
+ pefconfig.c (ipmiutil lan) ver 2.13
+ sensor.c (ipmiutil sensor) ver 2.13
+ showsel.c (ipmiutil sel) ver 2.13
+ tmconfig.c (ipmiutil serial) ver 2.13
+ wdt.c (ipmiutil wdt) ver 2.13
+ isolconsole.c (ipmiutil sol) ver 2.13
+ idiscover.c (ipmiutil discover) ver 1.3
+ ipmi_port.c (ipmi_port) ver 1.1
+ events.c (ievents) ver 2.13
+
+08/25/08 ARCress ipmiutil-2.2.0 changes
+ util/icmd.c - add -q for quiet mode
+ util/isolwin.c - add translation for graphic arrow keys,
+ add more set attrib esc sequences
+ util/pefconfig.c - add -o to just disable SOL,
+ add -v for access priv (admin/oper/user),
+ added case for NSN2U
+ util/tmconfig.c - add -e for TMode without console,
+ add -v for access priv (admin/oper/user)
+ util/getevent.c - call iclose() before any exit();
+ util/hwreset.c - do ipmi_close_ if soft-reset
+ util/ipmilan.c - add ALLOW_GPL flag for MD2OK
+ util/ipmilan2.c - add ALLOW_GPL flag for MD2OK
+ util/ipmiva.c - moved _va routines to ipmiva.h, only stubs here,
+ add ALLOW_GPL flag for VAOK
+ util/ipmiva.h - new, contains _va routines
+ util/md2.c - moved md2 routines from here to md2.h
+ util/md2.h - new, contains md2 routines
+ util/mem_if.c - new, to get_BiosVersion
+ util/bmcconfig.c - new, to save/restore bmc configuration
+ util/bmchealth.c - added case for NSN2U
+ util/events.c - added fan redundancy interpretation
+ util/sensor.c - added cases for other discrete temp sensors,
+ handle full sensor readings in init state.
+ util/Makefile.am - added mem_if, bmcconfig,
+ fixed libipmiutil.a build
+ configure.in - add --enable-gpl/ALLOW_GPL (default=no)
+ INSTALL - document configure option changes
+ doc/bmclanpet.mib - PetEvts->petevts for some mib compilers, Trap->trap
+ doc/bmcconfig.8 - new
+ ipmiutil-2.2.0 contains:
+ ipmiutil.c (ipmiutil) ver 2.20
+ alarms.c (ipmiutil alarms) ver 2.20
+ bmchealth.c (ipmiutil health) ver 2.20
+ fruconfig.c (ipmiutil fru) ver 2.20
+ getevent.c (ipmiutil getevt) ver 2.20
+ hwreset.c (ipmiutil reset) ver 2.20
+ icmd.c (ipmiutil cmd) ver 2.20
+ pefconfig.c (ipmiutil lan) ver 2.20
+ sensor.c (ipmiutil sensor) ver 2.20
+ showsel.c (ipmiutil sel) ver 2.20
+ tmconfig.c (ipmiutil serial) ver 2.20
+ wdt.c (ipmiutil wdt) ver 2.20
+ isolconsole.c (ipmiutil sol) ver 2.20
+ bmcconfig.c (ipmiutil config) ver 1.0
+ idiscover.c (ipmiutil discover) ver 1.3
+ ipmi_port.c (ipmi_port) ver 1.1
+ events.c (ievents) ver 2.20
+
+09/15/08 ARCress ipmiutil-2.2.1 changes
+ doc/ipmi_if.sh - reuse dmidecode output rather than repeat calls
+ util/ipmilanplus.c - for no LANPLUS, still need 2 global vars
+ util/ipmiutil.mak - added VCLIB_ADD, VCINCL_ADD,
+ added LIBS_W, mem_if.exe, ipmims.obj
+ util/mem_if.c - added smbios code for WIN32
+ util/getevent.c - continue even if set_bmc_enables fails,
+ add code for openipmi async cmds (remote soft reset).
+ util/events.c - added more type 1D & 20 decoding from IPMI 2.0 E3 spec,
+ if fPET, do not show reading on sensor line.
+ util/ipmimv.c - add setmaint_mv() routine, add register routines,
+ mods to getevent_mv for other recv_types
+ util/sensor.c - added EvLog(0x10) sensor type decoding,
+ Show EventType for Full & Comp SDRs (instead of Sz).
+ util/ipmims.c - new, for MS IPMI driver support
+ util/isolwin.c - detect BIOS Setup via background for CR handling,
+ only set fg intensity instead of fg/bg for mode 1,
+ move arrow/function key handling to console_in
+ util/isolconsole.c - move arrow/function key handling to console_in
+ util/wdt.c - change pretimeout from half to 90% of timeout
+ util/alarms.c - enhanced BMC TAM detection
+ util/Makefile.am - fix lib if condition for no lanplus,
+ add strip to install, added ipmims.o
+ doc/icmd.8 - added -q description
+ doc/pefconfig.8 - added -o -v descriptions
+ doc/tmconfig.8 - added -e -v descriptions
+ doc/sensor.8 - added output columns explanation
+ doc/wdt.8 - change pretimeout from half to 90% of timeout
+ doc/UserGuide - updated man pages, added sample output section,
+ documented MS IPMI driver support
+ lib/lanplus/ipmiplus.mak - added VCLIB_ADD, VCINCL_ADD
+ buildwin.cmd - added more comments about VS8, added VC*_ADD
+ ipmiutil-2.2.1 contains:
+ ipmiutil.c (ipmiutil) ver 2.21
+ alarms.c (ipmiutil alarms) ver 2.21
+ bmchealth.c (ipmiutil health) ver 2.21
+ fruconfig.c (ipmiutil fru) ver 2.21
+ getevent.c (ipmiutil getevt) ver 2.21
+ hwreset.c (ipmiutil reset) ver 2.21
+ icmd.c (ipmiutil cmd) ver 2.21
+ pefconfig.c (ipmiutil lan) ver 2.21
+ sensor.c (ipmiutil sensor) ver 2.21
+ showsel.c (ipmiutil sel) ver 2.21
+ tmconfig.c (ipmiutil serial) ver 2.21
+ wdt.c (ipmiutil wdt) ver 2.21
+ isolconsole.c (ipmiutil sol) ver 2.21
+ bmcconfig.c (ipmiutil config) ver 1.1
+ idiscover.c (ipmiutil discover) ver 1.3
+ ipmi_port.c (ipmi_port) ver 1.1
+ events.c (ievents) ver 2.21
+
+09/19/08 ARCress ipmiutil-2.2.2 changes
+ util/pefconfig.c - readonly warning if options but no -e,
+ set BMC IP to 0.0.0.0 if -d,
+ fix bug with trap2sink parsing,
+ if mac unresolved, show warning, but dont set it
+ util/isolconsole.c - add -i -o options
+ doc/isolconsole.8 - describe -i -o options
+ doc/UserGuide - updated isolconsole man page
+ ipmiutil-2.2.2 contains:
+ ipmiutil.c (ipmiutil) ver 2.22
+ alarms.c (ipmiutil alarms) ver 2.22
+ bmchealth.c (ipmiutil health) ver 2.22
+ fruconfig.c (ipmiutil fru) ver 2.22
+ getevent.c (ipmiutil getevt) ver 2.22
+ hwreset.c (ipmiutil reset) ver 2.22
+ icmd.c (ipmiutil cmd) ver 2.22
+ pefconfig.c (ipmiutil lan) ver 2.22
+ sensor.c (ipmiutil sensor) ver 2.22
+ showsel.c (ipmiutil sel) ver 2.22
+ tmconfig.c (ipmiutil serial) ver 2.22
+ wdt.c (ipmiutil wdt) ver 2.22
+ isolconsole.c (ipmiutil sol) ver 2.22
+ bmcconfig.c (ipmiutil config) ver 1.2
+ idiscover.c (ipmiutil discover) ver 1.3
+ ipmi_port.c (ipmi_port) ver 1.1
+ events.c (ievents) ver 2.22
+
+10/06/08 ARCress ipmiutil-2.2.3 changes
+ util/isolconsole.c - fix abort on Linux F10
+ util/bmchealth.c - use chan 1 for auth if NSN2U
+ util/mem_if.c - cosmetic reuse mods
+ util/showsel.c - get Windows ipmiutildir path if -w
+ util/events.c - fix decoding for OEM events betw c0 & e0
+ doc/bmclanpet.mib - add PowerUnitRedundancy PET OIDs
+ doc/UserGuide - updates to Intro sections
+ doc/showsel.reg - added scheduler time for checksel.cmd
+ doc/install.cmd - new, install script for Windows
+ doc/checksel.cmd - new, checksel at script for Windows
+ INSTALL - updated info about --enable-gpl
+ README - updated info about --enable-gpl
+ ipmiutil-2.2.3 contains:
+ ipmiutil.c (ipmiutil) ver 2.23
+ alarms.c (ipmiutil alarms) ver 2.23
+ bmchealth.c (ipmiutil health) ver 2.23
+ fruconfig.c (ipmiutil fru) ver 2.23
+ getevent.c (ipmiutil getevt) ver 2.23
+ hwreset.c (ipmiutil reset) ver 2.23
+ icmd.c (ipmiutil cmd) ver 2.23
+ pefconfig.c (ipmiutil lan) ver 2.23
+ sensor.c (ipmiutil sensor) ver 2.23
+ showsel.c (ipmiutil sel) ver 2.23
+ tmconfig.c (ipmiutil serial) ver 2.23
+ wdt.c (ipmiutil wdt) ver 2.23
+ isolconsole.c (ipmiutil sol) ver 2.23
+ bmcconfig.c (ipmiutil config) ver 1.3
+ idiscover.c (ipmiutil discover) ver 1.3
+ ipmi_port.c (ipmi_port) ver 1.1
+ events.c (ievents) ver 2.23
+
+10/27/08 ARCress ipmiutil-2.2.4 changes
+ util/fruconfig.c - fixed segfault with -a due to early free_fru
+ this bug was introduced in 2.2.1, worked before.
+ also fixed write_asset if multi-record area present.
+ doc/UserGuide - added page breaks (FormFeeds) for printing
+ ipmiutil-2.2.4 contains:
+ ipmiutil.c (ipmiutil) ver 2.24
+ alarms.c (ipmiutil alarms) ver 2.24
+ bmchealth.c (ipmiutil health) ver 2.24
+ fruconfig.c (ipmiutil fru) ver 2.24
+ getevent.c (ipmiutil getevt) ver 2.24
+ hwreset.c (ipmiutil reset) ver 2.24
+ icmd.c (ipmiutil cmd) ver 2.24
+ pefconfig.c (ipmiutil lan) ver 2.24
+ sensor.c (ipmiutil sensor) ver 2.24
+ showsel.c (ipmiutil sel) ver 2.24
+ tmconfig.c (ipmiutil serial) ver 2.24
+ wdt.c (ipmiutil wdt) ver 2.24
+ isolconsole.c (ipmiutil sol) ver 2.24
+ bmcconfig.c (ipmiutil config) ver 2.24
+ idiscover.c (ipmiutil discover) ver 1.3
+ ipmi_port.c (ipmi_port) ver 1.1
+ events.c (ievents) ver 2.24
+
+11/14/08 ARCress ipmiutil-2.3.0 changes
+ util/sensor.c - handle minutes-per-count for FSC POH
+ util/events.c - decode Fan Absent event (trg=88 d1=01)
+ util/md2.c - add md2 from libcrypto if HAVE_LANPLUS
+ util/ipmilan.c - set MD2OK if HAVE_LANPLUS
+ util/bmchealth.c - get_chassis_status error message change,
+ use common error return point
+ util/ipmicmd.h - move ACCESS_OK out of ifdef, add DRV_BMC
+ util/ipmidir.c - use meaningful return codes
+ INSTALL - added Solaris notes
+ configure.in - added Solaris/SunOS changes
+ lib/lanplus/lanplus.c - add SOLARIS ifdefs
+ util/Makefile.am - added Solaris changes
+ util/ipmibmc.c - new, for Solaris 10 bmc driver
+ util/bmcconfig.c - add SOLARIS ifdefs
+ util/getevent.c - add SOLARIS ifdefs
+ util/idiscover.c - add SOLARIS ifdefs
+ util/ipmicmd.c - add SOLARIS ifdefs
+ util/ipmilan2.c - add SOLARIS ifdefs
+ util/ipmilan.c - add SOLARIS ifdefs
+ util/ipmilanplus.c - add SOLARIS ifdefs
+ util/mem_if.c - add SOLARIS ifdefs
+ util/pefconfig.c - add SOLARIS ifdefs
+ util/imbapi.c - add ifndef SOLARIS for safety
+ util/ipmi*.c - add ifdef LINUX for safety
+ ipmiutil-2.3.0 contains:
+ ipmiutil.c (ipmiutil) ver 2.30
+ alarms.c (ipmiutil alarms) ver 2.30
+ bmchealth.c (ipmiutil health) ver 2.30
+ fruconfig.c (ipmiutil fru) ver 2.30
+ getevent.c (ipmiutil getevt) ver 2.30
+ hwreset.c (ipmiutil reset) ver 2.30
+ icmd.c (ipmiutil cmd) ver 2.30
+ pefconfig.c (ipmiutil lan) ver 2.30
+ sensor.c (ipmiutil sensor) ver 2.30
+ showsel.c (ipmiutil sel) ver 2.30
+ tmconfig.c (ipmiutil serial) ver 2.30
+ wdt.c (ipmiutil wdt) ver 2.30
+ isolconsole.c (ipmiutil sol) ver 2.30
+ bmcconfig.c (ipmiutil config) ver 2.30
+ idiscover.c (ipmiutil discover) ver 1.4
+ ipmi_port.c (ipmi_port) ver 1.1
+ events.c (ievents) ver 2.30
+
+12/02/08 ARCress ipmiutil-2.3.1 changes
+ util/bmchealth.c - add ClearBay id, move to get_mfg_str()
+ util/events.c - add -h hex option, NM event decoding
+ util/sensor.c - add -g for sensor type groups,
+ change -h/-l to set noncrit first, then crit,nonrec,
+ add etype 03 to Discrete Thermal sensor decoding
+ util/pefconfig.c - skip error message if setting BMC MAC not allowed
+ util/bmcconfig.c - set ndest again from Serial param 16
+ util/idiscover.c - init fpdbg if METACOMMAND and -x (#2339334),
+ find first enabled eth interface,
+ use eth intf ip for broadcast by default,
+ check if broadcast ip is invalid,
+ show progress if not broadcast.
+ util/ipmicmd.c - check fpdbg in dump_buf()
+ util/imbapi.c - added more fdebug messages for Emp/Lan
+ util/isolwin.c - handle screen mode escape sequences
+ util/getevent.c - add error message if wrong async cmd,
+ handle shorter async format from some BMCs.
+ doc/ipmiutil.spec - copy wdt.sh, asy.sh to /etc/init.d
+ doc/Makefile - add asy.sh to install
+ doc/idiscover.8 - document detection changes
+ doc/getevent.8 - document asy.sh (ipmiutil_asy)
+ doc/wdt.8 - edit info about wdt.sh (ipmiutil_wdt)
+ doc/events.8 - document -h option
+ doc/sensor.8 - document -g option
+ doc/bmcconfig.8 - added info about editing UserPassword records
+ doc/UserGuide - man page updates
+ doc/asy.sh - new, init script for getevt -a
+ cleanwin.cmd - new, clean windows binaries
+ buildwin2.cmd - new, alt build for standalone/bootable wo lanplus
+ util/ipmiutil2.mak - new, alt build for standalone/bootable wo lanplus
+ ipmiutil-2.3.1 contains:
+ ipmiutil.c (ipmiutil) ver 2.31
+ alarms.c (ipmiutil alarms) ver 2.31
+ bmchealth.c (ipmiutil health) ver 2.31
+ fruconfig.c (ipmiutil fru) ver 2.31
+ getevent.c (ipmiutil getevt) ver 2.31
+ hwreset.c (ipmiutil reset) ver 2.31
+ icmd.c (ipmiutil cmd) ver 2.31
+ pefconfig.c (ipmiutil lan) ver 2.31
+ sensor.c (ipmiutil sensor) ver 2.31
+ showsel.c (ipmiutil sel) ver 2.31
+ tmconfig.c (ipmiutil serial) ver 2.31
+ wdt.c (ipmiutil wdt) ver 2.31
+ isolconsole.c (ipmiutil sol) ver 2.31
+ bmcconfig.c (ipmiutil config) ver 2.31
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+ events.c (ievents) ver 2.31
+
+12/08/08 ARCress ipmiutil-2.3.2 changes
+ util/bmchealth.c - add Tyan product id logic,
+ add last selftest status if error,
+ show IPMI driver type
+ util/pefconfig.c - debug messages for -t,
+ better warning for no -e option
+ util/sensor.c - fix for setting thresholds if sens_num matches
+ on more than one slave_addr (TAO 2125)
+ util/Makefile.am - add $(extradir)
+ doc/ipmiutil.spec - mods for Fedora compliance
+ doc/ipmi_if.sh - add #!/bin/sh
+ doc/ipmi_port.sh - add $progdir
+ lib/lanplus/lanplus.c - patch to ipmi_req_remove_entry()
+ ipmiutil-2.3.2 contains:
+ ipmiutil.c (ipmiutil) ver 2.32
+ alarms.c (ipmiutil alarms) ver 2.32
+ bmchealth.c (ipmiutil health) ver 2.32
+ fruconfig.c (ipmiutil fru) ver 2.32
+ getevent.c (ipmiutil getevt) ver 2.32
+ hwreset.c (ipmiutil reset) ver 2.32
+ icmd.c (ipmiutil cmd) ver 2.32
+ pefconfig.c (ipmiutil lan) ver 2.32
+ sensor.c (ipmiutil sensor) ver 2.32
+ showsel.c (ipmiutil sel) ver 2.32
+ tmconfig.c (ipmiutil serial) ver 2.32
+ wdt.c (ipmiutil wdt) ver 2.32
+ isolconsole.c (ipmiutil sol) ver 2.32
+ bmcconfig.c (ipmiutil config) ver 2.32
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+ events.c (ievents) ver 2.32
+
+01/09/09 ARCress ipmiutil-2.3.3 changes
+ util/pefconfig.c - add Voltage Ok PEF rule to -k, swap PEF7/8 descriptions
+ util/events.c - add voltage ok decoding to -p
+ doc/ipmiutil.spec - fix broken %_mandir with MV4
+ ipmiutil-2.3.3 contains:
+ ipmiutil.c (ipmiutil) ver 2.33
+ alarms.c (ipmiutil alarms) ver 2.33
+ bmchealth.c (ipmiutil health) ver 2.33
+ fruconfig.c (ipmiutil fru) ver 2.33
+ getevent.c (ipmiutil getevt) ver 2.33
+ hwreset.c (ipmiutil reset) ver 2.33
+ icmd.c (ipmiutil cmd) ver 2.33
+ pefconfig.c (ipmiutil lan) ver 2.33
+ sensor.c (ipmiutil sensor) ver 2.33
+ showsel.c (ipmiutil sel) ver 2.33
+ tmconfig.c (ipmiutil serial) ver 2.33
+ wdt.c (ipmiutil wdt) ver 2.33
+ isolconsole.c (ipmiutil sol) ver 2.33
+ bmcconfig.c (ipmiutil config) ver 2.33
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+ events.c (ievents) ver 2.33
+
+02/25/09 ARCress ipmiutil-2.3.4 changes
+ configure.in - For SunOS substitution, add space after -lnsl
+ INSTALL - Solaris idiscover note
+ util/idiscover.c - fix Solaris e1000g? loop
+ util/bmchealth.c - comment about Power State 2a (unknown)
+ util/pefconfig.c - fix FindEthNum, GetIPMac for Solaris,
+ show max_users, enabled_users
+ util/tmconfig.c - show max_users, enabled_users
+ util/bmcconfig.c - set nusers = max_users
+ COPYING - added Copyright 2009 Kontron
+ util/*.c,*.h - added Copyright 2009 Kontron
+ doc/*.8 - added Copyright 2009 Kontron
+ lib/lanplus/helper.c - printbuf to stdout (was stderr)
+ lib/lanplus/lanplus.c - add bridging patches from Mirko Klefker
+ util/ipmilanplus.c - bridging patch
+ util/ipmicmd.c - bridging patch to ipmi_cmd_mc
+ util/ipmilan.c - by default, dont send ping,
+ handle bridged requests for non-BMC addrs
+ util/sensor.c - enable lan bridging for HSC sensor readings
+ util/alarms.c - enable lan bridging for HSC disk LEDs
+ util/ipmiutil.c - add events as a subcommand
+ util/ipmiutil.h - add i_events as a subroutine
+ util/bmchealth.c - more debug for get_last_selftest
+ util/events.c - handle PET threshold trap end cases,
+ handle discrete temp events,
+ handle i_events from ipmiutil metacommand
+ doc/events.8 - add -r (same as -h) with example
+ doc/UserGuide - added 4.10 How to configure IPMI PET SNMP
+ doc/alarms.cmd - new, invoke ipmiutil.exe instead
+ doc/bmcconfig.cmd - new, invoke ipmiutil.exe instead
+ doc/bmchealth.cmd - new, invoke ipmiutil.exe instead
+ doc/fruconfig.cmd - new, invoke ipmiutil.exe instead
+ doc/getevent.cmd - new, invoke ipmiutil.exe instead
+ doc/hwreset.cmd - new, invoke ipmiutil.exe instead
+ doc/icmd.cmd - new, invoke ipmiutil.exe instead
+ doc/idiscover.cmd - new, invoke ipmiutil.exe instead
+ doc/isolconsole.cmd - new, invoke ipmiutil.exe instead
+ doc/pefconfig.cmd - new, invoke ipmiutil.exe instead
+ doc/sensor.cmd - new, invoke ipmiutil.exe instead
+ doc/showsel.cmd - new, invoke ipmiutil.exe instead
+ doc/tmconfig.cmd - new, invoke ipmiutil.exe instead
+ doc/wdt.cmd - new, invoke ipmiutil.exe instead
+ ipmiutil-2.3.4 contains:
+ ipmiutil.c (ipmiutil) ver 2.34
+ alarms.c (ipmiutil alarms) ver 2.34
+ bmchealth.c (ipmiutil health) ver 2.34
+ fruconfig.c (ipmiutil fru) ver 2.34
+ getevent.c (ipmiutil getevt) ver 2.34
+ hwreset.c (ipmiutil reset) ver 2.34
+ icmd.c (ipmiutil cmd) ver 2.34
+ pefconfig.c (ipmiutil lan) ver 2.34
+ sensor.c (ipmiutil sensor) ver 2.34
+ showsel.c (ipmiutil sel) ver 2.34
+ tmconfig.c (ipmiutil serial) ver 2.34
+ wdt.c (ipmiutil wdt) ver 2.34
+ isolconsole.c (ipmiutil sol) ver 2.34
+ bmcconfig.c (ipmiutil config) ver 2.34
+ events.c (ipmiutil events) ver 2.34
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+
+03/30/09 ARCress ipmiutil-2.3.5 changes
+ util/bmchealth.c - add GetPowerOnHours, skip get_power_state if HP.
+ util/sensor.c - rename GetPowerOnHours as ShowPowerOnHours
+ util/ipmilan.c - some fixes for SOL 1.5 data
+ util/pefconfig.c - clear gateway IP/MAC when fdisable with -d
+ util/events.c - decode EFI System Events too
+ configure.in - FreeBSD mods
+ lib/Makefile - FreeBSD mods
+ lib/lanplus/Makefile.am - FreeBSD mods
+ util/bmcconfig.c - FreeBSD mods
+ util/getevent.c - FreeBSD mods
+ util/imbapi.c - FreeBSD mods
+ util/ipmicmd.c - FreeBSD mods
+ util/mem_if.c - FreeBSD mods, detect IPMI register spacing via SMBIOS
+ util/pefconfig.c - FreeBSD mods, tested on FreeBSD 7.1
+ util/ipmidir.c - FreeBSD mods, fixed SMBIOS overwriting ipmi_if.txt,
+ add register spacing from SMBIOS,
+ fix SMBChar to init SSIF correctly.
+ ipmiutil-2.3.5 contains:
+ ipmiutil.c (ipmiutil) ver 2.35
+ alarms.c (ipmiutil alarms) ver 2.35
+ bmchealth.c (ipmiutil health) ver 2.35
+ fruconfig.c (ipmiutil fru) ver 2.35
+ getevent.c (ipmiutil getevt) ver 2.35
+ hwreset.c (ipmiutil reset) ver 2.35
+ icmd.c (ipmiutil cmd) ver 2.35
+ pefconfig.c (ipmiutil lan) ver 2.35
+ sensor.c (ipmiutil sensor) ver 2.35
+ showsel.c (ipmiutil sel) ver 2.35
+ tmconfig.c (ipmiutil serial) ver 2.35
+ wdt.c (ipmiutil wdt) ver 2.35
+ isolconsole.c (ipmiutil sol) ver 2.35
+ bmcconfig.c (ipmiutil config) ver 2.35
+ events.c (ipmiutil events) ver 2.35
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+
+04/09/09 ARCress ipmiutil-2.3.6 changes
+ doc/UserGuide - Note that Legacy OS Redir is optional for SOL,
+ and ipmiutil serial is not required for SOL.
+ doc/bmchealth.8 - document -g and -s options
+ util/bmchealth.c - add -s option to get_lan_stats,
+ fixed WIN32 stack overflow in get_last_selftest()
+ util/pefconfig.c - change -z to use get_lan_stats,
+ recognize 115200 variant as well as 115.2k for -B
+ util/tmconfig.c - recognize 115200 variant as well as 115.2k for -B
+ util/ipmicmd.c - include ipmimv for BSD
+ util/ipmimv.c - include ipmimv for BSD, still some compatibility issues
+ ipmiutil-2.3.6 contains:
+ ipmiutil.c (ipmiutil) ver 2.36
+ alarms.c (ipmiutil alarms) ver 2.36
+ bmchealth.c (ipmiutil health) ver 2.36
+ fruconfig.c (ipmiutil fru) ver 2.36
+ getevent.c (ipmiutil getevt) ver 2.36
+ hwreset.c (ipmiutil reset) ver 2.36
+ icmd.c (ipmiutil cmd) ver 2.36
+ pefconfig.c (ipmiutil lan) ver 2.36
+ sensor.c (ipmiutil sensor) ver 2.36
+ showsel.c (ipmiutil sel) ver 2.36
+ tmconfig.c (ipmiutil serial) ver 2.36
+ wdt.c (ipmiutil wdt) ver 2.36
+ isolconsole.c (ipmiutil sol) ver 2.36
+ bmcconfig.c (ipmiutil config) ver 2.36
+ events.c (ipmiutil events) ver 2.36
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+
+05/08/09 ARCress ipmiutil-2.3.7 changes
+ doc/ipmiutil.spec - fixed an rpmlint warning
+ doc/showsel.cmd - fixed syntax error (showsel->sel)
+ util/ipmiutil.mak - clean *.res/.rc/.bin files from showsel.dll
+ util/sensor.c - add ChassisIntrus msg under Physical Security
+ util/showsel.c - fixed -l if only one SEL record.
+ util/ipmidir.c - always return error if wait_for_OBF_set timeout,
+ or if wait_for_IBF_clear timeout
+ util/*.c - added DOS compile flags
+ util/ipmilanplus.c - log the correct rq_seq value in sol_send,
+ set the rq_seq to sol_seq in sol_send,
+ added lan2_recv_handler to fix bug #2787484
+ util/isolconsole.c - get all socket data before any stdin data,
+ use lan2_recv_handler in set_sol_data,
+ detect dropped session sooner, and
+ use LAN_ERR_DROPPED for bug #2789103
+ util/ipmicmd.h - add LAN_ERR_DROPPED
+ util/ipmilan.c - add LAN_ERR_DROPPED to decode_rv()
+ doc/install.cmd - copy to Program Files, set PATH, etc.
+ doc/uninstall.cmd - new
+ doc/showselun.reg - new
+ ipmiutil-2.3.7 contains:
+ ipmiutil.c (ipmiutil) ver 2.37
+ alarms.c (ipmiutil alarms) ver 2.37
+ bmchealth.c (ipmiutil health) ver 2.37
+ fruconfig.c (ipmiutil fru) ver 2.37
+ getevent.c (ipmiutil getevt) ver 2.37
+ hwreset.c (ipmiutil reset) ver 2.37
+ icmd.c (ipmiutil cmd) ver 2.37
+ pefconfig.c (ipmiutil lan) ver 2.37
+ sensor.c (ipmiutil sensor) ver 2.37
+ showsel.c (ipmiutil sel) ver 2.37
+ tmconfig.c (ipmiutil serial) ver 2.37
+ wdt.c (ipmiutil wdt) ver 2.37
+ isolconsole.c (ipmiutil sol) ver 2.37
+ bmcconfig.c (ipmiutil config) ver 2.37
+ events.c (ipmiutil events) ver 2.37
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+
+06/01/09 ARCress ipmiutil-2.3.8 changes
+ util/events.c - moved decode logic to decode_raw_sel()
+ util/showsel.c - added -b/-f options calling decode_raw_sel()
+ util/ipmiutil.mak - do not delete crypto DLLs during clean
+ util/isolconsole.c - do not abort if keepalive error
+ ,(reverts 2.3.7 change that could abort during reboot),
+ handle extra '\n' in WIN32 dbglog,
+ add -v option to specify debug log filename
+ util/pefconfig.c - overwrite GCM MAC if specified,
+ dont arping for gwymac if gcm_ch and not same subnet.
+ util/sensor.c - add ':' delimiter to -s output
+ util/ipmidir.c - check for rlen==0 from ssif and return, fixed SegFault.
+ util/getevent.c - update comments for -a option
+ util/ipmi_sample.c - new, sample app
+ util/Makefile.am - add ipmi_sample app build
+ util/ipmiutil.mak - add ipmiutil.lib,ipmi_sample app build
+ doc/events.8 - changes to -b/-r/-f/-h descriptions
+ doc/showsel.8 - added -b/-f options
+ doc/uninstall.cmd - automated cleanup of PATH and at jobs
+ configure.in - detect rpm PKG_DIR if Linux
+ Makefile.am - use PKG_DIR
+ ipmiutil-2.3.8 contains:
+ ipmiutil.c (ipmiutil) ver 2.38
+ alarms.c (ipmiutil alarms) ver 2.38
+ bmchealth.c (ipmiutil health) ver 2.38
+ fruconfig.c (ipmiutil fru) ver 2.38
+ getevent.c (ipmiutil getevt) ver 2.38
+ hwreset.c (ipmiutil reset) ver 2.38
+ icmd.c (ipmiutil cmd) ver 2.38
+ pefconfig.c (ipmiutil lan) ver 2.38
+ sensor.c (ipmiutil sensor) ver 2.38
+ showsel.c (ipmiutil sel) ver 2.38
+ tmconfig.c (ipmiutil serial) ver 2.38
+ wdt.c (ipmiutil wdt) ver 2.38
+ isolconsole.c (ipmiutil sol) ver 2.38
+ bmcconfig.c (ipmiutil config) ver 2.38
+ events.c (ipmiutil events) ver 2.38
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+
+06/05/09 ARCress ipmiutil-2.3.9 changes
+ util/bmcconfig.c - save LAN1 and LAN3 if present, include chan for each,
+ fix ser_ch defaults if -L, fnotshared->fsharedMAC
+ util/pefconfig.c - fix ser_ch defaults if -L, fnotshared->fsharedMAC
+ util/isolconsole.c - allow 0.5 sec after close for BMC teardown.
+ util/events.c - interpret IERR deasserts correctly
+ util/sensor.c - check for type 0x21 DIMM slot fault bit
+ util/hwreset.c - do not reset by default, show usage if no options
+ doc/hwreset.8 - default is no longer hard reset
+ ipmiutil-2.3.9 contains:
+ ipmiutil.c (ipmiutil) ver 2.39
+ alarms.c (ipmiutil alarms) ver 2.39
+ bmchealth.c (ipmiutil health) ver 2.39
+ fruconfig.c (ipmiutil fru) ver 2.39
+ getevent.c (ipmiutil getevt) ver 2.39
+ hwreset.c (ipmiutil reset) ver 2.39
+ icmd.c (ipmiutil cmd) ver 2.39
+ pefconfig.c (ipmiutil lan) ver 2.39
+ sensor.c (ipmiutil sensor) ver 2.39
+ showsel.c (ipmiutil sel) ver 2.39
+ tmconfig.c (ipmiutil serial) ver 2.39
+ wdt.c (ipmiutil wdt) ver 2.39
+ isolconsole.c (ipmiutil sol) ver 2.39
+ bmcconfig.c (ipmiutil config) ver 2.39
+ events.c (ipmiutil events) ver 2.39
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+
+06/25/09 ARCress ipmiutil-2.4.0 changes
+ lib/lanplus/lanplus.c - removed 2 asserts, handle better
+ util/ipmilanplus.c - added more stubs ifndef HAVE_LANPLUS
+ util/mem_if.c - skip error msg if Solaris
+ util/showsel.c - generalize syslog code, fix SEL info vtotal(short->int)
+ util/getevent.c - use syslog code to log -a shutdown/reboot
+ util/tmconfig.c - if transient MUX error, still success
+ handle 9.6K string properly
+ util/pefconfig.c - handle 9.6K string properly,
+ disallow setting params if -N and another session active
+ util/bmcconfig.c - disallow setting params if -N and another session active
+ util/sensor.c - for -s, simplify to show only full/compact sensors
+ util/bmchealth.c - added WinBond, Inventec to vendor strings
+ doc/ipmiutil.spec - create $tmpdir instead of %{_tmppath} in %post*,
+ change events->ievents
+ install init/cron scripts via %files instead of %post
+ doc/install-solaris.sh - change events to ievents
+ doc/Makefile - change events to ievents, detect initto dir
+ doc/events.8 -> doc/ievents.8
+ util/events.c -> util/ievents.c
+ util/ievents.c - change progname from events to ievents,
+ also decode HSC thresh events with act=/thr=
+ ipmiutil-2.4.0 contains:
+ ipmiutil.c (ipmiutil) ver 2.40
+ alarms.c (ipmiutil alarms) ver 2.40
+ bmchealth.c (ipmiutil health) ver 2.40
+ fruconfig.c (ipmiutil fru) ver 2.40
+ getevent.c (ipmiutil getevt) ver 2.40
+ hwreset.c (ipmiutil reset) ver 2.40
+ icmd.c (ipmiutil cmd) ver 2.40
+ pefconfig.c (ipmiutil lan) ver 2.40
+ sensor.c (ipmiutil sensor) ver 2.40
+ showsel.c (ipmiutil sel) ver 2.40
+ tmconfig.c (ipmiutil serial) ver 2.40
+ wdt.c (ipmiutil wdt) ver 2.40
+ isolconsole.c (ipmiutil sol) ver 2.40
+ bmcconfig.c (ipmiutil config) ver 2.40
+ ievents.c (ipmiutil events) ver 2.40
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+
+08/10/09 ARCress ipmiutil-2.4.1 changes
+ util/showsel.c - define write_syslog routine here,
+ return error if ClearSEL fails.
+ util/getevent.c - move write_syslog routine out,
+ fix index from evt.idx after SEL gets cleared (0xCD),
+ show sensor description if IPMI event.
+ util/hwreset.c - call write_syslog if reset action is initiated
+ util/pefconfig.c - show OS IP/MAC used for arp if debug,
+ add -c option for canonical output
+ util/isolconsole.c - allow 2nd retry pass if sol_send error with -t2,
+ limit sol_send size to MAX_BMC_DATA(203),
+ set max debug for -xx, like -z.
+ fix truncate bug in dbglog().
+ lib/lanplus/lanplus.c - if debug, show try of sol_packet, show session_seq
+ util/ievents.c - add Power Cycle ok event description,
+ show sensor description if IPMI event.
+ util/sensor.c - num->snum for -s/-c canonical output
+ util/ipmilan.c - add hash_special code for SuperMicro,
+ fix _send_lan_cmd() for bug 2827802 with auth=none
+ util/ipmicmd.c - add 'supermicro' as a driver type for -F
+ util/imbapi.c - use MAX_IMB_RESP_SIZE instead of MAX_RBUFFER_SIZE(64)
+ util/imb_api.h - MAX_IMB_PACKET_SIZE was 33, now 63
+ util/ipmidir.c - if detect I/F as KCS and get error, do not try SSIF,
+ increase MAX_KCS_LOOP from 5000 to 7000 for Ht
+ doc/ipmi_port.sh - fixed to point to /usr/sbin/ipmi_port now
+ ipmiutil-2.4.1 contains:
+ ipmiutil.c (ipmiutil) ver 2.41
+ alarms.c (ipmiutil alarms) ver 2.41
+ bmchealth.c (ipmiutil health) ver 2.41
+ fruconfig.c (ipmiutil fru) ver 2.41
+ getevent.c (ipmiutil getevt) ver 2.41
+ hwreset.c (ipmiutil reset) ver 2.41
+ icmd.c (ipmiutil cmd) ver 2.41
+ pefconfig.c (ipmiutil lan) ver 2.41
+ sensor.c (ipmiutil sensor) ver 2.41
+ showsel.c (ipmiutil sel) ver 2.41
+ tmconfig.c (ipmiutil serial) ver 2.41
+ wdt.c (ipmiutil wdt) ver 2.41
+ isolconsole.c (ipmiutil sol) ver 2.41
+ bmcconfig.c (ipmiutil config) ver 2.41
+ ievents.c (ipmiutil events) ver 2.41
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+
+09/02/09 ARCress ipmiutil-2.4.2 changes
+ lib/lanplus/lanplus.c - if -x, show session_id, added check_sol debug,
+ added lanplus_set_recvdelay() for slow networks
+ util/pefconfig.c - Windows: always check for -I before setting IP,
+ to fix bug 2836451.
+ util/imbapi.c - added more DBG_IPMI messages
+ util/imb_api.h - moved GetLastError() to imbapi.c
+ util/ipmilanplus.c - always set acked_packet_number in lan2_send_sol,
+ add more debug messages if max debug,
+ add lan2_validate_solrcv for more checking
+ util/isolconsole.c - allow max debug via -xxx,
+ limit stdin reads to MAX_BMC_DATA(203) also,
+ handle sol_send errors/retries better,
+ add -s for slow link recvdelay
+ util/isolwin.c - mods for arrow keys (0x1b [A -> OA),
+ make sure WIN32 dbglog msgs have \r\n
+ util/bmchealth.c - show more for Chassis Status (last_pwr)
+ util/ipmicmd.c - added get_mfgid/set_mfgid for my_devid
+ util/mem_if.c - added get_MemDesc routine
+ util/ievents.c - use get_MemDesc for DIMM string if Intel
+ doc/ipmiutil.spec - add BuildRequires: openssl-devel
+ ipmiutil-2.4.1-fix-format-errors.patch - use printf("%s",var) format
+ ipmiutil-2.4.1-fix-getline-conflict.patch - getline->my_getline in ipmicmd.c
+ these 2 patches were merged from Guillaume Rousse
+ util/ipmiutil.mak - changed CFLAGS
+ lib/lanplus/ipmiplus.mak - changed CFLAGS
+ doc/isolconsole.8 - document -s option for slow link
+ ipmiutil-2.4.2 contains:
+ ipmiutil.c (ipmiutil) ver 2.42
+ alarms.c (ipmiutil alarms) ver 2.42
+ bmchealth.c (ipmiutil health) ver 2.42
+ fruconfig.c (ipmiutil fru) ver 2.42
+ getevent.c (ipmiutil getevt) ver 2.42
+ hwreset.c (ipmiutil reset) ver 2.42
+ icmd.c (ipmiutil cmd) ver 2.42
+ pefconfig.c (ipmiutil lan) ver 2.42
+ sensor.c (ipmiutil sensor) ver 2.42
+ showsel.c (ipmiutil sel) ver 2.42
+ tmconfig.c (ipmiutil serial) ver 2.42
+ wdt.c (ipmiutil wdt) ver 2.42
+ isolconsole.c (ipmiutil sol) ver 2.42
+ bmcconfig.c (ipmiutil config) ver 2.42
+ ievents.c (ipmiutil events) ver 2.42
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+
+09/14/09 ARCress ipmiutil-2.4.3 changes
+ util/ipmilanplus.c - logic to compute lan2_latency, after open,
+ change recv_handler arg to (void *),
+ set timeout=1, esc_char in set_sol_data(),
+ fix null username if Solaris printf
+ util/isolconsole.c - auto-detect latency, set -s 500 if >100ms,
+ change recv_handler arg to (void *)
+ util/fruconfig.c - add SMI MCs via -m00c000s,
+ use get_errno()
+ util/sensor.c - add SMI MCs via -m002000s,
+ change delimiter from ':' to '|' for -c
+ util/pefconfig.c - add -H to gateway MAC warning text,
+ change delimiter from ':' to '|' for -c,
+ use get_errno()
+ util/bmcconfig.c - use get_errno()
+ util/ipmicmd.c - add get_errno(), set_lan_options(),
+ util/ipmicmd.h - add get_errno(), set_lan_options(), removed gnode
+ util/ievents.c - get DIMM index from data2 if mini-BMC
+ lib/lanplus/lanplus.c - change some check_sol debug msgs LOG_WARN -> LOG_INFO,
+ allow setting lan2_timeout in lanplus_open,
+ if slow_link, set lan2_timeout = 2 sec
+ doc/fruconfig.8 - document SMI MCs via -m00c000s
+ doc/sensor.8 - document SMI MCs via -m002000s
+ doc/pefconfig.8 - added more about MAC detection under -H
+ doc/UserGuide - updated man pages from above
+ ipmiutil-2.4.3 contains:
+ ipmiutil.c (ipmiutil) ver 2.43
+ alarms.c (ipmiutil alarms) ver 2.43
+ bmchealth.c (ipmiutil health) ver 2.43
+ fruconfig.c (ipmiutil fru) ver 2.43
+ getevent.c (ipmiutil getevt) ver 2.43
+ hwreset.c (ipmiutil reset) ver 2.43
+ icmd.c (ipmiutil cmd) ver 2.43
+ pefconfig.c (ipmiutil lan) ver 2.43
+ sensor.c (ipmiutil sensor) ver 2.43
+ showsel.c (ipmiutil sel) ver 2.43
+ tmconfig.c (ipmiutil serial) ver 2.43
+ wdt.c (ipmiutil wdt) ver 2.43
+ isolconsole.c (ipmiutil sol) ver 2.43
+ bmcconfig.c (ipmiutil config) ver 2.43
+ ievents.c (ipmiutil events) ver 2.43
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+
+10/28/09 ARCress ipmiutil-2.5.0 changes
+ Full ANSI VT100 emulation for Windows SOL console
+ Two-character escape sequence (~.) for SOL console, adding send-Break.
+ Added canonical output option -c for fru,config,sensor,health,lan
+ Added ipmiutil getevt -r to run specified script when an event occurs
+ util/bmchealth.c - add -f to show FRUSDR versions
+ renamed show_devid -> show_devid_all
+ add -c for canonical output with delim '|'
+ util/tmconfig.c - show Adjusting messages even if not debug,
+ add -g for fconsoleonly with BMode CTS
+ util/ievents.c - only show file_grep error msg if fdebug
+ util/ipmicmd.c - added global fdebug,
+ add SOLARIS logic for tty_setraw to fix stdin
+ added show_devid()
+ util/ipmicmd.h - added show_devid and BDELIM ('|')
+ util/AnsiTerm.cpp - new, from Robert Nelson, see file comments,
+ this is a complete ANSI VT100 emulation
+ util/AnsiTerm.h - new, from Robert Nelson, see file comments
+ util/isolwin.c - changes to use AnsiTerm.cpp, more dbglog messages
+ util/isolconsole.c - changes to use AnsiTerm.cpp,
+ implement 2-char escape sequence (~.),
+ use extern for lan2 even if not HAVE_LANPLUS,
+ use CheckTextMode to detect CRLF if bg color set
+ which automatically converts Enter in BIOS Setup.
+ util/ipmiutil.mak - changes to add AnsiTerm.obj
+ util/ipmilanplus.c - added lan2_send_break()
+ util/ipmidir.c - only decrement SMBase if l.o.bit is 1
+ util/fruconfig.c - add -c for canonical output with delim '|'
+ util/bmcconfig.c - add -c for canonical output with delim '|'
+ util/getevent.c - add -e to wait for specific event sensor type,
+ add -r to run script file when event occurs
+ doc/getevent.8 - document -e, -r options
+ doc/evt.sh - new, sample event script for ipmiutil getevt -r
+ doc/Makefile - install evt.sh
+ doc/ipmiutil.spec - include evt.sh
+ configure.in - include WindRiver detection to show warning
+ <various> - change email to " at users.sourceforge.net"
+ ipmiutil-2.5.0 contains:
+ ipmiutil.c (ipmiutil) ver 2.50
+ alarms.c (ipmiutil alarms) ver 2.50
+ bmchealth.c (ipmiutil health) ver 2.50
+ fruconfig.c (ipmiutil fru) ver 2.50
+ getevent.c (ipmiutil getevt) ver 2.50
+ hwreset.c (ipmiutil reset) ver 2.50
+ icmd.c (ipmiutil cmd) ver 2.50
+ pefconfig.c (ipmiutil lan) ver 2.50
+ sensor.c (ipmiutil sensor) ver 2.50
+ showsel.c (ipmiutil sel) ver 2.50
+ tmconfig.c (ipmiutil serial) ver 2.50
+ wdt.c (ipmiutil wdt) ver 2.50
+ isolconsole.c (ipmiutil sol) ver 2.50
+ bmcconfig.c (ipmiutil config) ver 2.50
+ ievents.c (ipmiutil events) ver 2.50
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+
+11/20/09 ARCress ipmiutil-2.5.1 changes
+ util/isolwin.c - use wait_time for wait/select tuning with -u
+ util/isolconsole.c - add -u for wait_time, use it for Linux select,
+ detect Dell BMC and set shorter max_bmc_data.
+ util/ipmiutil.mak - fix CFLAGS_W for AnsiTerm.cpp
+ util/sensor.c - show nominal SDR values with -v
+ util/tmconfig.c - added fcanonical option -a
+ util/alarms.c - adjust if -i param > 255
+ util/pefconfig.c - do not copy eth%d in FindEthNum if -i,
+ only show SIOCGIF erros if debug (-x)
+ doc/ipmiutil.spec - cleanup some unneeded script logic
+ configure.in - move distro-specific logic here
+ ipmiutil-2.5.1 contains:
+ ipmiutil.c (ipmiutil) ver 2.51
+ alarms.c (ipmiutil alarms) ver 2.51
+ bmchealth.c (ipmiutil health) ver 2.51
+ fruconfig.c (ipmiutil fru) ver 2.51
+ getevent.c (ipmiutil getevt) ver 2.51
+ hwreset.c (ipmiutil reset) ver 2.51
+ icmd.c (ipmiutil cmd) ver 2.51
+ pefconfig.c (ipmiutil lan) ver 2.51
+ sensor.c (ipmiutil sensor) ver 2.51
+ showsel.c (ipmiutil sel) ver 2.51
+ tmconfig.c (ipmiutil serial) ver 2.51
+ wdt.c (ipmiutil wdt) ver 2.51
+ isolconsole.c (ipmiutil sol) ver 2.51
+ bmcconfig.c (ipmiutil config) ver 2.51
+ ievents.c (ipmiutil events) ver 2.51
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+
+12/16/09 ARCress ipmiutil-2.5.2 changes
+ util/sensor.c - fix -w(fwrap) with -c(fsimple) feat#2907464
+ util/ievents.c - decode OEM type f1 as all ascii
+ util/showsel.c - added option for adding OEM SEL record type f1
+ util/md2.c - undef MD2OK if NON_GPL
+ util/mem_if.c - fix get_Ipmi for NSI2U to only decr if odd
+ util/bmchealth.c - fix NSI2U to set fmBMC=1
+ util/ipmiutil.mak - use static CFLAGS/link for Win64
+ lib/lanplus/ipmiplus.mak - use static CFLAGS/link for Win64
+ util/ievents.c - decode PS config error event
+ util/ipmimv.c - added pragma pack and ioctls for FreeBSD
+ util/ipmicmd.c - choose open driver for BSD if loaded
+ doc/UserGuide - document 'kldload ipmi' for FreeBSD,
+ document that Win64 needs vcredist_x86.exe
+ ipmiutil-2.5.2 contains:
+ ipmiutil.c (ipmiutil) ver 2.52
+ alarms.c (ipmiutil alarms) ver 2.52
+ bmchealth.c (ipmiutil health) ver 2.52
+ fruconfig.c (ipmiutil fru) ver 2.52
+ getevent.c (ipmiutil getevt) ver 2.52
+ hwreset.c (ipmiutil reset) ver 2.52
+ icmd.c (ipmiutil cmd) ver 2.52
+ pefconfig.c (ipmiutil lan) ver 2.52
+ sensor.c (ipmiutil sensor) ver 2.52
+ showsel.c (ipmiutil sel) ver 2.52
+ tmconfig.c (ipmiutil serial) ver 2.52
+ wdt.c (ipmiutil wdt) ver 2.52
+ isolconsole.c (ipmiutil sol) ver 2.52
+ bmcconfig.c (ipmiutil config) ver 2.52
+ ievents.c (ipmiutil events) ver 2.52
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+
+01/27/10 ARCress ipmiutil-2.5.3 changes
+ doc/UserGuide - resync with man pages
+ doc/wdt.8 - line breaks for ipmiutil_wdt commands
+ util/ievents.c - add System Reconfig variant
+ util/pefconfig.c - for -c, show PEF Control = none if disabled
+ util/Makefile.am - removed xmlconfig
+ util/fruconfig.c - show frutype,fruid in show_fru, detect bad type/len,
+ fix WIN32 ctime() error w Board DateTime on CG2100,
+ fix GetSDR error 0xCA if SDR size < 16,
+ skip FRU for frutype==0x2e (ME)
+ util/showsel.c - ovf->overflow in status msg, show Size,Used,Free
+ util/ipmidir.c - max_kcs_loops 7000->30000 for slower ClearSEL cmd
+ util/imbapi.c - changed Async handle from int to long
+ util/imb_api.h - changed Async handle from int to long
+ util/getevent.c - changed Async handle from int to long
+ util/isolconsole.c - added retry_time, initially 5msec, now set to latency
+ util/sensor.c - fix GetSDR error 0xCA if SDR size < 16 for CG2100
+ util/ipmilan.c - changed 1.5 SOL data header,
+ if sa==SWID for soft reset, bridge_level=0,
+ change TEST_LAN to fdebuglan>2 w dbglog.
+ util/ipmiutil.c - added svc function
+ util/getevent.c - add debug message if unknown Sms function
+ doc/setlib.sh - new, resolves libcrypto.so reference
+ doc/ipmiutil_wdt - updated for rpmlint issues
+ doc/ipmiutil_asy - updated for rpmlint issues
+ doc/ipmi_port.sh - updated for rpmlint issues
+ doc/ipmiutil.spec - updated for rpmlint issues, removed bmclanaol.mib
+ doc/Makefile - removed bmclanaol.mib
+ ipmiutil-2.5.3 contains:
+ ipmiutil.c (ipmiutil) ver 2.53
+ alarms.c (ipmiutil alarms) ver 2.53
+ bmchealth.c (ipmiutil health) ver 2.53
+ fruconfig.c (ipmiutil fru) ver 2.53
+ getevent.c (ipmiutil getevt) ver 2.53
+ hwreset.c (ipmiutil reset) ver 2.53
+ icmd.c (ipmiutil cmd) ver 2.53
+ pefconfig.c (ipmiutil lan) ver 2.53
+ sensor.c (ipmiutil sensor) ver 2.53
+ showsel.c (ipmiutil sel) ver 2.53
+ tmconfig.c (ipmiutil serial) ver 2.53
+ wdt.c (ipmiutil wdt) ver 2.53
+ isolconsole.c (ipmiutil sol) ver 2.53
+ bmcconfig.c (ipmiutil config) ver 2.53
+ ievents.c (ipmiutil events) ver 2.53
+ idiscover.c (ipmiutil discover) ver 1.5
+ ipmi_port.c (ipmi_port) ver 1.1
+
+02/10/10 ARCress ipmiutil-2.5.4 changes
+ doc/setlib.sh - handle multiple instances
+ doc/ipmiutil.spec - set RPM_BUILD_ROOT for debuginfo
+ util/Makefile.am - do not strip in install for debuginfo
+ util/sensor.c - add Platform Alert meanings
+ util/pefconfig.c - skip rest of PEF if ccode=0xC1,
+ set arp_ctl=0x02 and sol_accum/retry for CG2100,
+ set_max_kcs_loops(100000) if CG2100,
+ fix DisablePef(9) policy num to conform.
+ util/bmcconfig.c - skip rest of PEF if ccode=0xC1, comment errors
+ util/ipmims.c - moved to ipmims.cpp
+ util/ipmims.cpp - new, renamed from ipmims.c
+ util/ipmicmd.c - set default gpriv_level to user (was admin)
+ util/hwreset.c - set default gpriv_level to admin when invoked
+ util/ievents.c - for CritStop data2,data2 -> data2,data3
+ util/ipmidir.c - make ProcesSendM/ProcessTimedM static
+ util/bmchealth.c - show Kontron KTC5520 product desc
+ ipmiutil-2.5.4 contains:
+ ipmiutil (ipmiutil) ver 2.54
+ alarms (ipmiutil alarms) ver 2.54
+ bmchealth (ipmiutil health) ver 2.54
+ fruconfig (ipmiutil fru) ver 2.54
+ getevent (ipmiutil getevt) ver 2.54
+ hwreset (ipmiutil reset) ver 2.54
+ icmd (ipmiutil cmd) ver 2.54
+ pefconfig (ipmiutil lan) ver 2.54
+ sensor (ipmiutil sensor) ver 2.54
+ showsel (ipmiutil sel) ver 2.54
+ tmconfig (ipmiutil serial) ver 2.54
+ wdt (ipmiutil wdt) ver 2.54
+ isolconsole (ipmiutil sol) ver 2.54
+ bmcconfig (ipmiutil config) ver 2.54
+ ievents (ipmiutil events) ver 2.54
+ idiscover (ipmiutil discover) ver 1.5
+ ipmi_port (ipmi_port) ver 1.1
+
+02/26/10 ARCress ipmiutil-2.6.0 changes
+ beforeconf.sh - handle libtool-2.x
+ configure.in - tweak install-strip subst
+ Makefile.am - clean debug*.list files,
+ doc/Makefile - change *.8,*.cmd,script names to new scheme
+ doc/ipmiutil.spec - changes for new naming scheme
+ doc/UserGuide - changes for new naming scheme
+ util/showsel.h - deleted, no longer used
+ util/ipmignustub.c - deleted, no longer used
+ util/xmlconfig.c - deleted, no longer used
+ util/Makefile.sco - deleted, no longer used
+ util/Makefile.am - change *.c names to new scheme
+ util/ipmiutil.mak - change *.c names to new scheme
+ util/alarms.c - renamed, now ialarms.c
+ util/bmcconfig.c - renamed, now iconfig.c
+ util/bmchealth.c - renamed, now ihealth.c
+ util/fruconfig.c - renamed, now ifru.c
+ util/getevent.c - renamed, now igetevent.c
+ util/hwreset.c - renamed, now ireset.c
+ util/isolconsole.c - renamed, now isol.c
+ util/pefconfig.c - renamed, now ilan.c
+ util/sensor.c - renamed, now isensor.c
+ util/showsel.c - renamed, now isel.c
+ util/tmconfig.c - renamed, now iserial.c
+ util/wdt.c - renamed, now iwdt.c
+ doc/alarms.8 - renamed, now ialarms.8
+ doc/bmcconfig.8 - renamed, now iconfig.8
+ doc/bmchealth.8 - renamed, now ihealth.8
+ doc/fruconfig.8 - renamed, now ifru.8
+ doc/getevent.8 - renamed, now igetevent.8
+ doc/hwreset.8 - renamed, now ireset.8
+ doc/isolconsole.8 - renamed, now isol.8
+ doc/pefconfig.8 - renamed, now ilan.8
+ doc/sensor.8 - renamed, now isensor.8
+ doc/showsel.8 - renamed, now isel.8
+ doc/tmconfig.8 - renamed, now iserial.8
+ doc/wdt.8 - renamed, now iwdt.8
+ util/ipmiutil.c - allow either getevt or getevent subcommands
+ util/iconfig.c - add SystemParam(0) for Chassis Restore Policy,
+ count num errors and show warning if any,
+ add wart for iBMC and user2
+ util/ilan.c - count num errors and show warning if any,
+ add wart for iBMC and user2
+ util/isol.c - fix script input for WIN32 dwKeyCode,
+ request admin priv if deactivate,
+ check for a recv before sending next script line,
+ util/isolwin.c - add Ascii2KeyCode for WIN32 script input,
+ increase IBUF_SZ to 128, check overflow better.
+ util/ipmimv.c - changes for ALONE/TEST_BIN compile flags for testing
+ util/ipmims.cpp - changes for ALONE/TEST_BIN compile flags for testing
+ util/ifru.c - set_max_kcs_loops to 100 msec if CG2100
+ util/isensor.c - set_max_kcs_loops to 100 msec if CG2100
+ util/icmd.c - set_max_kcs_loops to 100 msec if CG2100
+
+old name new name existing meta-command
+---------- ---------- ----------
+ipmiutil.8 ipmiutil.8 (ipmiutil)
+alarms.8 ialarms.8 (ipmiutil alarms)
+bmcconfig.8 iconfig.8 (ipmiutil config)
+bmchealth.8 ihealth.8 (ipmiutil health)
+fruconfig.8 ifru.8 (ipmiutil fru)
+getevent.8 igetevent.8 (ipmiutil getevent)
+hwreset.8 ireset.8 (ipmiutil reset)
+icmd.8 icmd.8 (ipmiutil cmd)
+idiscover.8 idiscover.8 (ipmiutil discover)
+ievents.8 ievents.8 (ipmiutil events)
+isolconsole.8 isol.8 (ipmiutil sol)
+pefconfig.8 ilan.8 (ipmiutil lan)
+sensor.8 isensor.8 (ipmiutil sensor)
+showsel.8 isel.8 (ipmiutil sel)
+tmconfig.8 iserial.8 (ipmiutil serial)
+wdt.8 iwdt.8 (ipmiutil wdt)
+
+ ipmiutil-2.6.0 contains:
+ ipmiutil (ipmiutil) ver 2.60
+ ialarms (ipmiutil alarms) ver 2.60
+ ihealth (ipmiutil health) ver 2.60
+ iconfig (ipmiutil config) ver 2.60
+ igetevent (ipmiutil getevt) ver 2.60
+ ireset (ipmiutil reset) ver 2.60
+ icmd (ipmiutil cmd) ver 2.60
+ ilan (ipmiutil lan) ver 2.60
+ isensor (ipmiutil sensor) ver 2.60
+ isel (ipmiutil sel) ver 2.60
+ iserial (ipmiutil serial) ver 2.60
+ iwdt (ipmiutil wdt) ver 2.60
+ isol (ipmiutil sol) ver 2.60
+ iconfig (ipmiutil config) ver 2.60
+ ievents (ipmiutil events) ver 2.60
+ idiscover (ipmiutil discover) ver 1.5
+ ipmi_port (ipmi_port) ver 1.1
+
+03/18/10 ARCress ipmiutil-2.6.1 changes
+ util/ipmicmd.c - move get_lan_channel & atoip here
+ util/ifru.c - request admin privilege if setting values,
+ add -v to set product version,
+ add -i to specify a fru id
+ util/isensor.c - request admin privilege if setting thresholds
+ util/isel.c - request admin privilege if clearing SEL
+ util/isol.c - change default fCRLF from 2 to 0 for stty onlcr
+ util/ilan.c - tweak SetUserAccess on iBMC (user1 ok, user2 skip)
+ util/imbapi.c - change RegisterAsync check for compile optim issue
+ doc/ifru.8 - added -v and -i documentation
+ doc/ipmiutil_wdt - init script standardization
+ doc/ipmiutil_asy - init script standardization
+ doc/ipmi_port.sh - init script standardization
+ doc/ipmiutil.spec - additional cleanup,
+ moved UserGuide to /usr/share/doc/ipmiutil-$version
+ ipmiutil-2.6.1 contains:
+ ipmiutil (ipmiutil) ver 2.61
+ ialarms (ipmiutil alarms) ver 2.61
+ icmd (ipmiutil cmd) ver 2.61
+ iconfig (ipmiutil config) ver 2.61
+ ievents (ipmiutil events) ver 2.61
+ ifru (ipmiutil fru) ver 2.61
+ igetevent (ipmiutil getevt) ver 2.61
+ ihealth (ipmiutil health) ver 2.61
+ ilan (ipmiutil lan) ver 2.61
+ ireset (ipmiutil reset) ver 2.61
+ isel (ipmiutil sel) ver 2.61
+ isensor (ipmiutil sensor) ver 2.61
+ iserial (ipmiutil serial) ver 2.61
+ isol (ipmiutil sol) ver 2.61
+ iwdt (ipmiutil wdt) ver 2.61
+ idiscover (ipmiutil discover) ver 1.5
+ ipmi_port (ipmi_port) ver 1.1
+
+04/06/10 ARCress ipmiutil-2.6.2 changes
+ util/ialarms.c - add \n to get_enc_leds error message
+ util/ihealth.c - show product 3E as CG2100
+ util/ifru.c - only check len in write_asset if new value supplied,
+ which avoids -10 error if sernum was empty.
+ util/isel.c - avoid extra SEL full warning if GetSelInfo failed
+ util/ilan.c - check show_users against max_users for miniBMC
+ util/iserial.c - check show_users against max_users for miniBMC
+ util/ifruset.c - new, allow setting all Product Area fields
+ util/Makefile.am - add ifruset
+ doc/isensor - fix script syntax error (%->$)
+ doc/UserGuide - resync with man page updates
+ doc/ipmiutil_wdt - fix to abort if no ipmi driver, caused problems
+ in SLES that auto-starts services.
+ ipmiutil-2.6.2 contains:
+ ipmiutil (ipmiutil) ver 2.62
+ ialarms (ipmiutil alarms) ver 2.62
+ icmd (ipmiutil cmd) ver 2.62
+ iconfig (ipmiutil config) ver 2.62
+ ievents (ipmiutil events) ver 2.62
+ ifru (ipmiutil fru) ver 2.62
+ igetevent (ipmiutil getevt) ver 2.62
+ ihealth (ipmiutil health) ver 2.62
+ ilan (ipmiutil lan) ver 2.62
+ ireset (ipmiutil reset) ver 2.62
+ isel (ipmiutil sel) ver 2.62
+ isensor (ipmiutil sensor) ver 2.62
+ iserial (ipmiutil serial) ver 2.62
+ isol (ipmiutil sol) ver 2.62
+ iwdt (ipmiutil wdt) ver 2.62
+ idiscover (ipmiutil discover) ver 1.5
+ ipmi_port (ipmi_port) ver 1.1
+
+04/27/10 ARCress ipmiutil-2.6.3 changes
+ configure.in - detect if libcrypto.so has md2, else set SKIP_MD2
+ to fix bug #2990244 with openssl-1.0.0,
+ removed NON_GPL flag, only use ALLOW_GPL toggle.
+ util/md2.c - add SKIP_MD2 compile flag
+ util/ipmilan.c - add SKIP_MD2 compile flag,
+ include SWID_SMSOS(0x41), changed TEST_LAN logic,
+ include -504 in decode_rv.
+ util/ihealth.c - add -p to set power restore policy
+ util/isensor.c - always request admin priv if remote for ReservID
+ util/isel.c - request admin priv if addsel & remote
+ util/isol.c - add stub for send_ctlaltdel,
+ explicitly set default priv to User for sol
+ util/ifru.c - if write error, dont load/show fru again
+ util/ifruset.c - if write error, dont load/show fru again
+ util/ipmimv.c - handle bad sresp passed to ipmi_cmdraw_mv()
+ util/iconfig.c - skip setting LanParam 10 arp if Lan3
+ util/igetevent.c - if -a and mv, write_syslog before shutdown/reboot.
+ use loop/stages with mv driver.
+ util/imbapi.c - return LAN_ERR_RECV_FAIL if status==1 in cmdraw_ia
+ util/iwdt.c - add -c for canonical output format,
+ set default priv to Admin for iwdt
+ doc/iwdt.8 - include -c description
+ doc/ifru.8 - include -c description
+ doc/ifruset.8 - new, man page for ifruset
+ doc/ipmi_port.8 - new, man page for ipmi_port
+ doc/UserGuide - updated man pages from above
+ doc/ipmiutil_wdt - detect if /etc/init.d/functions present
+ doc/ipmiutil_asy - detect if /etc/init.d/functions present
+ doc/ipmi_port.sh - detect if /etc/init.d/functions present,
+ this caused script errors with 2.61/2.62 on SuSE.
+ test/panicsel-c.sh - updated for new naming
+ test/panicsel_apptool_test.sh - updated for new naming
+ test/panicsel_test_needreboot.sh - updated for new naming
+ test/unittest.sh - new, added unit test script
+ ipmiutil-2.6.3 contains:
+ ipmiutil (ipmiutil) ver 2.63
+ ialarms (ipmiutil alarms) ver 2.63
+ icmd (ipmiutil cmd) ver 2.63
+ iconfig (ipmiutil config) ver 2.63
+ ievents (ipmiutil events) ver 2.63
+ ifru (ipmiutil fru) ver 2.63
+ igetevent (ipmiutil getevt) ver 2.63
+ ihealth (ipmiutil health) ver 2.63
+ ilan (ipmiutil lan) ver 2.63
+ ireset (ipmiutil reset) ver 2.63
+ isel (ipmiutil sel) ver 2.63
+ isensor (ipmiutil sensor) ver 2.63
+ iserial (ipmiutil serial) ver 2.63
+ isol (ipmiutil sol) ver 2.63
+ iwdt (ipmiutil wdt) ver 2.63
+ idiscover (ipmiutil discover) ver 1.5
+ ipmi_port (ipmi_port) ver 1.1
+
+05/19/10 ARCress ipmiutil-2.6.4 changes
+ test/sensor-TIGW1U.txt - new, for unittest.sh
+ test/sensor-CG2100.txt - new, for unittest.sh
+ test/unittest.sh - changes to run on Solaris, use $testdir, add dosol flag
+ util/ihealth.c - request admin priv if -p and remote,
+ mods to skip powerstate for picmg/atca
+ util/ifruset.c - track existing num product fields, debug message if more,
+ rename i_fru to i_ifruset
+ util/ipmiutil.c - rename i_bmc() to i_config()
+ util/ipmiutil.h - rename i_bmc() to i_config()
+ util/iconfig.c - rename i_bmc() to i_config(),
+ include all LAN channels (e.g. 1,2,3)
+ doc/ipmi_if.sh - randomize dmi.out file
+ doc/ipmiutil.spec - changes for style, use /var/lib/ipmiutil
+ configure.in - tweaks to match spec file changes
+ INSTALL - add build instructions for FreeBSD
+ util/ipmidir.c - check /var/lib/ipmiutil & /usr/share/ipmiutil for ipmi_if.txt
+ util/ipmignu.c - check /var/lib/ipmiutil & /usr/share/ipmiutil for ipmi_if.txt
+ util/igetevent.c - move /usr/share/ipmiutil/evt.idx to /var/lib/ipmiutil,
+ remove WIN32 reference to fwritesel
+ util/isel.c - move /usr/share/ipmiutil/sel.idx to /var/lib/ipmiutil,
+ use extern evt_hdr
+ util/isensor.c - move /usr/share/ipmiutil/thresholds.sh ->/var/lib/ipmiutil,
+ add sensor types 17,F0,F1 for atca
+ util/ievents.c - move /usr/share/ipmiutil/sensor_out.txt ->/var/lib/ipmiutil
+ add SEVerity to decode_sel_entry(): INF,MIN,MAJ,CRT
+ show error message if cannot open sensfil from -s
+ util/ialarms.c - mods for picmg/atca leds, set fHasEnc for TIGI2U
+ doc/ipmi_port.sh - move /usr/share/ipmiutil/thresholds.sh to /var/lib/ipmiutil
+ doc/ilan.8 - document -b authmask option
+ util/ilan.c - show existing -b authmask option in Usage,
+ add strings for Auth enables (param2)
+ ipmiutil-2.6.4 contains:
+ ipmiutil (ipmiutil) ver 2.64
+ ialarms (ipmiutil alarms) ver 2.64
+ icmd (ipmiutil cmd) ver 2.64
+ iconfig (ipmiutil config) ver 2.64
+ ievents (ipmiutil events) ver 2.64
+ ifru (ipmiutil fru) ver 2.64
+ igetevent (ipmiutil getevt) ver 2.64
+ ihealth (ipmiutil health) ver 2.64
+ ilan (ipmiutil lan) ver 2.64
+ ireset (ipmiutil reset) ver 2.64
+ isel (ipmiutil sel) ver 2.64
+ isensor (ipmiutil sensor) ver 2.64
+ iserial (ipmiutil serial) ver 2.64
+ isol (ipmiutil sol) ver 2.64
+ iwdt (ipmiutil wdt) ver 2.64
+ ifruset (ifruset) ver 2.64
+ idiscover (ipmiutil discover) ver 1.5
+ ipmi_port (ipmi_port) ver 1.1
+
+06/10/10 ARCress ipmiutil-2.6.5 changes
+ util/isensor.c - modify idstr for shared compact sensor
+ util/ipicmg.c - new, added
+ util/ipicmg.h - new, added
+ util/ifirewall.c - new, added
+ util/ifirewall.h - new, added
+ util/Makefile.am - added picmg.c, ifirewall.c
+ util/ipmiutil.mak- added picmg.c, ifirewall.c
+ doc/ipicmg.8 - new, added
+ doc/ipicmg - new, added
+ doc/ifirewall.8 - new, added
+ doc/ifirewall - new, added
+ doc/Makefile - added picmg.8, ifirewall.8
+ doc/ipmiutil.spec - added ipicmg*, ifirewall*
+ doc/ipmiutil.8 - added picmg, firewall
+ ipmiutil-2.6.5 contains:
+ ipmiutil (ipmiutil) ver 2.65
+ ialarms (ipmiutil alarms) ver 2.65
+ icmd (ipmiutil cmd) ver 2.65
+ iconfig (ipmiutil config) ver 2.65
+ ievents (ipmiutil events) ver 2.65
+ ifru (ipmiutil fru) ver 2.65
+ igetevent (ipmiutil getevt) ver 2.65
+ ihealth (ipmiutil health) ver 2.65
+ ilan (ipmiutil lan) ver 2.65
+ ireset (ipmiutil reset) ver 2.65
+ isel (ipmiutil sel) ver 2.65
+ isensor (ipmiutil sensor) ver 2.65
+ iserial (ipmiutil serial) ver 2.65
+ isol (ipmiutil sol) ver 2.65
+ iwdt (ipmiutil wdt) ver 2.65
+ ifruset (ipmiutil ifruset) ver 2.65
+ ipicmg (ipmiutil picmg) ver 2.65
+ ifirewall (ipmiutil firewall) ver 2.65
+ idiscover (ipmiutil discover) ver 1.5
+ ipmi_port (ipmi_port) ver 1.1
+
+07/06/10 ARCress ipmiutil-2.6.6 changes
+ test/testipmi.sh - new, added for more detailed testing
+ test/unittest.sh - handle $testdir with dirname
+ doc/ipmiutil_evt - new, init script for ipmiutil getevt -s service
+ doc/evt.sh - change to filter out INFormational events
+ util/igetevent.c - also write to syslog for each event received
+ util/ireset.c - fix -w option to wait for BMC ready if ipmi lan
+ util/ihealth.c - for -f in get_frusdr_version: fix extra chars,
+ and also keep going to return SDR Package version.
+ util/ialarms.c - default to admin priv if remote get or set
+ util/ifru.c - set -V4 earlier if fwritefru
+ util/ifruset.c - set -V4 earlier if fwritefru
+ ipmiutil-2.6.6 contains:
+ ipmiutil (ipmiutil) ver 2.66
+ ialarms (ipmiutil alarms) ver 2.66
+ icmd (ipmiutil cmd) ver 2.66
+ iconfig (ipmiutil config) ver 2.66
+ ievents (ipmiutil events) ver 2.66
+ ifru (ipmiutil fru) ver 2.66
+ igetevent (ipmiutil getevt) ver 2.66
+ ihealth (ipmiutil health) ver 2.66
+ ilan (ipmiutil lan) ver 2.66
+ ireset (ipmiutil reset) ver 2.66
+ isel (ipmiutil sel) ver 2.66
+ isensor (ipmiutil sensor) ver 2.66
+ iserial (ipmiutil serial) ver 2.66
+ isol (ipmiutil sol) ver 2.66
+ iwdt (ipmiutil wdt) ver 2.66
+ ifruset (ipmiutil ifruset) ver 2.66
+ ipicmg (ipmiutil picmg) ver 2.66
+ ifirewall (ipmiutil firewall) ver 2.66
+ idiscover (ipmiutil discover) ver 1.5
+ ipmi_port (ipmi_port) ver 1.1
+
+07/15/10 ARCress ipmiutil-2.6.7 changes
+ util/ilan.c - skip some optional lan params based on detection,
+ add -w to set the grat arp interval.
+ util/iconfig.c - skip some optional params based on detection
+ util/ipmilan.c - detect if default MD5 AuthType not supported, try Pswd,
+ resolved some compile warnings.
+ util/ipmicmd.h - add VENDOR_PEPPERCON for SuperMicro AOC-SIMSO
+ util/ireset.c - ignore boot opts if VENDOR_KONTRON,
+ fix buffer overflow for initmsg
+ util/igetevent.c - handle sms_sa != 0x81 for Urbanna,
+ enable -a with DO_MVL for FreeBSD
+ util/ipicmg.c - fix compile warning by adding string.h
+ util/idiscover.c - try to resolve host names, use full broadcast,
+ fix packet format error in send_getauth
+ test/testipmi.sh - do not exit on failure, continue to other tests
+ test/ipmievt.sh - set hitemp instead of lotemp, handle /var/lib/ipmiutil
+ doc/ilan.8 - reorder lan options in alphabetical order, add -w
+ doc/ipmi_if.sh - always include Register Spacing
+ doc/Makefile - changes for rpmlint
+ doc/ipmiutil.spec - changes for rpmlint
+ ipmiutil-2.6.7 contains:
+ ipmiutil (ipmiutil) ver 2.67
+ ialarms (ipmiutil alarms) ver 2.67
+ icmd (ipmiutil cmd) ver 2.67
+ iconfig (ipmiutil config) ver 2.67
+ ievents (ipmiutil events) ver 2.67
+ ifru (ipmiutil fru) ver 2.67
+ igetevent (ipmiutil getevt) ver 2.67
+ ihealth (ipmiutil health) ver 2.67
+ ilan (ipmiutil lan) ver 2.67
+ ireset (ipmiutil reset) ver 2.67
+ isel (ipmiutil sel) ver 2.67
+ isensor (ipmiutil sensor) ver 2.67
+ iserial (ipmiutil serial) ver 2.67
+ isol (ipmiutil sol) ver 2.67
+ iwdt (ipmiutil wdt) ver 2.67
+ ifruset (ipmiutil ifruset) ver 2.67
+ ipicmg (ipmiutil picmg) ver 2.67
+ ifirewall (ipmiutil firewall) ver 2.67
+ idiscover (ipmiutil discover) ver 1.6
+ ipmi_port (ipmi_port) ver 1.1
+
+08/06/10 ARCress ipmiutil-2.6.8 changes
+ util/ifru.c - added ChkOverflow() to show_fru
+ test/testipmi.sh - do remote reset tests last, since reboot times vary
+ doc/ipmiutil.spec - fix two more rpmlint errors
+ ChangeLog - remove execute permissions
+ doc/UserGuide - remove execute permissions
+ Makefile.am - clean out \r in 'make tarball'
+ - fedora 14 cut taken here (build 1)
+ util/ilan.c - added get_sensor_desc in PefDesc
+ test/testipmi.sh - extra message about 3 other files required
+ configure.in - added changes for Wind River Linux, SuSE chkconfig
+ util/ievents.c - adjust SEV for thresholds to match TAM,
+ change get_sensdesc, add show_sensdesc
+ util/isel.c - add -d to show sensor description
+ util/igetevent.c - change get_sensdesc parameters
+ - all other binaries built here (build 2)
+ ipmiutil-2.6.8 contains:
+ ipmiutil (ipmiutil) ver 2.68
+ ialarms (ipmiutil alarms) ver 2.68
+ icmd (ipmiutil cmd) ver 2.68
+ iconfig (ipmiutil config) ver 2.68
+ ievents (ipmiutil events) ver 2.68
+ ifru (ipmiutil fru) ver 2.68
+ igetevent (ipmiutil getevt) ver 2.68
+ ihealth (ipmiutil health) ver 2.68
+ ilan (ipmiutil lan) ver 2.68
+ ireset (ipmiutil reset) ver 2.68
+ isel (ipmiutil sel) ver 2.68
+ isensor (ipmiutil sensor) ver 2.68
+ iserial (ipmiutil serial) ver 2.68
+ isol (ipmiutil sol) ver 2.68
+ iwdt (ipmiutil wdt) ver 2.68
+ ifruset (ipmiutil ifruset) ver 2.68
+ ipicmg (ipmiutil picmg) ver 2.68
+ ifirewall (ipmiutil firewall) ver 2.68
+ idiscover (ipmiutil discover) ver 1.6
+ ipmi_port (ipmi_port) ver 1.1
+
+09/01/10 ARCress ipmiutil-2.6.9 changes
+ util/ifruset.c - newdata buffer overflow handling to avoid segfault,
+ added -d/-r options to dump/restore FRU
+ util/ifru.c - newdata buffer overflow handling for -a/-s/-v
+ util/ievents.c - added decode_sel_fujitsu() call
+ util/ipmimv.c - fix potential overflow if sresp > 80
+ util/oem_fujitsu.c - new, for decode_sel_fujitsu, decode_sensor_fujitsu
+ code from Dan Lukes
+ util/oem_fujitsu.h - new, for oem_fujitsu functions
+ util/Makefile.am - added oem_fujitsu.c
+ util/showsel.h - deleted, no longer used
+ lib/lanplus/inc/ipmitool/ipmi_constants.h - added SHA256 defines
+ lib/lanplus/lanplus_crypt_impl.c - added SHA256 patch from Holger Liebig
+ lib/lanplus/lanplus_crypt.c - added SHA256 patch from Holger Liebig
+ lib/lanplus/lanplus_crypt.h - added SHA256 patch from Holger Liebig
+ lib/lanplus/lanplus_dump.c - added SHA256 patch from Holger Liebig
+ lib/lanplus/lanplus.c - added SHA256 patch from Holger Liebig
+ lib/lanplus/lanplus.h - added SHA256 patch from Holger Liebig
+ lib/lanplus/inc/ipmitool/ipmi.h - [20] -> [EVP_MAX_MD_SIZE] for SHA256
+ lib/lanplus/inc/ipmitool/ipmi_intf.h - add sik_len, k1_len, k2_len
+ lib/lanplus/lanplus_defs.h - new, consolidate lanplus structures
+ util/ipmilanplus.h - move structures to lanplus_defs.h
+ Note that SHA256 is not enabled without -DHAVE_SHA256 compile flag,
+ since many openssl/libcrypto versions do not yet include it.
+ configure.in - add --enable-sha256 to set -DHAVE_SHA256 compile flag,
+ set service default start/stop levels if not Red Hat.
+ util/ifwum.c - new, added OEM firmware update mgr functionality
+ util/ifwum.h - new, added OEM firmware update mgr functionality
+ util/ihpm.c - new, added HPM firmware update mgr functionality
+ util/ihpm.h - new, added HPM firmware update mgr functionality
+ util/ipmiutil.c - added fwum and hpm
+ util/ipmiutil.h - added fwum and hpm
+ doc/ifru.8 - added -k for oem_kontron
+ doc/ifwum.8 - new, ifwum man page
+ doc/ifwum - new, ifwum shortcut script
+ doc/ihpm.8 - new, ihpm man page
+ doc/ihpm - new, ihpm shortcut script
+ doc/UserGuide - added 5.3 Windows Command Usage, ifwum, ihpm
+ doc/ipmiutil.spec - added ifwum,ihpm parts
+ util/ipmimv.c - use poll() instead of wait_interval in getevent_mv
+ util/igetevent.c - call get_sdr_cache to pre-fetch sdr data
+ util/isel.c - call get_sdr_cache to pre-fetch sdr data if -e
+ util/isensor.c - added get_sdr_cache & get_sdr_from_cache
+ util/ievents.c - use set_sel_opts to pass sdr data
+ ipmiutil-2.6.9 contains:
+ ipmiutil (ipmiutil) ver 2.69
+ ialarms (ipmiutil alarms) ver 2.69
+ icmd (ipmiutil cmd) ver 2.69
+ iconfig (ipmiutil config) ver 2.69
+ ievents (ipmiutil events) ver 2.69
+ ifru (ipmiutil fru) ver 2.69
+ igetevent (ipmiutil getevt) ver 2.69
+ ihealth (ipmiutil health) ver 2.69
+ ilan (ipmiutil lan) ver 2.69
+ ireset (ipmiutil reset) ver 2.69
+ isel (ipmiutil sel) ver 2.69
+ isensor (ipmiutil sensor) ver 2.69
+ iserial (ipmiutil serial) ver 2.69
+ isol (ipmiutil sol) ver 2.69
+ iwdt (ipmiutil wdt) ver 2.69
+ ifruset (ipmiutil ifruset) ver 2.69
+ ipicmg (ipmiutil picmg) ver 2.69
+ ifirewall (ipmiutil firewall) ver 2.69
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 0.4
+ idiscover (ipmiutil discover) ver 1.6
+ ipmi_port (ipmi_port) ver 1.1
+
+09/27/10 ARCress ipmiutil-2.7.0 changes
+ util/ialarms.c - moved Intel functions to oem_intel.c
+ util/oem_intel.h - new, for oem_intel alarm LED functions
+ util/oem_intel.c - new, for oem_intel alarm LED functions
+ added decode_sensor_intel, show_oemsdr_intel
+ util/oem_sun.c - new, for oem_sun functions
+ util/oem_sun.h - new, for oem_sun functions
+ util/ipmiutil.c - show subcommand with show_outcome(), added i_sun
+ util/i*.c - don't call extra show_outcome(), exit->return.
+ util/ifru.c - add multi-record area decoding, call show_fru_picmg
+ util/ifruset.c - add multi-record area decoding, call show_fru_picmg,
+ added some validation for -f restore.
+ util/ipicmg.h - added more picmg defines
+ util/isensor.c - added -d/-f dump/file restore options,
+ util/ifru_picmg.c - new, add picmg FRU decoding in show_fru_picmg
+ util/iekanalyzer.c - new, added for ekanalyzer
+ util/iekanalyzer.h - new, added for ekanalyzer
+ util/isensor.c - added decode_sensor_intel/_kontron, show_oemsdr_intel,
+ fix get_sdr_cache with use_devsdrs()
+ util/oem_kontron.c - added decode_sensor_kontron, more fru checking
+ util/oem_fujitsu.c - added alarms_fujitsu routines for LEDs
+ util/ialarms.c - added calls to alarms_fujitsu routines
+ util/ihpm.c - upgraded from 0.4 to 1.0.2
+ util/ihealth.c - get ME version if S5500
+ util/ievents.c - call decode_sel_kontron, handle sel -e if sdrcache fails
+ util/ipmi_sample.c - add -m option, use show_outcome (v0.2)
+ lib/lanplus/lanplus.c - return error instead of assert if session id mismatch
+ doc/isunoem.8 - new, for sunoem functions
+ doc/iekanalyzer.8 - new, for ekanalyzer functions
+ doc/ifru.8 - added -d option to dump fru
+ doc/isensor.8 - added -d/-f options
+ doc/ipmiutil.spec - added isunoem.8, iekanalyzer.8
+ doc/UserGuide - added sunoem, ekanalyzer, added 7.1 for return codes
+ ipmiutil-2.7.0 contains:
+ ipmiutil (ipmiutil) ver 2.70
+ ialarms (ipmiutil alarms) ver 2.70
+ icmd (ipmiutil cmd) ver 2.70
+ iconfig (ipmiutil config) ver 2.70
+ ievents (ipmiutil events) ver 2.70
+ ifru (ipmiutil fru) ver 2.70
+ igetevent (ipmiutil getevt) ver 2.70
+ ihealth (ipmiutil health) ver 2.70
+ ilan (ipmiutil lan) ver 2.70
+ ireset (ipmiutil reset) ver 2.70
+ isel (ipmiutil sel) ver 2.70
+ isensor (ipmiutil sensor) ver 2.70
+ iserial (ipmiutil serial) ver 2.70
+ isol (ipmiutil sol) ver 2.70
+ iwdt (ipmiutil wdt) ver 2.70
+ ifruset (ipmiutil ifruset) ver 2.70
+ oem_sun (ipmiutil sunoem) ver 2.70
+ ipicmg (ipmiutil picmg) ver 2.70
+ ifirewall (ipmiutil firewall) ver 2.70
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.02
+ idiscover (ipmiutil discover) ver 1.6
+ ipmi_port (ipmi_port) ver 1.1
+
+10/18/10 ARCress ipmiutil-2.7.1 changes
+ util/oem_intel.c - changed sensor reading strings slightly,
+ added decode_post_intel
+ util/isol.c - fix compile error on Solaris Sparc
+ util/icmd.c - added -d decimal option to match 'ipmitool raw' syntax
+ util/ievents.c - added decoding detail for NM Exception events,
+ added decode_post_oem to decode some OEM POST codes,
+ added fixup for peppercon genid,
+ added all other threshold strings
+ util/ireset.c - added -y option to persist boot device param
+ util/ipmidir.c - added SKIP_IO flag for ppc64
+ util/ipmilan.c - ignore gethostbyname error if input is IP address
+ util/ipmicmd.c - use bcomma in show_outcome(), add stricmp for -F
+ util/oem_kontron.c - fix decode_sensor_kontron(PowerGood)
+ util/isensor.c - fix find_sdr_by_num() if last sdr
+ util/ilan.c - if sparc, set default ifname to eri0
+ util/Makefile.am - use OS_LFLAGS for idiscover also if Solaris
+ doc/ireset.8 - describe -y option to persist boot device param
+ doc/install-solaris.sh - add mkdir -p $mandir
+ configure.in - set SKIP_IO flag if ppc64 or other arch,
+ check for /usr/sfw or /usr/local if Solaris,
+ set __SPARC__ flag if arch is sun4u
+ ipmiutil-2.7.1 contains:
+ ipmiutil (ipmiutil) ver 2.71
+ ialarms (ipmiutil alarms) ver 2.71
+ icmd (ipmiutil cmd) ver 2.71
+ iconfig (ipmiutil config) ver 2.71
+ ievents (ipmiutil events) ver 2.71
+ ifru (ipmiutil fru) ver 2.71
+ igetevent (ipmiutil getevt) ver 2.71
+ ihealth (ipmiutil health) ver 2.71
+ ilan (ipmiutil lan) ver 2.71
+ ireset (ipmiutil reset) ver 2.71
+ isel (ipmiutil sel) ver 2.71
+ isensor (ipmiutil sensor) ver 2.71
+ iserial (ipmiutil serial) ver 2.71
+ isol (ipmiutil sol) ver 2.71
+ iwdt (ipmiutil wdt) ver 2.71
+ ifruset (ipmiutil ifruset) ver 2.71
+ oem_sun (ipmiutil sunoem) ver 2.71
+ ipicmg (ipmiutil picmg) ver 2.71
+ ifirewall (ipmiutil firewall) ver 2.71
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.02
+ idiscover (ipmiutil discover) ver 1.6
+ ipmi_port (ipmi_port) ver 1.1
+
+11/01/10 ARCress ipmiutil-2.7.2 changes
+ util/ifru.c - refine FruTypeString as Baseboard only if dev 0
+ util/isel.c - add patch for bug 3091058 (SelAllocationInfo/Dell)
+ from Alexander Dupuy,
+ and protect against SelAllocationInfo errors
+ util/ipmiutil.c - init psubcmd = "" for usage message
+ util/ipmicmd.c - added ipmi_set_mymc, ipmi_get_mymc, added -Z
+ util/ipmicmd.h - added ipmi_set_mymc, ipmi_get_mymc
+ util/ipmimv.c - added SET_MY_ADDRESS in ipmi_open_mv()
+ util/ifru.c - added -Z to set mymc.sa
+ util/ifruset.c - added -Z to set mymc.sa
+ util/ilan.c - reuse existing sol_baud if valid & no -B param
+ util/ievents.c - handle event type 06 for PS Fans
+ util/ipmi_port.c - mkdaemon: set fdlimit=stderr
+ util/igetevent.c - mkdaemon: set fdlimit=stderr (fixes -b EBADF if mv),
+ use ipmiutil_asy.log filename if -a
+ util/ireset.c - fix chassis soft-shutdown for non-Intel to use cmd 0x05
+ util/ipmiutil.c - add 'power' subcommand, same as 'reset'
+ test/unittest.sh - add ipmiutil sel -e
+ test/testipmi.sh - add ipmiutil sel -e
+ doc/Makefile.am - new, handle initto via @INIT_DIR@
+ doc/ipmi_port.sh - if no /var/lock/subsys, use /var/run
+ doc/ipmiutil_asy - if no /var/lock/subsys, use /var/run, fix getpid
+ doc/ipmiutil_evt - if no /var/lock/subsys, use /var/run, fix getpid
+ doc/ipmiutil_wdt - if no /var/lock/subsys, use /var/run, use $wdtlog
+ doc/ipmi.init.basic - new, added for debian ipmi driver
+ beforeconf.sh - set ltver via --version, not rpm -q
+ configure.in - detect if Debian, detect INIT_DIR
+ debian/changelog - new, added for debian packaging
+ debian/control - new, added for debian packaging
+ debian/copyright - new, added for debian packaging
+ debian/dirs - new, added for debian packaging
+ debian/docs - new, added for debian packaging
+ debian/rules - new, added for debian packaging
+ ipmiutil-2.7.2 contains:
+ ipmiutil (ipmiutil) ver 2.72
+ ialarms (ipmiutil alarms) ver 2.72
+ icmd (ipmiutil cmd) ver 2.72
+ iconfig (ipmiutil config) ver 2.72
+ ievents (ipmiutil events) ver 2.72
+ ifru (ipmiutil fru) ver 2.72
+ igetevent (ipmiutil getevt) ver 2.72
+ ihealth (ipmiutil health) ver 2.72
+ ilan (ipmiutil lan) ver 2.72
+ ireset (ipmiutil reset) ver 2.72
+ isel (ipmiutil sel) ver 2.72
+ isensor (ipmiutil sensor) ver 2.72
+ iserial (ipmiutil serial) ver 2.72
+ isol (ipmiutil sol) ver 2.72
+ iwdt (ipmiutil wdt) ver 2.72
+ ifruset (ipmiutil ifruset) ver 2.72
+ oem_sun (ipmiutil sunoem) ver 2.72
+ ipicmg (ipmiutil picmg) ver 2.72
+ ifirewall (ipmiutil firewall) ver 2.72
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.02
+ idiscover (ipmiutil discover) ver 1.6
+ ipmi_port (ipmi_port) ver 1.2
+
+12/16/10 ARCress ipmiutil-2.7.3 changes
+ util/ipmilan2.c - a stub of ipmilanplus.c without HAVE_LANPLUS
+ util/iekanalyzer.c - fix a compiler warning and lint error
+ util/isel.c - fix printf() syntax warning for Mandriva,
+ define decode_sel_entry() with return value,
+ fixup idxfile,idxfile2 if remote
+ util/ihpm.c - fix printf() syntax warning for Mandriva
+ util/ievents.c - fix printf() syntax warning for Mandriva,
+ added -t for full PET traps,
+ fix PET decoding for Sun OEM bytes,
+ adjust threshold description strings,
+ check for filename & decoding errors,
+ use fseek to fix file_grep(2) special case,
+ add size param to get_MemDesc,
+ add custom DIMM decoding for Intel S5500,
+ use snprintf to fix buf overflow in decode_sel_entry
+ util/igetevent.c - define decode_sel_entry() with return value,
+ fixup idxfile2 if remote
+ util/ifru.c - wart for Kontron 1-byte Version anomaly
+ util/ifruset.c - wart for Kontron 1-byte Version anomaly
+ util/ipmilipmi.c - new, for Solaris 8/9 lipmi driver
+ util/isensor.c - add sensor type 0x25 Entity Presence,
+ add call to decode_sensor_sun(),
+ change un-Recoverable threshold tag (nonrec -> unrec),
+ do not show separate reading error line unless fdebug,
+ but just show 'Unknown' by default
+ util/oem_sun.c - add decode_sensor_sun routine
+ util/oem_intel.c - added get_id_status_intel(),
+ check for NSW1U in detect_capab,
+ use raw command in check_bmctam_intel,
+ fixups to intel_s5500_post table
+ util/ialarms.c - call get_id_status_intel() if vendor=intel
+ util/mem_if.c - add Bank Locator string to get_MemDesc,
+ add size/presence to get_MemDesc
+ util/icmd.c - add 's' tag logic for -m
+ util/isol.c - change bKeepAlive from type 2 to 1
+ util/ihealth.c - added get_health_oem/_supermicro
+ util/oem_supermicro.c - new, added
+ util/ipmilan.c - set fdoping=1 to help stuck BMCs
+ util/Makefile.am - added oem_supermicro.c
+ util/ipmiutil.mak - added oem_supermicro.obj
+ beforeconf.sh - fixed to libtoolize by default
+ configure.in - handle space in _topdir from Mandriva
+ Makefile.am - add mkdir -p $(SOURCEDIR) in make tarball
+ doc/ipmiutil.spec - updated package description
+ doc/ipmi.init.basic - include watchdog module, check if exists
+ debian/control - updated package description
+ ipmiutil-2.7.3 contains:
+ ipmiutil (ipmiutil) ver 2.73
+ ialarms (ipmiutil alarms) ver 2.73
+ icmd (ipmiutil cmd) ver 2.73
+ iconfig (ipmiutil config) ver 2.73
+ ievents (ipmiutil events) ver 2.73
+ ifru (ipmiutil fru) ver 2.73
+ igetevent (ipmiutil getevt) ver 2.73
+ ihealth (ipmiutil health) ver 2.73
+ ilan (ipmiutil lan) ver 2.73
+ ireset (ipmiutil reset) ver 2.73
+ isel (ipmiutil sel) ver 2.73
+ isensor (ipmiutil sensor) ver 2.73
+ iserial (ipmiutil serial) ver 2.73
+ isol (ipmiutil sol) ver 2.73
+ iwdt (ipmiutil wdt) ver 2.73
+ ifruset (ipmiutil ifruset) ver 2.73
+ oem_sun (ipmiutil sunoem) ver 2.73
+ ipicmg (ipmiutil picmg) ver 2.73
+ ifirewall (ipmiutil firewall) ver 2.73
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.02
+ idiscover (ipmiutil discover) ver 1.6
+ ipmi_port (ipmi_port) ver 1.2
+
+02/09/11 ARCress ipmiutil-2.7.4 changes
+ Makefile.am - add 'make test' to run test/testipmi.sh,
+ restrict SUBDIRS if standalone
+ configure.in - restrict SUBDIRS if standalone
+ util/ipmidir.c - add debug output of Resp(netfn,cmd)
+ add lock file to ensure exclusive access to I/O
+ util/iconfig.c - add -m option to force setting BMC MAC,
+ fix to not SetUserEnable(1) if extra users.
+ util/ireset.c - do not set Intel S5500 systems for bridge agent method
+ util/ilan.c - fix GetPefRecord for bug 3163406
+ util/iconfig.c - fix GetPefRecord also for bug 3163406
+ util/isensor.c - allow defaults from sdr for -u via fill_thresholds,
+ fix to set threshold even if g_sa is HSC
+ util/igetevent.c - add -n to wait for events from a specific sensor number
+ util/mem_if.c - add get_SystemGuid to get GUID from SMBIOS
+ util/ifruset.c - use get_SystemGuid for GUID
+ util/ihealth.c - use get_SystemGuid for GUID
+ util/ifru.c - use get_SystemGuid for GUID,
+ add logic to follow child MCs if -f,
+ request admin if reading child FRUs
+ util/ifruset.c - request admin by default
+ util/icmd.c - auto-request admin priv if bridging to child MC SA
+ util/ipmimv.c - set exit(rv) if TEST_BIN/ALONE
+ util/ievents.c - use GetSensorType() if fPET and no sensor file
+ util/isensor.c - ignore sensor reading state bits 0xC0 (was OK*, now valid),
+ added -q to output Thresh in ::::: fmt
+ doc/ipmi.init.basic - refine start/stop output
+ doc/UserGuide - added more to SOL section 4.8
+ doc/ipmiutil.spec - use sensor -q for sensor_out.txt
+ doc/install-solaris.sh - use sensor -q for sensor_out.txt
+ doc/ipmi_port.sh - use sensor -q for sensor_out.txt
+ doc/init.sh - use sensor -q for sensor_out.txt
+ debian/postinst - new, do sensor -q for sensor_out.txt
+ added some files from tarball to svn trunk:
+ doc/idiscover.8
+ doc/ifruset.8
+ doc/install-solaris.sh
+ doc/ipmi_port.8
+ doc/ipmiutil_evt
+ doc/ipmiutil_wdt.cmd
+ lib/lanplus/inc/ipmitool/ipmi_cc.h
+ lib/lanplus/inc/ipmitool/ipmi_hpmfwupg.h
+ lib/lanplus/inc/ipmitool/ipmi_kontronoem.h
+ lib/lanplus/Makefile.am
+ util/oem_supermicro.c
+ debian/postinst
+ ipmiutil-2.7.4 contains:
+ ipmiutil (ipmiutil) ver 2.74
+ ialarms (ipmiutil alarms) ver 2.74
+ icmd (ipmiutil cmd) ver 2.74
+ iconfig (ipmiutil config) ver 2.74
+ ievents (ipmiutil events) ver 2.74
+ ifru (ipmiutil fru) ver 2.74
+ igetevent (ipmiutil getevt) ver 2.74
+ ihealth (ipmiutil health) ver 2.74
+ ilan (ipmiutil lan) ver 2.74
+ ireset (ipmiutil reset) ver 2.74
+ isel (ipmiutil sel) ver 2.74
+ isensor (ipmiutil sensor) ver 2.74
+ iserial (ipmiutil serial) ver 2.74
+ isol (ipmiutil sol) ver 2.74
+ iwdt (ipmiutil wdt) ver 2.74
+ ifruset (ipmiutil ifruset) ver 2.74
+ oem_sun (ipmiutil sunoem) ver 2.74
+ ipicmg (ipmiutil picmg) ver 2.74
+ ifirewall (ipmiutil firewall) ver 2.74
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.02
+ idiscover (ipmiutil discover) ver 1.6
+ ipmi_port (ipmi_port) ver 1.2
+
+04/04/11 ARCress ipmiutil-2.7.5 changes
+ util/ifru.c - fixed logic to follow child MCs with -e or -f,
+ include -r to restore fru from ifruset.c,
+ check for overflow in sdr loop with idstr
+ util/iwdt.c - add -q to set a specific pretimeout value (-p sets 90%)
+ util/mem_if.c - detect properly if SMBIOS has 16-byte register spacing
+ util/ilan.c - use GetPefCapabilities to set pefmax,
+ use float to show arp interval,
+ set LanParam 4 (IPsrc) before LanParam 3 (IPaddr),
+ handle if GetLanEntry returns ok but zero data
+ util/iconfig.c - use GetPefCapabilities to set pefmax,
+ turn off GratArp and set IPsrc before setting IP,
+ skip serial users if no serial channel,
+ skip optional serial params if errors,
+ handle if GetLanEntry returns ok but zero data
+ util/ihealth.c - added Intel S1200, S2600 board info,
+ show BMC extra version info for Kontron,
+ added IANA for NAT
+ util/ievents.c - use utc2local in fmt_time()
+ util/isensor.c - cosmetic changes in RawToFloat(),
+ added -e (same as -b) to follow child MCs
+ util/isol.c - increased -i filename size from 40 to 80
+ util/isel.c - find_msg_sev() detects severity for syslog messages
+ util/ialarms.c - show up to 8 disk LEDs (previously 6)
+ util/oem_intel.c - detect_capab_intel: return max# disks based on product ID
+ util/idiscover.c - add -m option for raw packets to display MAC addrs
+ util/ireset.c - only set boot opts if not default device
+ util/ipmilan.c - try MD2 or NONE if default auth type not allowed.
+ util/ipmidir.c - allow set_max_kcs_loops for BSD also
+ util/ipmicmd.c - do set_max_kcs_loops for BSD also
+ util/ipmicmd.h - define set_max_kcs_loops for BSD also
+ util/ipmiutil.mak - add ipmi_sample.exe to TARG_EXE
+ util/ihpm.c - fixed percent to display dots during upgrade,
+ added more debug messages
+ doc/ipmi.init.basic - added comments
+ doc/iwdt.8 - include -q description
+ doc/idiscover.8 - include -m description
+ doc/ifru.8 - include -e description
+ doc/isensor.8 - include -e description
+ doc/UserGuide - updated Windows install instructions wrt drivers,
+ updated section 4.2 with new sample output,
+ updated section 4.8 SOL Upstart instructions,
+ updated man pages
+ ipmiutil-2.7.5 contains:
+ ipmiutil (ipmiutil) ver 2.75
+ ...(various subcommands) ver 2.75
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.02
+ idiscover (ipmiutil discover) ver 1.7
+ ipmi_port (ipmi_port) ver 1.2
+
+05/09/11 ARCress ipmiutil-2.7.6 changes
+ util/isensor.c - show Thresholds based on readable (not settable) bits,
+ handle unit type bit for percent
+ util/ipmilan.c - add ipmi_lan_set_timeout()
+ util/icmd.c - add -t to set lan timeout
+ util/igetevent.c - add SmsOs func 3 to send NMI
+ util/oem_kontron.c - added ktc5520_post decoding
+ util/ievents.c - added more GenID decoding
+ util/ipmicmd.c - added my_devid defaults
+ util/mem_if.c - added debug messages
+ util/oem_intel.c - fixup for Relay bits on CG2100
+ util/isel.c - allow filtering by severity with -s
+ util/ipmi_port.c - cleanup syntax warnings
+ util/ilan.c - add support for VLAN/Cipher params
+ util/iconfig.c - add support for VLAN/Cipher params
+ doc/isel.8 - change to document -s
+ util/ipmims.cpp - fix for WIN64-unsafe logic from Jay Krell
+ cleaned up compile warnings flagged by Jay Krell in:
+ igetevent.c, imbapi.c, ipmims.cpp, ievents.c, ifru.c, mem_if.c,
+ ievents.c, ifirewall.c, igetevent.c, oem_kontron.c/.h
+ cleaned up WIN64 /W3 compile warnings in util/*.c
+ util/ipmiutil2.mak - updates
+ util/mem_if_cpp.cpp - new, wrapper for build.exe, includes mem_if.c
+ test/retro.sh - new, retrofit subcommand naming for pre-2.6.0 scripts
+ ipmiutil-2.7.6 contains:
+ ipmiutil (ipmiutil) ver 2.76
+ ...(various subcommands) ver 2.76
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.02
+ idiscover (ipmiutil discover) ver 1.7
+ ipmi_port (ipmi_port) ver 1.3
+
+06/06/11 ARCress ipmiutil-2.7.7 changes
+ util/oem_intel.c - move Aborting message out for BMC TAM
+ util/ialarms.c - move Aborting message in for BMC TAM
+ util/ifru.c - fixed bug with -a and not -b (introduced in 2.7.5),
+ util/icmd.c - add -k to check IPMI access, driver type
+ util/ipmicmd.h - added CMD_GET_SESSION_INFO
+ util/ihealth.c - add get_session_info for -s (use -l for lan stats)
+ util/ipmi_port.c - added signal init
+ util/igetevent.c - added signal init
+ util/ilan.c - send snmp error message to stdout, not stderr
+ util/iconfig.c - send snmp error message to stdout, not stderr
+ doc/ihealth.8 - document -s, -l options
+ doc/ipmiutil.spec - description update, added gcc/gcc-c++ to BuildRequires
+ doc/ipmi_port.sh - $localfs -> $local_fs
+ doc/ipmiutil_asy - $remotefs -> $remote_fs, use cmd -k to detect driver
+ doc/ipmiutil_evt - $remotefs -> $remote_fs, use cmd -k to detect driver
+ doc/ipmiutil_wdt - $remotefs -> $remote_fs, use cmd -k to detect driver
+ doc/UserGuide - resync'd with man pages
+ test/unittest.sh - allow getevt timeout to count as success
+ Makefile.am - enforce UserGuide permissions in make tarball
+ configure.in - for WRL, enforce -DSKIP_MD2
+ ipmiutil-2.7.7 contains:
+ ipmiutil (ipmiutil) ver 2.77
+ ...(various subcommands) ver 2.77
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.02
+ idiscover (ipmiutil discover) ver 1.7
+ ipmi_port (ipmi_port) ver 1.4
+
+09/13/11 ARCress ipmiutil-2.7.8 changes
+ util/iwdt.c - check for pretime >max 255 & set to 255.
+ util/ilan.c - show Intel IPv6 params, include set MAC addr with -D,
+ add ngood counter, call find_ifname,
+ add -f to set arp_ctl
+ util/iconfig.c - add ngood counter, call find_ifname,
+ skip errors if optional SetPef(9), SetUserName(same)
+ util/ireset.c - cleanup of usage message
+ util/isel.c - check & fix if vsize reports 0
+ util/ialarms.c - added ALONE compile flag
+ util/ievents.c - added decode_sel_intel for PCIe AER events,
+ added decode_mem_intel for DIMMs if remote
+ util/oem_intel.c - added decode_sel_intel for PCIe AER events,
+ added decode_mem_intel for DIMMs
+ util/isensor.c - added -o to output memory DIMM info, sdr getall=ffff
+ util/igetevent.c - added write_syslog when exiting
+ util/idiscover.c - added find_ifname()
+ util/ipicmg.c - updated with PICMG 2.3
+ util/ipmicmd.c - clear driver type in ipmi_close_()
+ util/ipmilan.c - moved some subroutines to subs.c,
+ added ipv6 support - thanks Rajaganesh87
+ util/ipmilan.h - increased RQ_LEN_MAX from 25 to 200
+ util/ipmilanplus.c - moved some subroutines to subs.c
+ util/subs.c - new, consolidate subroutines from other *.c files
+ util/oem_dell.c - new, Dell OEM functions
+ util/oem_dell.h - new, Dell OEM functions
+ util/ipmiutil.c - added delloem reference
+ util/ipmiutil.h - added delloem reference
+ util/Makefile.am - add oem_dell
+ util/ipmiutil.mak - add oem_dell
+ util/ihpm.c - updated to v1.08
+ util/ipmidir.c - return error if data len > DATA_BUF_SIZE (was truncate)
+ util/ipmidir.h - increase DATA_BUF_SIZE from 64 to 255 (IPMI_REQBUF_SIZE)
+ util/ipmi*.c/.h - changed ipmi_cmd*(uchar sdata -> int sdata)
+ util/itsol.c - new, for Tyan SOL
+ util/itsol.h - new, for Tyan SOL
+ util/ihealth.c - added WinBond/SuperMicro X8SIL
+ util/oem_supermicro.c - added more SuperMicro functions
+ util/isol.c - use kontron sol_send max = 74, default others to 45.
+ util/ifru.c - fixed fault with -a if asset present in non-baseboard
+ lib/lanplus/helper.c - moved some subroutines to subs.c
+ lib/lanplus/lanplus.c - added ipv6 support - thanks Rajaganesh87
+ test/testipmi.sh - fixed getevt success check via runcmdr
+ doc/ilan.8 - more description for -d
+ doc/ireset.8 - cosmetic cleanup
+ doc/isensor.8 - added -o description
+ doc/idelloem.8 - new, document Dell OEM functions
+ doc/UserGuide - sync'd with current man pages
+ doc/ipmiutil_asy.service - new, systemd service for ipmiutil_asy
+ doc/ipmiutil_evt.service - new, systemd service for ipmiutil_evt
+ doc/ipmiutil_wdt.service - new, systemd service for ipmiutil_wdt
+ doc/ipmi_port.service - new, systemd service for ipmi_port
+ doc/ipmiutil.env - new, environment for ipmiutil systemd
+ doc/ipmiutil.pre - new, preinstall for ipmiutil systemd
+ doc/ipmiutil.setup - new, setup for ipmiutil ipmi_port systemd
+ doc/ipmiutil.spec - added systemd scripts, idelloem.8
+ doc/Makefile.am - added systemd scripts, idelloem.8
+ hpiutil/hpiutil.spec - updated version to 1.1.11, updated header syntax
+ hpiutil/hpiinit.sh - use /var/run if /var/lock/subsys does not exist
+ fixes bug# 3400659
+ ipmiutil-2.7.8 contains:
+ ipmiutil (ipmiutil) ver 2.78
+ ...(various subcommands) ver 2.78
+ oem_dell (ipmiutil delloem) ver 2.78
+ itsol (ipmiutil tsol) ver 2.78
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.08
+ idiscover (ipmiutil discover) ver 1.8
+ ipmi_port (ipmi_port) ver 1.4
+
+10/04/11 ARCress ipmiutil-2.7.9 changes
+ util/isensor.c - check for DIMM disabled bit 0x0100,
+ add sensor type 0x28 for MC Health,
+ fix RawToFloat for ARM cross-compiler
+ util/ilan.c - show param 102 better for S2600CP with -c
+ util/oem_supermicro.c - add return(rv) at line 182 to fix compile warning
+ util/oem_dell.c - fix data size to 10 in CheckSetLEDSupport
+ util/ipmilan.c - resolve compiler warnings,
+ add #if CROSS_COMPILE for gethostbyname
+ util/idiscover.c - add #if CROSS_COMPILE for gethostbyaddr
+ util/subs.c - resolve compiler warnings
+ util/ievents.c - move Intel DIMM code to decode_mem_intel,
+ added BMC Drive Slot event decoding if not HSC
+ util/oem_intel.c - add more to decode_mem_intel,
+ add is_thurley(), is_romley(), is_lan2intel()
+ util/ilan.c - add Romley IDs to S2600, skip PEF if disabled,
+ preferred SOL baud 115200
+ util/isol.c - use is_lan2intel() for lan2i method
+ util/ipmicmd.c - show invalid -F string in error message
+ util/ipmilanplus.c - use is_lan2intel() in ipmi_oem_active()
+ lib/lanplus/lanplus.c - resolve compiler warning
+ doc/checksel - also save a copy of the SEL in /var/lib/ipmiutil
+ doc/Makefile.am - do not make *.service files executable
+ configure.in - separate two sed -i subst's if MontaVista,
+ add static/CROSS_COMPILE if --host=xxx, e.g. ARM
+ INSTALL - add build instructions for ARM
+ ipmiutil-2.7.9 contains:
+ ipmiutil (ipmiutil) ver 2.79
+ ...(various subcommands) ver 2.79
+ oem_dell (ipmiutil delloem) ver 2.79
+ itsol (ipmiutil tsol) ver 2.79
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.08
+ idiscover (ipmiutil discover) ver 1.8
+ ipmi_port (ipmi_port) ver 1.4
+
+10/28/11 ARCress ipmiutil-2.7.9-2 changes (patched)
+ util/isensor.c - fix Therm Margin reading bug 3429298 from 2.7.9,
+
+11/10/11 ARCress ipmiutil-2.7.9-3 changes (patched)
+ doc/ipmiutil.spec - copy checksel to cron.daily only if IPMI is enabled
+ which fixes RH bug #752319
+ doc/checksel - do nothing if IPMI SEL is not enabled
+ doc/Makefile.am - do not auto-install checksel into cron.daily
+ doc/Makefile.in - do not auto-install checksel into cron.daily
+ doc/Makefile - do not auto-install checksel into cron.daily
+
+12/16/11 ARCress ipmiutil-2.8.0 changes
+ util/iconfig.c - use enabled_users instead of max_users for SOL.
+ util/ievents.c - interpret Proc Config events if 0x83,
+ add fcanonical output,
+ handle more discrete Temp events for Romley,
+ fix b3 error in Memory DIMM decoding,
+ fix threshs string if -p
+ util/ilan.c - fix PefDesc for strcat, (fixes RH bug#804723)
+ bounds check GetPefCapabilities,
+ increase MAXPEF to 41 for Dell PE 1950,
+ use bmcsubnet by default if not user-specified,
+ skip SOL baud if Intel Romley,
+ add -K to set Kontron IPMI hostname
+ util/ipmicmd.c - more bounds checking in set_lan_options
+ util/ipmicmd.h - comment headers for set_lan_options, etc.
+ util/isensor.c - fix Therm Margin reading bug 3429298 from 2.7.9,
+ compare both num & sa before setting thresholds,
+ add Romley HSBP sensor interpretations,
+ document -q option in usage,
+ add call to decode_sensor_supermicro
+ util/isel.c - add -n for nominal/canonical output format
+ util/subs.c - added str2uchar, atob routines with error msgs
+ util/ihealth.c - added Supermicro X9SCA product id decoding,
+ added special Kontron FW version cmd
+ util/ipmicmd.c/h - change get_node to get_nodename
+ util/*.c - converted strtol/atoi to atob if one-byte result
+ util/oem_supermicro.c - add decode_sensor_/decode_sel_supermicro()
+ util/ihpm.c - handle if Activation compcode==0xD5
+ util/idcmi.c - new, for DCMI commands
+ util/idcmi.h - new, for DCMI commands
+ util/Makefile.sample - new, for ipmiutil-devel
+ util/Makefile.am - changes to install ipmiutil-devel files,
+ do not include lanplus in libipmiutil by default
+ util/iconfig.c - do not call atob if beyond ':'
+ util/subs.c - fix str2uchar for 08,09.,
+ fix lprintf to use fplog if fdbglog
+ util/isol.c - send chassis soft reset for ctl+alt+del (~D)
+ util/ievents.h - new, define public routines
+ util/ipmilan.c - handle recvfrom errors better if bad MC stack
+ util/oem_sun.c - remove extra usage message if error
+ util/itsol.c - handle Windows compile warnings
+ doc/isensor.8 - add -q option to show thresholds in d:d:d format
+ doc/ilan.8 - document -K for hostname, etc.
+ doc/ipmiutil.spec - copy checksel to cron.daily only if IPMI is enabled
+ which fixes RH bug #752319,
+ changed Summary line,
+ added libtool to BuildRequires:,
+ added ipmiutil-devel package files
+ doc/Makefile.am - do not auto-install checksel into cron.daily
+ doc/checksel - do nothing if IPMI SEL is not enabled
+ doc/install.cmd - changed install path
+ doc/uninstall.cmd - changed install path
+ doc/install.vbs - new, for MSI package
+ doc/uninstall.vbs - new, for MSI package
+ debian/postinst - copy checksel only if IPMI is enabled
+ debian/control - changes to description
+ debian/prerm - remove checksel if present in /etc/cron.daily
+ doc/UserGuide - added section 8.x for building ipmiutil,
+ moved Related Information to section 9
+ test/testipmi.sh - skip serial tests if not supported
+ test/unittest.sh - add Memory DIMM event decoding tests
+ util/ipmi_sample.mak - new, makefile for ipmi_sample.exe
+ buildsamp.cmd - new, script to build ipmi_sample.exe
+ configure.in - add --enable-liblanplus parameter
+ ipmiutil-2.8.0 contains:
+ ipmiutil (ipmiutil) ver 2.80
+ ...(various subcommands) ver 2.80
+ idcmi (ipmiutil dcmi) ver 2.80
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.09
+ idiscover (ipmiutil discover) ver 1.8
+ ipmi_port (ipmi_port) ver 1.4
+
+02/10/2012 ARCress ipmiutil-2.8.1 changes
+ util/isensor.c - GetSensorReading: include channel/bus for ME,
+ use isensor.h,
+ added decode_entity_id() if -t,
+ handle CritInterrupt 0x0A,0x0B,
+ handle HP, Sun returning 0xD4 for fdevsdrs
+ util/ihealth.c - change format of ME firmware version,
+ add Quanta S99Q vendor/product interpretation,
+ added system_info command data,
+ added list of IPMI LAN channels
+ util/ipmicmd.c - if DRV_MV, do not use ipmi_cmd_ipmb for ME
+ util/ipmidir.c - include bus in ProcessMessage (for ME)
+ util/iconfig.c - show extra LanParam IP address comment,
+ add lan_failover, system_info as SystemParams,
+ cleanup some clutter
+ util/idcmi.c - add get_power_read*, set_power_limit* routines
+ from Rajaganesh87,
+ add support for dcmi_get_sensor_info,
+ add dcmi_set_asset_tag, dcmi_set_mc_id,
+ util/isensor.h - new, common sensor subroutine definitions
+ util/oem_sun.c - use isensor.h
+ util/oem_dell.c - use isensor.h,
+ applied 01-powermonitor-bigendian.patch
+ already included 02-fix-overflow.patch
+ applied 03-delloem-help.patch
+ util/oem_intel.c - add decode_sensor_intel_nm for ME NM sensors,
+ add lan_failover_intel() routine
+ util/oem_quanta.c - add interpretation for Quanta S99Q OEM sensor/sel
+ util/oem_supermicro.c - add decoding for CPU Overheat deassert events
+ util/ifru.c - for Dell BMC, allow scan with user privilege,
+ for Dell R415, add 6-bit ASCI decoding,
+ fixed fdevsdrs mismatch for Dell R610
+ util/ipmilan.c - add get_rand() for init_out_seq,
+ handle if per-message auth disabled (Dell PE R415)
+ util/ilan.c - add lan_failover_intel if -y
+ util/ievents.c - add -o to specify vendor IANA ID
+ util/iserial.c - limit show_users to 5 to avoid 0xCC warnings
+ doc/ihealth.8 - added -mnopq descriptions
+ doc/ilan.8 - added -y description
+ doc/itsol.8 - new
+ doc/idcmi.8 - new
+ doc/UserGuide - updated man pages
+ test/testipmi.sh - copy PASS/FAIL messages in output log
+ configure.in - use --libdir= option for cross-compiles,
+ fix PKG_DIR for openSuSE 12
+ ipmiutil-2.8.1 contains:
+ ipmiutil (ipmiutil) ver 2.81
+ ...(various subcommands) ver 2.81
+ idcmi (ipmiutil dcmi) ver 2.81
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.09
+ idiscover (ipmiutil discover) ver 1.8
+ ipmi_port (ipmi_port) ver 1.4
+
+03/12/2012 ARCress ipmiutil-2.8.2 changes
+ doc/* - moved scripts from here
+ scripts/* - moved scripts to here
+ scripts/Makefile.am - new, for script handling
+ scripts/ipmiutil_asy - use -b instead of -t0
+ scripts/ipmiutil_asy.service - use -b instead of -t0
+ doc/Makefile.am - remove script handling
+ doc/isensor.8 - added 'Typ' header description
+ doc/ipmiutil.spec - use systemd scripts if systemctl, and
+ use SYSV init scripts otherwise (RH bug 789702),
+ move ipmiutil from /usr/sbin to /usr/bin,
+ add %req_systemd and --enable-systemd for suse
+ util/ipmiva.c - removed, obsolete valinux driver
+ util/ipmiva.h - removed, obsolete valinux driver
+ util/ipmi_ioctls.h - removed, obsolete valinux driver
+ util/ipmignu.c - removed, obsolete libfreeipmi interface code
+ util/Makefile.am - remove ipmiva.c, ipmignu.c drivers,
+ move ipmiutil from /usr/sbin to /usr/bin
+ util/ievents.c - handle deassert/ok for discrete Battery Fail
+ util/oem_hp.c - new, add decode_sensor_hp for discrete readings
+ on HP ProLiant servers
+ util/isensor.c - call decode_sensor_hp if vendor==HP
+ util/ipmicmd.c - removed valinux, libfreeipmi from messages
+ util/oem_kontron.c - fix get_fru_area_str NULL pointer check
+ util/oem_intel.c - add more Romley product IDs and descriptions
+ fixes bug# 3497948,
+ added logic to enc_leds_intel routines for Romley
+ util/ihealth.c - use intel_romley_desc for Romley descriptions
+ util/ialarms.c - added -f option to turn off all disk leds
+ lib/lanplus/lanplus.c - fix bridged lanplus session close failures
+ freeipmi/* - removed unused files
+ configure.in - handle scripts subdir, remove va/gnu,
+ handle if %_initrddir does not exist,
+ add enable-systemd parameter, installs %_unitdir
+ ipmiutil-2.8.2 contains:
+ ipmiutil (ipmiutil) ver 2.82
+ ...(various subcommands) ver 2.82
+ idcmi (ipmiutil dcmi) ver 2.82
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.09
+ idiscover (ipmiutil discover) ver 1.8
+ ipmi_port (ipmi_port) ver 1.4
+
+04/23/2012 ARCress ipmiutil-2.8.3 changes
+ util/oem_intel.c - fix Romley DIMM decoding with intel_mem_s2600,
+ add Version Change event OEM detail,
+ added get_power_restore_delay_intel()
+ util/ilan.c - additional safeguards in PefDesc,
+ fix setting PEF/Alert (introduced in 2.7.9),
+ use previous dest mac if not resolved.
+ util/ihealth.c - added error cases with decode_selftest,
+ format romley prodstr with (),
+ fix #3516915 with more chassis status decoding,
+ added call to get_power_restore_delay_intel
+ util/ipmilan.c - handle some compile warnings
+ util/ievents.c - change some NMFW/ME event descriptions
+ util/isensor.c - show Entity ID if -v (but not -t),
+ move Dell Discrete Voltage to oem_dell.c to fix
+ Romley VR Watchdog,
+ added get_sdr_file routine for ipmi_sample2
+ util/oem_dell.c - fix #3514908 powerconsumption cannot find error,
+ added decode_sel_dell() merged from patches by
+ Srinivas_G_Gowda,
+ fix #3514925 LOM MAC display error,
+ added getled function to read ID LED,
+ util/oem_newisys.c - new, decode_sel_newisys()
+ util/oem_kontron.c - added sensor types 0x70, 0x71
+ util/ipmi_sample.c - v0.4, added GET_SENSORS case
+ util/ireset.c - add -k for ColdReset, -m for MC, use -v for DVD/CD
+ util/Makefile.am - added GET_SENSORS case for ipmi_sample2
+ util/ipmiutil.mak - added GET_SENSORS case for ipmi_sample2
+ util/imbapi.c - reduce MAX_RETRIES from 3 to 2, do ipmb for ME_BUS
+ util/ilan.c - added GetFirstIP for WIN32
+ util/idiscover.c - call GetFirstIP for WIN32 if -a
+ util/AnsiTerm.cpp - default AutoWrap = true in ResetTerm
+ doc/ireset.8 - document -k, -m, -v
+ doc/idiscover.8 - document -a defaults better
+ doc/UserGuide - resync with man pages
+ doc/ipmiutil.spec - skip chkconfig if systemd
+ debian/prerm - remove /etc/cron.daily/checksel if present
+ configure.in - fix error checking for PKG_DIR
+ ipmiutil-2.8.3 contains:
+ ipmiutil (ipmiutil) ver 2.83
+ ...(various subcommands) ver 2.83
+ idcmi (ipmiutil dcmi) ver 2.83
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.09
+ idiscover (ipmiutil discover) ver 1.9
+ ipmi_port (ipmi_port) ver 1.4
+
+06/13/2012 ARCress ipmiutil-2.8.4 changes
+ configure.in - detect HP-UX and set compile options,
+ check for ltmain.sh, else beforeconf.sh
+ util/*.c - #ifdef HPUX, skip getopt since it is in stdio.h,
+ handle DLPI for HPUX instead of SIOC.
+ TODO: We need someone to test this on HPUX.
+ util/ilan.c - prioritize existing Dest IP if not using -A,
+ default to arp_ctl 0x03 if Intel Romley
+ util/idcmi.c - fix rlen, argc, priv for bug#3523229 (DCMI 1.1)
+ fix activate param check for bug#3526523
+ util/ihealth.c - move _sysinfo routines from here,
+ call get_hsbp_version_intel if Romley
+ util/subs.c - move _sysinfo routines to here
+ util/ipmicmd.c - add -Fibm option
+ util/ipmilan.c - if -Fibm, do not get_rand for init_out_seq
+ util/ireset.c - set OEM boot option if HP for bug#3527355,
+ add -i/-j for boot initiator mailbox string
+ fix printf bug #3534551
+ util/ifru.c - refine calculation for Mfg DateTime
+ util/ievents.c - add Intel CATERR decoding
+ util/oem_dell.c - merged 01-powermonitor-bigendian.patch,
+ merged 03-delloem-help.patch,
+ fix debug printf at line 4289 by adding %x
+ util/Makefile.am - build ipmi_sample2 with sensor,fru,sel
+ install ipmicmd.h into $(includedir),
+ use $objdir to fix parallel build bug 3523822,
+ add LANPLUS_LIB to dependencies
+ doc/UserGuide, doc/*.8 - reflect that cipher suites are 0 thru 17
+ doc/ireset.8 - added -i/-j descriptions
+ doc/ipmiutil.spec - devel virtually provides static,
+ devel ipmicmd.h into %_includedir
+ doc/rh_spec.patch - new, customize spec file for Red Hat bug#818910
+ ipmiutil-2.8.4 contains:
+ ipmiutil (ipmiutil) ver 2.84
+ ...(various subcommands) ver 2.84
+ idcmi (ipmiutil dcmi) ver 2.84
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.09
+ idiscover (ipmiutil discover) ver 1.9
+ ipmi_port (ipmi_port) ver 1.4
+
+08/13/2012 ARCress ipmiutil-2.8.5 changes
+ util/oem_dell.c - add 'static void' to ipmi_delloem_getled_usage()
+ util/idcmi.c - fixes for bug#3526523
+ util/ipmicmd.h - define Cisco IANA number
+ util/subs.c - include Cisco in manufacturers list
+ util/ihealth.c - handle Cisco get_chan_auth bug#3535196,
+ change to 'Sec Operating System' in sysinfo
+ util/ifru.c - change to 'Sec Operating System' in sysinfo
+ util/mem_if.c - add get_Chassis_Sernum()
+ util/ilan.c - add '-L list' show_chans function
+ util/oem_intel.c - set to 4 disk LEDs if CG1200
+ util/imbapi.c - fixed rsp offset for ipmb bridged cmds
+ util/isensor.c - fixed module presence sensor decoding
+ util/ievents.c - simplify redundancy & presence decoding,
+ add board presence decoding,
+ decode Intel OEM PCI bus:dev:func data
+ lib/lanplus/lanplus.c - fixed 2 possible memory leaks,
+ patch contributed by Oliver Stoneberg
+ doc/ilan.8 - mention RMM chan 3, add -L list description
+ scripts/checksel - fix /usr/sbin to /usr/bin for bug#3538998
+ debian/dirs, postinst - fix /usr/sbin to /usr/bin for binary
+ buildwin.cmd - cleanup, simplify Windows build (Oliver Stoneberg)
+ buildwin2.cmd - cleanup, simplify Windows build
+ buildsamp.cmd - cleanup, simplify Windows build
+ cleanwin.cmd - cleanup, simplify Windows build
+ lib/ipmilib.mak - cleanup, simplify Windows build
+ lib/lanplus/ipmiplus.mak - cleanup, simplify Windows build
+ util/ipmiutil.mak - cleanup, simplify Windows build (Oliver Stoneberg)
+ util/ipmiutil2.mak - cleanup, simplify Windows build
+ util/ipmi_sample.mak - cleanup, simplify Windows build
+ util/igetevents.c - skip mkdaemon if ppid==1
+ util/ilan.c - fix bug #3554862 for IBM non-conformance
+ configure.in - set CFLAGS if --enable-systemd
+ ipmiutil-2.8.5 contains:
+ ipmiutil (ipmiutil) ver 2.85
+ ...(various subcommands) ver 2.85
+ idcmi (ipmiutil dcmi) ver 2.85
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.09
+ idiscover (ipmiutil discover) ver 1.9
+ ipmi_port (ipmi_port) ver 1.4
+
+10/08/2012 ARCress ipmiutil-2.8.6 changes
+ doc/ipmiutil.spec - added F18 systemd macros
+ test/ipmievt.sh - get fresh sensor readings before calculations
+ util/ievents.c - added -n to generate a New platform event,
+ added SENSORS_OK flag for ipmi_sample_evt
+ util/isensor.c - show correct sensor type for EvtOnly sensors
+ util/oem_intel.c - dont get disk LEDs if Intel TSRMT2,
+ remove 'Fatal' from AER descriptions,
+ added a few more S5000 POST code descriptions
+ util/igetevents.c - ppid==1 in mkdaemon is ok
+ util/ihealth.c - show Romley BMC build version
+ util/oem_dell.c - added 'passwordpolicy' command for Dell C6220
+ util/ipmi_sample_evt.c - new, sample app to get events
+ util/isel.c - moved syslog routines to subs.c
+ util/subs.c - inserted syslog routines
+ util/isol.c - add -n option for payload instance number
+ util/imbapi.c - only include DllMain if IMBDLL flag
+ util/ialarms.c - added TEST_ENC compile flag for ialarms_enc,
+ fixed case for old Intel/NSC TIGPT1U
+ util/Makefile.am - add ipmi_sample_evt, ialarms_enc
+ util/Makefile.sample - add ipmi_sample_evt
+ util/ipmi_sample.mak - add ipmi_sample_evt.exe
+ util/ipmiutil.mak - add ipmi_sample_evt.exe, ipmiutillib.dll
+ util/ipmiutil2.mak - add ipmi_sample_evt.exe
+ util/ipmiutillib.def - new, for ipmiutillib.dll
+ ipmiutil-2.8.6 contains:
+ ipmiutil (ipmiutil) ver 2.86
+ ...(various subcommands) ver 2.86
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.09
+ idiscover (ipmiutil discover) ver 1.9
+ ipmi_port (ipmi_port) ver 1.4
+
+12/13/2012 ARCress ipmiutil-2.8.7 changes
+ Always compile Windows with Visual Studio (fixes bug#3592308)
+ scripts/ipmi_info - new, to set IPMI System Info if supported
+ scripts/Makefile.am - added ipmi_info
+ doc/ipmiutil.spec - added ipmi_info
+ util/ipmims.cpp - fix memory leak
+ lib/lanplus/lanplus.c - if HP, don't build any v1.5 commands
+ util/ipmilanplus.c - add hp case to ipmi_oem_active()
+ configure.in - fixup for HP-UX case
+ util/isol.c - add -k for keepalive timeout
+ util/isensor.c - revised output format for -c
+ util/ipmilanplus.c - fix keepalive data_len in Windows (#3592308)
+ util/ialarms.c - add -e to skip disk enclosure LEDs
+ util/oem_intel.c - add rcmd method for Romley disk LEDs
+ ipmiutil-2.8.7 contains:
+ ipmiutil (ipmiutil) ver 2.87
+
+12/17/2012 ARCress ipmiutil-2.8.7 changes
+ doc/ipmiutil.spec - fixed ipmi_info/init typo
+
+02/05/2013 ARCress ipmiutil-2.8.8 changes
+ util/ihealth.c - caveats for VENDOR_SUPERMICROX, product X8SIU
+ util/ilan.c - caveats for VENDOR_SUPERMICROX
+ util/iconfig.c - caveats for VENDOR_SUPERMICROX
+ util/iserial.c - caveats for VENDOR_SUPERMICROX
+ util/isensor.c - caveat if sensor reading not present
+ util/oem_supermicro.c - added Power Supply sensor status
+ util/isel.c - show record id if compcode = 0xcb
+ util/ireset.c - added EFI compile flags
+ util/ievents.c - handle fake SMS_OS threshold events
+ util/ipmiutil64.mak - NEW, for Win x64 builds
+ lan/lanplus/lanplus.c - remove asserts
+ lan/lanplus/lanplus_crypt.c - x64 HMAC tweaks and remove asserts
+ lan/lanplus/lanplus_crypt_impl.c - handle x64 types in lanplus_HMAC
+ doc/UserGuide - add 'Run as administrator' note in 5.1 Win Install
+ buildwin.cmd - detect if VC is Win x64 and use ipmiutil64.mak
+ test/unittest.cmd - NEW, ipmiutil unit test for Windows
+ ipmiutil-2.8.8 contains:
+ ipmiutil (ipmiutil) ver 2.88
+
+04/08/2013 ARCress ipmiutil-2.9.0 changes
+ util/ihealth.c - set SuperMicro product 0x60B to 'X8SIA',
+ added 0x0705 as 'X9DR7'
+ util/ilan.c - dont show extra dest params if invalid, IP dots,
+ add interpretation for Cipher Suites
+ util/ipmicmd.c - update Solaris driver message for lipmi
+ util/ipmi_sample.c - added GetSensorReading sample logic,
+ added -l option for looping on sensor readings,
+ added -f option to iterate on node list
+ util/isensor.h - added decode_comp_reading
+ util/ipmilan.c - added ipmi_flush_lan, handle multiple opens,
+ added busy_tries for Node Busy error
+ util/ipmilan.h - added ipmi_flush_lan
+ util/ipmilanplus.c - added LAN2_STRUCT for multiple opens,
+ added open logic to close first if new nodename.
+ lan/lanplus/lanplus.c - ipmi_req_entries=NULL in ipmi_req_clear_entries
+ buildwin.cmd - cosmetic findstr change
+ buildwin2.cmd - updated for Win x64 builds (without lanplus)
+ util/ipmiutil.mak - cosmetic change
+ util/ipmiutil64.mak - cosmetic change
+ util/ipmiutil2.mak - updated for sample builds, clarity
+ util/ipmiutil2-64.mak - NEW, for Win x64 builds
+ util/ipmi_sample.mak - added MARCH for IX86 or X64
+ util/ievents.c - add decode_mem_supermicro call,
+ handle parse_lan_options better.
+ util/oem_supermicro.h - new, supermicro routines
+ util/oem_supermicro.c - update decode_sel_supermicro,
+ added decode_mem_supermicro,
+ added i_smcoem, ipmi_smcoem_main
+ util/ipmiutil.c - added i_smcoem
+ util/ipmiutil.h - added i_smcoem
+ util/iseltime.c - new, show/sync system time and SEL time
+ util/subs.c - added strlen_() wrapper for compile warnings
+ util/ipmicmd.h - added strlen_()
+ util/Makefile.am - add iseltime, set LD_SAMX for libipmiutil.a
+ configure.in - build libipmiutil with lanplus by default
+ doc/iseltime.8 - new, man page for iseltime
+ doc/ismcoem.8 - new, man page for ismcoem
+ doc/UserGuide - updated Windows file list in section 5.0,
+ add iseltime man page
+ doc/ipmiutil.spec - add autoconf to %build for aarch64/ARM64 bug 925593
+ ipmiutil-2.9.0 contains:
+ ipmiutil (ipmiutil) ver 2.90
+ ...(various subcommands) ver 2.90
+ iseltime (iseltime) ver 2.90
+ ismcoem (ipmiutil smcoem) ver 2.90
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.09
+ idiscover (ipmiutil discover) ver 1.9
+ ipmi_port (ipmi_port) ver 1.4
+
+05/15/2013 ARCress ipmiutil-2.9.1 changes
+ configure.in - changes to support MACOS, HAVE_SOCKLEN_T
+ lib/lanplus/lanplus_defs.h - changes for HAVE_SOCKLEN_T for MACOS
+ lib/lanplus/lanplus.c - #ifdef MACOS
+ util/*.c - getopt includes for MACOS, other MACOS ifdefs
+ util/isel.c - change header if -n/-c, move delete/clear from -c to -d,
+ add -u to use UTC sel times.
+ util/ievent.c - define header string if -n, add format_event(),
+ handle fcanonical uniformly
+ util/ipmi_sample.c - changed nsec from 5 to 10 by default, added -i
+ util/ipmiutil.mak - build ipmi_sample2.exe by default
+ util/ipmiutil64.mak - build ipmi_sample2.exe by default
+ util/ihealth.c - add better HP product code names (feat#6)
+ util/ifru.c - handle DDR3 format SPD data
+ util/igetevent.c - use offset 3 for sel_time
+ util/oem_dell.c - some cleanup, reorder ActiveLOM_Strings
+ util/oem_*.c - call format_event to handle fcanonical uniformly
+ util/isensor.c - fix parse_idx for 3 hex digits from -i,
+ add -j to Jumpstart SDR cache from file
+ util/ihealth.c - add 2 more SuperMicro product ids
+ util/oem_supermicro.c - added get/set lanport
+ util/*.c - clean up some compile warnings
+ scripts/checksel - use sel -d
+ scripts/checksel.cmd - use sel -d
+ scripts/evt.sh - add sample snmptrap logic
+ scripts/Makefile.am - add ipmi.init.basic
+ doc/ipmiutil.spec - add ipmi.init.basic
+ doc/isel.8 - change -c to -d, add new -c/-n description, add -u
+ doc/UserGuide - updated with current man pages
+ ipmiutil-2.9.1 contains:
+ ipmiutil (ipmiutil) ver 2.91
+ ...(various subcommands) ver 2.91
+ ismcoem (ipmiutil smcoem) ver 2.91
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.09
+ idiscover (ipmiutil discover) ver 1.9
+ ipmi_port (ipmi_port) ver 1.4
+
+10/09/2013 ARCress ipmiutil-2.9.2 changes
+ util/isensor.c - set default -t tag to "Thresholds" instead of "",
+ added find_sdr_by_id(),
+ fixed thresholds.sh script for cmd if recid==0
+ util/ilan.c - if disabling SuperMicro, set failover off also
+ util/isel.c - fix -c option for canonical
+ util/ipmiutil.c - marked iekanalyzer as deprecated
+ debian/* - updated for debhelper 9 builds by Alex Waite
+ debian/copyright - updated to DEP-5 format with file-level detail
+ debian/ipmiutil.lintian-overrides - added gpl-openssl warning override
+ lib/Makefile - added check: for debian
+ scripts/Makefile.am - added check: for debian
+ scripts/ipmi.init.basic - added checks if ipmi is builtin
+ doc/Makefile.am - added check: for debian
+ doc/UserGuide - marked iekanalyzer as deprecated
+ doc/iekanalyzer.8 - marked iekanalyzer as deprecated
+ doc/ipmiutil.spec - add dummy echo in %post in case of a command error
+ configure.ac - renamed from previous configure.in
+ lib/lanplus/lanplus_dump.c - reduce rakp2 debug output (CVE-2013-4786)
+ lib/lanplus/lanplus_crypt.c - reduce rakp2 debug output (CVE-2013-4786)
+ util/ipmims.cpp - fixed Win2012 x64 core in SafeArrayDestroy
+ util/igetevent.c - added -c for canonical event formats, get_evt_method
+ doc/igetevent.8 - added -c description
+ util/oem_supermicro.c - fix memory decoding to use data2 byte
+ util/Makefile.am - add $OS_CF for ievents, idiscover, ipmi_port
+ configure.ac - add fortify flags to OS_CF if supported
+ lib/lanplus/lanplus.c - fix possible mem leak, line 2195 (entry)
+ lib/lanplus/lanplus_crypt.c - fix possible mem leak, line 842 (padded_input)
+ ipmiutil-2.9.2 contains:
+ ipmiutil (ipmiutil) ver 2.92
+ ...(various subcommands) ver 2.92
+ ismcoem (ipmiutil smcoem) ver 2.92
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.09
+ idiscover (ipmiutil discover) ver 1.9
+ ipmi_port (ipmi_port) ver 1.4
+
+03/28/2013 ARCress ipmiutil-2.9.3 changes
+ doc/ipmiutil.spec - add 'BuildRequires: systemd' if Fedora >= 15
+ scripts/install.cmd - split mkdir into two steps
+ scripts/ipmi_info - return 0 even if sysinfo is not supported
+ scripts/ipmi_port.sh - redirect threshold.sh output to thresh_out.txt
+ util/ifru.c - [thibaulf88] Add another valid type (0x0) in ValidTL,
+ Add end-of-string char in binary case of decode_string function.
+ removed #ifdef OLD nSec case
+ util/ievents.c - parse SMI as if BMC when getting sensor description
+ util/isel.c - fix optarg for -l
+ util/i*.c - handle SUPEMICRO and SUPERMICROX the same
+ util/iconfig.c - use ipmi_reserved_user() to skip user1 sometimes
+ util/ilan.c - set default SOL_AUTH to operator if SUPERMICRO
+ util/ihealth.c - call get_device_guid if system guid error
+ util/subs.c - added get_device_guid routine
+ util/ipmi_sample.c - use get_BiosVersion also
+ util/isensor.c - add PS Fan Fail case, move SDR typedefs to isensor.h,
+ fix for -j jumpstart premature end.
+ util/isensor.h - move SDR typedefs to isensor.h
+ util/oem_fujitsu.c - return error if no OEM sensor status string
+ util/Makefile.am - build iseltime by default, build libipmiutil.so,
+ configure.ac - include -fPIC in OS_CFLAGS, exclude .so if Mac/Solaris,
+ added -Wunused-result -Wgnu-designator to cfwarn
+ INSTALL - update Windows build instructions
+ doc/UserGuide - update Windows build instructions, added API section 9
+ doc/ipmiutil.spec - include libipmiutil.so
+ debian/* - changes from review by JuhaniN
+ lib/lanplus/lanplus.c - clean up compile warnings (OliverS)
+ util/idcmi.c util/iekanalyzer.c - clean up compile warnings (OliverS)
+ util/ipmiutil2.mak util/ipmiutil2-64.mak - makefile cleanup (OliverS)
+ cleanwin.cmd util/ipmiutil.mak util/ipmiutil64.mak - ditto
+ ipmiutil-2.9.3 contains:
+ ipmiutil (ipmiutil) ver 2.93
+ ...(various subcommands) ver 2.93
+ ismcoem (ipmiutil smcoem) ver 2.93
+ iekanalyzer (ipmiutil ekanalyzer) ver 1.00
+ ifwum (ipmiutil fwum) ver 1.3
+ ihpm (ipmiutil hpm) ver 1.09
+ idiscover (ipmiutil discover) ver 1.9
+ ipmi_port (ipmi_port) ver 1.4
diff --git a/INSTALL b/INSTALL
new file mode 100755
index 0000000..cf523ba
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,224 @@
+-------------------------------------
+ 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
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..0c3af55
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,60 @@
+
+SUBDIRS = @SUBDIR_S@
+PKGDIR = @PKG_DIR@
+SOURCEDIR = $(PKGDIR)/SOURCES
+BUILDDIR = $(PKGDIR)/BUILD
+RSPEC = doc/$(PACKAGE).spec
+PNAME = $(PACKAGE)-$(VERSION)
+TMPDIR = /var/tmp/$(PNAME)
+BDIR = $(TMPDIR)-1-root
+RPMB = rpmbuild
+# $(RPMB) -bb --buildroot $(BDIR) $(RSPEC)
+
+rpm: $(RSPEC)
+ make tarball
+ $(RPMB) -bb $(RSPEC)
+ $(RPMB) -bs $(RSPEC)
+
+tarball:
+ rm -f $(SOURCEDIR)/$(PNAME).tar.gz
+ rm -rf $(TMPDIR)
+ mkdir -p $(TMPDIR)
+ mkdir -p $(SOURCEDIR)
+ find . -print | cpio -pdumv $(TMPDIR)
+ chown -R root $(TMPDIR)
+ chgrp -R root $(TMPDIR)
+ rm -f $(TMPDIR)/lib/libipmiapi*.a*
+ cd $(TMPDIR)/test; make clean; cd ..
+ cd $(TMPDIR)/hpiutil; make clean; cd ..
+ cd $(TMPDIR); make distclean
+ cd $(TMPDIR); rm -rf autom4te.cache
+ cd $(TMPDIR); rm -f util/events
+ cd $(TMPDIR); sed -i 's/\r//' ChangeLog AUTHORS COPYING NEWS README TODO doc/UserGuide
+ cd $(TMPDIR); chmod 644 doc/UserGuide
+ cd $(TMPDIR); cd ..; tar -czvf $(SOURCEDIR)/$(PNAME).tar.gz $(PNAME)
+ rm -rf $(TMPDIR)
+
+tarsol: util/ipmiutil
+ rm -f /tmp/$(PNAME)-solaris.tar
+ rm -rf $(TMPDIR)
+ mkdir -p $(TMPDIR)
+ cd util; cp ipmiutil idiscover ievents ipmi_port $(TMPDIR)
+ cd doc; cp UserGuide *.8 *.mib $(TMPDIR)
+ cd scripts; cp checksel ipmiutil_??? *.sh $(TMPDIR)
+ cd $(TMPDIR); mv install-solaris.sh install.sh
+ cd $(TMPDIR); tar cvf /tmp/$(PNAME)-solaris.tar .
+ rm -rf $(TMPDIR)
+
+tarbsd: util/ipmiutil
+ rm -f /tmp/$(PNAME)-bsd.tar
+ rm -rf $(TMPDIR)
+ mkdir -p $(TMPDIR)
+ cd util; cp ipmiutil idiscover ievents ipmi_port $(TMPDIR)
+ cd doc; cp UserGuide *.8 *.mib $(TMPDIR)
+ cd scripts; cp checksel ipmiutil_??? *.sh $(TMPDIR)
+ cd $(TMPDIR); mv install-solaris.sh install.sh
+ cd $(TMPDIR); tar -cvf /tmp/$(PNAME)-bsd.tar .
+ rm -rf $(TMPDIR)
+
+clean-generic:
+ rm -f *.log *.tmp debug*.list
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..6398861
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,687 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 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@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = .
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+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@
+DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/config.h.in \
+ $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
+ TODO config.guess config.sub depcomp install-sh ltconfig \
+ ltmain.sh missing mkinstalldirs
+subdir = .
+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)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno configure.status.lineno
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-exec-recursive install-info-recursive \
+ install-recursive installcheck-recursive installdirs-recursive \
+ pdf-recursive ps-recursive uninstall-info-recursive \
+ uninstall-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d $(distdir) \
+ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+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@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GPL_CFLAGS = @GPL_CFLAGS@
+IA64_CFLAGS = @IA64_CFLAGS@
+INIT_DIR = @INIT_DIR@
+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@
+LDFLAGS = @LDFLAGS@
+LD_SAMX = @LD_SAMX@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_DIR = @LIB_DIR@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+OS_CFLAGS = @OS_CFLAGS@
+OS_DRIVERS = @OS_DRIVERS@
+OS_LFLAGS = @OS_LFLAGS@
+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@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHR_LINK = @SHR_LINK@
+STRIP = @STRIP@
+SUBDIR_S = @SUBDIR_S@
+SYSTEMD_DIR = @SYSTEMD_DIR@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+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@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+SUBDIRS = @SUBDIR_S@
+PKGDIR = @PKG_DIR@
+SOURCEDIR = $(PKGDIR)/SOURCES
+BUILDDIR = $(PKGDIR)/BUILD
+RSPEC = doc/$(PACKAGE).spec
+PNAME = $(PACKAGE)-$(VERSION)
+TMPDIR = /var/tmp/$(PNAME)
+BDIR = $(TMPDIR)-1-root
+RPMB = rpmbuild
+all: config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
+ cd $(srcdir) && $(AUTOMAKE) --foreign \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+config.h: stamp-h1
+ @if test ! -f $@; then \
+ rm -f stamp-h1; \
+ $(MAKE) stamp-h1; \
+ else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+ @rm -f stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: $(am__configure_deps)
+ cd $(top_srcdir) && $(AUTOHEADER)
+ rm -f stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f config.h stamp-h1
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+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; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(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; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(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; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ mkdir $(distdir)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(mkdir_p) "$(distdir)/$$subdir" \
+ || exit 1; \
+ distdir=`$(am__cd) $(distdir) && pwd`; \
+ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+ (cd $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$top_distdir" \
+ distdir="$$distdir/$$subdir" \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+ -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r $(distdir)
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && cd $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}'
+distuninstallcheck:
+ @cd $(distuninstallcheck_dir) \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile config.h
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+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)
+
+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-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr \
+ distclean-libtool distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \
+ check-am clean clean-generic clean-libtool clean-recursive \
+ ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \
+ dist-shar dist-tarZ dist-zip distcheck distclean \
+ distclean-generic distclean-hdr distclean-libtool \
+ distclean-recursive distclean-tags distcleancheck distdir \
+ distuninstallcheck dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-exec \
+ install-exec-am install-info install-info-am install-man \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ maintainer-clean-recursive mostlyclean mostlyclean-generic \
+ mostlyclean-libtool mostlyclean-recursive pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am uninstall-info-am
+
+# $(RPMB) -bb --buildroot $(BDIR) $(RSPEC)
+
+rpm: $(RSPEC)
+ make tarball
+ $(RPMB) -bb $(RSPEC)
+ $(RPMB) -bs $(RSPEC)
+
+tarball:
+ rm -f $(SOURCEDIR)/$(PNAME).tar.gz
+ rm -rf $(TMPDIR)
+ mkdir -p $(TMPDIR)
+ mkdir -p $(SOURCEDIR)
+ find . -print | cpio -pdumv $(TMPDIR)
+ chown -R root $(TMPDIR)
+ chgrp -R root $(TMPDIR)
+ rm -f $(TMPDIR)/lib/libipmiapi*.a*
+ cd $(TMPDIR)/test; make clean; cd ..
+ cd $(TMPDIR)/hpiutil; make clean; cd ..
+ cd $(TMPDIR); make distclean
+ cd $(TMPDIR); rm -rf autom4te.cache
+ cd $(TMPDIR); rm -f util/events
+ cd $(TMPDIR); sed -i 's/\r//' ChangeLog AUTHORS COPYING NEWS README TODO doc/UserGuide
+ cd $(TMPDIR); chmod 644 doc/UserGuide
+ cd $(TMPDIR); cd ..; tar -czvf $(SOURCEDIR)/$(PNAME).tar.gz $(PNAME)
+ rm -rf $(TMPDIR)
+
+tarsol: util/ipmiutil
+ rm -f /tmp/$(PNAME)-solaris.tar
+ rm -rf $(TMPDIR)
+ mkdir -p $(TMPDIR)
+ cd util; cp ipmiutil idiscover ievents ipmi_port $(TMPDIR)
+ cd doc; cp UserGuide *.8 *.mib $(TMPDIR)
+ cd scripts; cp checksel ipmiutil_??? *.sh $(TMPDIR)
+ cd $(TMPDIR); mv install-solaris.sh install.sh
+ cd $(TMPDIR); tar cvf /tmp/$(PNAME)-solaris.tar .
+ rm -rf $(TMPDIR)
+
+tarbsd: util/ipmiutil
+ rm -f /tmp/$(PNAME)-bsd.tar
+ rm -rf $(TMPDIR)
+ mkdir -p $(TMPDIR)
+ cd util; cp ipmiutil idiscover ievents ipmi_port $(TMPDIR)
+ cd doc; cp UserGuide *.8 *.mib $(TMPDIR)
+ cd scripts; cp checksel ipmiutil_??? *.sh $(TMPDIR)
+ cd $(TMPDIR); mv install-solaris.sh install.sh
+ cd $(TMPDIR); tar -cvf /tmp/$(PNAME)-bsd.tar .
+ rm -rf $(TMPDIR)
+
+clean-generic:
+ rm -f *.log *.tmp debug*.list
+# 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:
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..59f7987
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,74 @@
+IPMIUTIL NEWS
+
+This project started in October 2001 as part of the Carrier Grade Linux effort.
+It was then known as 'panicsel' ("http://panicsel.sf.net") and included a kernel patch to write a Linux panic event to the IPMI firmware log, as well as utilities.
+
+This code was first included in MontaVista CGE Linux 2.1 in July 2002.
+The panicsel functionality was included in OSDL CGL 1.0 and 2.0 requirements.
+The kernel panic functionality was included in the OpenIPMI driver for 2.6 Linux kernels, and in the Intel IMB Linux driver v28 and greater.
+
+A Linux rpm and a Windows setup package for ipmiutil is included on
+the platform CD with Intel carrier-grade servers.
+
+The ipmiutil (or panicsel) rpm is known to be included in the following
+Linux distributions:
+MontaVista CGE 2.1, 3.0, 3.1, 4.0, SuSE SLES9, SLES10, RedFlag 5.0
+
+See http://ipmiutil.sourceforge.net for binaries, documentation, etc.
+
+In Oct 2001 (0.8.1), started panicsel.
+In Dec 2001 (1.0.0), released with Intel Telecom Linux Technology project
+In July 2002 (1.2.1), released with MontaVista CGE 2.1
+In Jan 2004 (1.4.1), compile flags for Windows 2000 & 2003 support were added.
+In August 2004 (1.4.8), the project was moved from panicsel.sf.net to
+ ipmiutil.sf.net. The new name more clearly reflects the purpose of the
+ project in its current state.
+In November 2004 (1.5.0), support for IPMI LAN was added using FreeIPMI.
+ The FreeIPMI library includes KCS and IPMI LAN protocols.
+In May 2006 (1.7.0), built-in IPMI LAN support was added.
+In August 2006 (1.7.5), driverless direct I/O support was added, to no longer
+ depend upon libfreeipmi.so, since ipmilan.c and ipmidir.c replace that
+ functionality, so the utilities are now more portable.
+In Jan 2007 (1.8.0), two major new features were added:
+ 1) The 'ipmiutil' meta-command, which may be more user-friendly for some
+ users, and maintains the existing syntax for each sub-command.
+ 2) Support for IPMI LAN 2.0 RMCP+ in both Linux and Windows. Support for
+ IPMI LAN 1.5 or 2.0 is detected by default, or can be explicitly
+ specified/forced with the -Flan2 option.
+In Feb 2007 (1.9.2), Linux Serial-Over-Lan console feature was added.
+In Oct 2007 (2.0.0), Windows SOL console and remote soft-shutdown features
+ were added.
+In Mar 2008 (ipmiutil-2.1.0), the Windows SOL client application was completed.
+In Aug 2008 (ipmiutil-2.2.0), a new function was added to save/restore the BMC
+ configuration parameters for lan, serial, user, channel, pef, and sol.
+ The command is "ipmiutil config" for this.
+In Sep 2008 (2.2.1), support for the Microsoft IPMI driver was added.
+In Nov 2008 (2.3.0), support for the Sun Solaris bmc driver was added.
+In Mar 2009 (2.3.5), support for the FreeBSD OS was added.
+In Oct 2009 (2.5.0), added several new features:
+ Full ANSI VT100 emulation for Windows SOL console
+ Two-character escape sequence (~.) for SOL console, adding send-Break.
+ Added canonical output option -c for fru,config,sensor,health,lan
+ Added ipmiutil getevt -r to run specified script when an event occurs
+In Feb 2010 (2.6.0), new subcommand naming scheme:
+ Renamed subcommands to match the meta-command name plus the prefix 'i'.
+ For instance, 'showsel' is now 'isel' and 'pefconfig' is now 'ilan'.
+ This may affect some scripts that use the old subcommand shortcuts.
+ Also included some spec file cleanup/standardization.
+ Support added for some CG2100 firmware differences.
+In Apr 2010 (2.6.2) ifruset was added to set all FRU Product Area fields
+In Jun 2010 (2.6.5) added picmg and firewall functionality
+In Aug 2010 (2.6.8) Fedora 14 version of ipmiutil submitted
+In Sep 2010 (2.6.9) added fwum/hpm functionality, and OEM Fujitsu sensor/sel
+In Sep 2010 (2.7.0) added sunoen, ekanalyzer, fru_picmg, oem_kontron
+In Sep 2010 (2.7.1) added ppc64, mips64, sparc arch support
+In Nov 2010 (2.7.2) added Debian package support
+In Nov 2010 Fedora 14 released with ipmiutil-2.6.8
+In Dec 2010 (2.7.3) added SuperMicro OEM functions
+In Mar 2011 OpenSuSE 11.4 released with ipmituil-2.7.2
+In May 2011 (2.7.6) added VLAN support and WIN64 fixes
+In Sep 2011 (2.7.8) added Dell OEM functions, PICMG 2.3, IPv6, systemd, tsol
+In Oct 2011 (2.7.9) support Wind River and ARM cross-compile, Intel S2600
+In Dec 2011 (2.8.0) added DCMI 1.1 commands, devel pkg, MSI package
+In Feb 2012 (2.8.1) added Quanta S99Q functions, Dell fixes, Intel ME fixes
+
diff --git a/README b/README
new file mode 100644
index 0000000..1d58b89
--- /dev/null
+++ b/README
@@ -0,0 +1,156 @@
+
+ ------------------------------
+ ipmiutil README
+ IPMI Management Utilities
+ ------------------------------
+
+The ipmiutil IPMI utilities below allow the user to access the firmware
+System Event Log and configure the Platform Event Filter table for the new
+'OS Critical Stop' records, as well as other common IPMI system management
+functions.
+
+ipmiutil - a meta-command to invoke all of the below as sub-commands
+ievents - a standalone utility to interpret IPMI and PET event data
+isel - show/set the firmware System Event Log records
+isensor - show Sensor Data Records, sensor readings, and thresholds
+ireset - cause the BMC to hard reset or power down the system
+ilan - show and configure the BMC LAN port and Platform Event Filter
+ table to allow BMC LAN alerts from firmware events and
+ OS Critical Stop messages,
+iserial - show and configure the BMC Serial port for various modes,
+ such as Terminal Mode.
+ifru - show the FRU chassis, board, and product inventory data,
+ and optionally write a FRU asset tag.
+ialarms - show and set front panel alarms (LEDs and relays)
+iwdt - show and set watchdog timer parameters
+igetevent - receive any IPMI events and display them
+ihealth - check and report the basic health of the IPMI BMC
+iconfig - list/save/restore the BMC configuration parameters
+icmd - send specific IPMI commands to the BMC,
+ mainly for testing and debug purposes.
+idiscover - discover the available IPMI LAN nodes on a subnet
+isol - start/stop an IPMI Serial-Over-LAN Console session
+ipicmg - show/set the IPMI PICMG parameters
+ifirewall - show/set the IPMI firmware firewall configuration
+iekanalyzer - run FRU-EKeying analyzer on FRU files
+ifwum - OEM firmware update manager extensions
+ihpm - HPM firmware update manager extensions
+isunoem - Sun OEM functions
+idelloem - Dell OEM functions
+itsol - Tyan SOL console start/stop session
+idcmi - get/set DCMI parameters, if supporting the DCMI spec
+
+Other supporting files:
+checksel = cron script using ipmiutil sel to check the SEL, write new
+ events to the OS system log, and clear the SEL if nearly full.
+ipmi_port = daemon to bind the RMCP port and sleep to prevent
+ Linux portmap from stealing the RMCP port
+ipmi_port.sh = init script to reserve the RMCP port from portmap,
+ this also restores saved sensor thresholds, if any.
+ipmiutil_wdt = init script to restart watchdog timer every 60 sec via cron
+ipmiutil_asy = init script runs 'ipmiutil getevt -a' for remote shutdown
+ipmiutil_evt = init script runs 'ipmiutil getevt -s' for monitoring events
+evt.sh = sample script which can be invoked by ipmiutil_evt
+ipmi_if.sh = script using dmidecode to determine the IPMI Interface Type
+bmclanpet.mib = SNMP MIB for BMC LAN Platform Event Traps
+test/* = scripts and utilities used in testing ipmiutil/panicsel
+kern/* = kernel patches for panic handling
+
+--------------------
+ Dependencies:
+--------------------
+The IPMI Management Utilities currently work with platforms that
+support the IPMI 1.5 or 2.0 specification. IPMI servers can be managed
+locally, or remotely via IPMI LAN, even when the OS or main CPU is not
+functional.
+
+The IPMI 1.5 spec, Table 36-3 defines the sensor types for SEL records,
+as used by showsel.
+The IPMI 1.5 spec, Table 15-2 defines the Platform Event Filter table
+entries, as used by pefconfig.
+The IPMI 1.5 spec, Table 19-4 defines the LAN Configuration Parameters,
+as used by pefconfig.
+
+The ipmiutil utilities will use an IPMI Driver, either the Intel IPMI package
+(ipmidrvr, /dev/imb), MontaVista OpenIPMI (/dev/ipmi0), the valinux IPMI
+Driver (/dev/ipmikcs), or the LANDesk ldipmi daemon. The ipmiutil utilities
+can also use direct user-space I/Os in Linux or FreeBSD if no IPMI driver
+is detected.
+
+If ipmiutil is compiled with LANPLUS enabled, then it does depend upon
+libcrypto.so, which is provided by the openssl package.
+
+------------------------
+ Build Instructions
+------------------------
+
+See notes in the INSTALL file from the ipmiutil*.tar.gz archive.
+
+------------------------
+ IPMI Configuration
+------------------------
+See http://ipmiutil.sourceforge.net/docs/UserGuide
+
+Note that ipmiutil can autodetect the IPMI interface using SMBIOS/dmi
+and use driverless KCS or SSIF if no IPMI driver is loaded.
+
+Various vendor IPMI firmware versions should support all of the
+mandatory IPMI functions, but there are variations in which of
+the optional IPMI functions that are supported.
+
+The 'ipmiutil lan' utility can be used to easily set up a working
+configuration of BMC LAN, SOL, and PEF Alerting while Linux is running,
+instead of a series of 40-50 commands with ipmitool, or a proprietary
+vendor tool, which may even require booting to DOS.
+
+The bmc_panic patch has been obsoleted by the CONFIG_IPMI_PANIC option
+in the OpenIPMI driver, which is included in kernel.org.
+The bmc_panic functionality is also included in the Intel imb IPMI driver
+build 28 and greater.
+To apply the bmc_panic patch (in kern/) to a different version of kernel source:
+ kver=2.4.18
+ cd /usr/src/linux-${kver}
+ cat bmcpanic-${kver}.patch | patch -p1
+ make menuconfig (make sure CONFIG_BMCPANIC=y)
+ make oldconfig
+ make dep
+ make bzImage
+ make modules
+ make modules_install
+ mkinitrd -f /boot/initrd-${kver}.img ${kver}
+ make install
+ reboot
+
+The ipmiutil package does not set the Linux kernel panic timeout.
+If a specific panic timeout is desired, do
+"echo 10 >/proc/sys/kernel/panic" to set it to 10 seconds, for instance.
+or add panic=10 to the kernel line in grub.conf.
+
+------------------------------
+ KNOWN PROBLEMS
+------------------------------
+
+See http://sourceforge.net/tracker/?group_id=116222&func=browse for
+a list of bugs.
+
+Contact for best-effort support: arcress at users.sourceforge.net or
+ipmiutil-developers at lists.sourceforge.net or http://ipmiutil.sf.net
+
+--------------------
+ LICENSING:
+--------------------
+The BSD License in the COPYING file applies to all source files
+herein, except for
+ * util/md5.c (Aladdin unrestricted license, compatible with BSD)
+ * util/md2.h (GPL)
+ * util/ipmi_ioctls.h (GPL, now defunct and removed)
+While the BSD License allows code reuse in both open and non-open
+applications, the md2.h and ipmi_ioctls.h files would have to be removed
+if used in a non-open application. There is a ALLOW_GPL compile flag
+for this that is disabled by default, but can be enabled for GPL
+open-source by running "./configure --enable-gpl".
+
+--------------------
+ CHANGE HISTORY:
+--------------------
+See http://ipmiutil.sourceforge.net/docs/ChangeLog
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..cec1931
--- /dev/null
+++ b/TODO
@@ -0,0 +1,293 @@
+
+IPMIUTIL PROJECT TODO LIST:
+
+IPV6:
+ . implement IPV6 for Windows
+
+SuperMicro Users:
+ . implement OEM cmd to set user privilege level
+
+SPD decoding:
+ . expose SPD decoding from file/buffer, not just FRU
+ c handle DDR3 SPD 1.0 format
+ PARTIAL in ipmiutil-2.9.1
+
+Add additional IPMI 2.0 commands from addendum:
+ c Get/Set System Info
+ . Get/Set SEL UTC Offset (requested 4/22/13)
+ . Forwarded Command
+ PARTIAL in ipmiutil-2.8.1, adding Get/Set System Info functions
+
+Add DCMI 1.5 commands for NetFn 0x2C to ipmiutil
+ . Get/Set DCMI Configuration Parameters (DCMI 1.5)
+ . Get/Set Thermal Limit (DCMI 1.5)
+
+Add an option/variant of canonical output for CSV (delimiter = ',')
+
+Change ipmicmd.c to be thread-safe if accessing multiple nodes.
+ Currently is only conditionally safe, if threads access the same node.
+ Will require adding a context struct param to the ipmi_cmd*() funcs.
+ Probably need to add new thread-safe functions to retain back-compatibility.
+ PARTIAL in ipmiutil-2.9.0, multiple nodes in sequence is fixed
+
+Add support for MAC OSX AppleBMC.kext driver
+ not yet implemented, pending some documentation.
+
+More automated testing
+ Started this in ipmiutil-2.6.6 with testipmi.sh, but it could be
+ more extensive and be tested on more types of IPMI firmware.
+ PARTIAL in ipmiutil-2.6.6 with testipmi.sh
+
+Remove assert() calls from lanplus code
+ Need to improve error handling and remove all assert() calls from
+ the lib/lanplus/ code: lanplus.c lanplus_crypt.c lanplus_crypt_impl.c
+ This requires test cases for the assert instances.
+ PARTIAL in ipmiutil-2.4.0, removed 2 asserts from lanplus.c
+ PARTIAL in ipmiutil-2.7.0, removed 1 more assert from lanplus.c
+ PARTIAL in ipmiutil-2.8.8, more from lanplus_crypt.c/lanplus_crypt_impl.c
+
+Add a function to send ctl-alt-del through SOL console
+ Although this is seldom used in a serial console environment, it
+ could be useful. To do this, the one-character escape sequence
+ would need to be changed to a 2 character escape sequence.
+ Also need a method to insert the key sequence in the console.
+ PARTIAL in ipmiutil-2.5.0 includes the 2-character escape sequence
+ and a send_break function.
+
+------------------------------------------------------------------------------
+IPMIUTIL COMPLETED TODO TASKS:
+
+Add support for a MAC OSX client
+ It should work with minor compile-time adjustments.
+ We need a system running OSX on which to build and test this.
+ Changes to compile on MACOS submitted to SVN on 04/12/2013
+ Support for AppleBMC.kext not yet implemented, pending documentation.
+ COMPLETED in ipmiutil-2.9.1
+
+Add snmptrap functionality to getevent -r example script
+ COMPLETE in ipmiutil-2.9.1
+
+Add DCMI 1.1 commands for NetFn 0x2C to ipmiutil
+ (0xDC defines the body code)
+ The command codes under this NetFn are:
+ c Get DCMI Capabilities Info
+ c Get/Set Management Controller Identifier String
+ c Get/Set Asset Tag
+ c Get DCMI Sensor Info
+ c Get Temperature Readings
+ c Get Power Reading
+ c Get/Set Power Limit
+ The remainder DCMI specified commands are from the IPMI specification
+ IMPLEMENTED in ipmiutil-2.8.1
+ COMPLETE (power options tested) in ipmiutil-2.8.4
+
+Perform retries on retries for some get/set lan parameters
+ COMPLETE in ipmiutil-2.8.1 by using set_max_kcs_loops()
+
+Add an oem_hp.c module with decode_sensor_hp() to
+ interpret HP discrete sensors with analog readings
+ COMPLETE in ipmiutil-2.8.2
+
+Add systemd scripts for ipmi_port, ipmiutil_evt, etc.
+ COMPLETE in ipmiutil-2.7.8, not default but installed in /usr/share/ipmiutil
+ ipmi_port.service, ipmiutil_evt.service,
+ ipmiutil_asy.service, ipmiutil_wdt.service
+
+Add IPv6 support
+ There is at least one IPMI BMC that has added IPv6 support, so
+ it would be nice to include support for it in ipmiutil.
+ Need access to a BMC that supports IPv6 for testing, or
+ someone to help test it whose BMC supports IPv6.
+ COMPLETE in ipmiutil-2.7.8, with contribution from Rajaganesh87
+
+Add an option to 'ipmiutil fru' that discovers every child MC FRU also,
+like the isensor.c code does for fchild.
+ COMPLETE in ipmiutil-2.7.5 (ifru -e)
+
+Pass event severities to syslog, instead of just writing them as 'info'.
+ COMPLETE in ipmiutil-2.7.5
+
+Add OEM code for ekanalyzer
+ COMPLETE in ipmiutil-2.7.0
+
+Add code for FRU multi-record area decoding and FRU PICMG records
+ COMPLETE in ipmiutil-2.7.0
+
+Add OEM code for Sun
+ COMPLETE in ipmiutil-2.7.0
+
+Add OEM code for Fujitsu
+ PARTIAL in ipmiutil-2.6.9 with iRMC S2 SEL decoding
+ COMPLETE in ipmiutil-2.7.0 with iRMC S2 LED routines
+
+Add SHA256 and Cipher Suite 17 support
+ Current max Cipher Suite ID is 14, but IPMI 2.0 Errata 4 and DCMI 1.1
+ add these.
+ COMPLETE in ipmiutil-2.6.9
+
+Add OEM code for fwum, hpm, and oem_kontron features.
+ COMPLETE in ipmiutil-2.6.9
+
+Add more ATCA/picmg functionality.
+ Currently have std IPMI functions, plus fru and sensor and blue LED
+ capability for ATCA/picmg bladed systems.
+ Need to add some additional picmg-specific functionality, like:
+ properties - get PICMG properties
+ addrinfo - get address information
+ activate - activate a FRU
+ deactivate - deactivate a FRU
+ policy get - get the FRU activation policy
+ policy set - set the FRU activation policy
+ portstate get - get port state
+ portstate set - set port state
+ led prop - get led properties
+ led cap - get led color capabilities
+ led state get - get led state
+ led state set - set led state
+ power get - get power level info
+ power set - set power level
+ and firmware firewall functions
+ COMPLETE: added ipicmg.c and ifirewall.c in ipmiutil-2.6.5
+
+Add older 1.5 SOL protocol capability
+ For ipmiutil sol with IPMI 1.5, the older (Intel-only) 1.5 SOL protocol
+ is implemented and will connect, but the 1.5 SOL data packets are not
+ right yet. This is in progress. Note that the standard IPMI 2.0 SOL
+ protocol is entirely separate and still works fine.
+ Lower priority right now. If you want to use this feature, email
+ ipmiutil-developers(at)lists.sourceforge.net
+ CANCELLED - Intel 1.5 SOL is too old to matter any more. It was
+ only supported on SE7501WV2 motherboards from <=2003.
+
+Fix the API interface to /dev/ipmi0 on FreeBSD
+ This FreeBSD ipmi driver is different than Linux.
+ We have support for ipmiutil driverless mode on FreeBSD.
+ COMPLETE in ipmiutil-2.5.2, support ipmi driver and driverless w FreeBSD 7.x
+
+Add a delimeted-output option for all utilities
+ Would make parsing the output in scripts easier.
+ 08/25/08 added ':' delimiters to lan/serial config output in 2.2.0
+ PARTIAL in ipmiutil-2.2.0 - added 'ipmiutil config'
+ DONE in ipmiutil-2.4.1 for sensor and lan canonical output with -c
+ COMPLETE in ipmiutil-2.5.0 added -c to bmchealth, fruconfig
+
+Add support for a DOS build
+ CANCELLED - use Linux boot media instead, DOS is not as good.
+
+Add detection for Windows SOL when Command Prompt window is >25 rows.
+ DONE with AnsiTerm.cpp in ipmiutil-2.5.0
+
+Build a bootable Linux CD with ipmiutil for use with other random OSs.
+ Note that with ipmiutil-1.7.5, any bootable Linux CD will do, since
+ the direct I/Os no longer require an IPMI driver.
+ We may still want to build and supply an example (like TRB or SLAX).
+ 2/06/07 Built an initial SLAX CD as http://ipmiutil.sf.net/ipmiutil.iso.
+ This ISO is too big to remain posted on sourceforge.net, however.
+ Need documentation on how to build an ISO to finish this.
+ 11/21/08 posted SLAX ISO as http://ipmiutil.sf.net/FILES/newgrab.iso
+ COMPLETE
+
+Add Solaris support
+ Needed because configuring IPMI LAN and PEF with ipmitool is too
+ complicated.
+ COMPLETE in ipmiutil-2.3.0 for Solaris 10 bmc driver
+
+Add output logging to ipmiutil sol
+ This is easy with stdio in Linux, but not possible in Windows without
+ adding a logging option in the code, since Windows uses the video
+ console buffer instead of stdio.
+ COMPLETE in ipmiutil-2.2.2
+
+Add support for Microsoft Windows IPMI driver
+ Currently only support Intel Windows imbdrv.sys driver.
+ Requires adding WMI infrastructure.
+ COMPLETED 09/12/08 in ipmiutil-2.2.1 for 32-bit Win2003R2
+
+Add support for remote soft reset via OpenIPMI driver
+ Currently 'ipmiutil reset -o -N' requires 'getevent -a' and the imb driver.
+ Requires adding async callback for OpenIPMI driver to getevent.c
+ COMPLETED 09/12/08 in ipmiutil-2.2.1
+
+Add a function to save/restore BMC IPMI settings
+ This would combine lan, serial, and fru parameters in a key-value-pair
+ file that could be restored automatically.
+ COMPLETED 08/25/08 in ipmiutil-2.2.0
+
+Eliminate duplication in binaries
+ Build only one Meta-command for ipmiutil, with static libs if possible.
+ Existing other commands would be sym-links or shortcuts, e.g.
+ showsel [args] => ipmiutil sel [args]
+ COMPLETED 03/31/08 in ipmiutil-2.1.0 for Linux
+
+Handle Windows command prompt terminal emulation for SOL
+ The Windows isolconsole.exe works, but the terminal emulation logic is
+ not finished. It works ok to Linux command-line and vi, but looks
+ bad for BIOS/POST. This is in progress. There are other (non-open)
+ tools available for Windows (e.g. Intel dpccli) in the interim.
+ The Linux isolconsole works fine, since the terminal emulation is
+ handled by the Linux termio.
+ COMPLETE in ipmiutil-2.0.0, no known issues
+
+Do an OS Agent for hwreset to do BMC LAN remote soft-shutdown.
+ Perhaps using an xinetd socket to not have a service always resident,
+ or sending a kill signal to init from the driver level would work.
+ i.e. kill(1,SIGINT); /*SIGINT==2*/
+ COMPLETE in ipmiutil-2.0.0 with hwreset & "getevent -a" for IMB driver.
+
+Do a configure option with/without lanplus support, since this adds so
+much size to the binary object code.
+ COMPLETE in ipmiutil-1.8.2
+
+Include IPMI v2.0 RMCP+ LAN protocol also.
+ (IPMI 2.0 commands were previously supported, however.)
+ COMPLETE in ipmiutil-1.8.0
+
+Add more boot parameters to hwreset, for things like:
+ . hwreset: Set which device to boot from (CD, Disk, LAN/PXE, etc.)
+ COMPLETE in ipmiutil-1.7.0
+ . Forcing the boot to continue (i.e. no POST pause) - BIOS setting
+ REJECTED - too platform specific for this project, see platform vendor
+ . Set which OS/Software version/target to be downloaded for PXE (?)
+ REJECTED - too platform specific for this project, see platform vendor
+
+Make a real-time sensor monitoring tool to monitor a specified SDR for
+sensor readings every second.
+ . partially complete with sensor -i option
+ . sensor 1.39 has -L option for looping
+ COMPLETE in ipmiutil-1.7.3 (sensor 1.39)
+
+Add encrypt/decrypt options to pefconfig & tmconfig, using RSA or DSA public
+keys, perhaps with the gnupg.org library.
+ There is some concern about increasing the size of the utilities for
+ encryption, when this functionality can be scripted instead.
+ POSTPONED - perhaps someone else would like to help?
+ COMPLETE - using -E to get password from IPMI_PASSWORD environment
+ variable works, and does not put the password in the
+ command line or script.
+ ADDED -Y option to allow user to enter password at prompt w ipmiutil-1.9.0
+
+Improve BMC LAN functionality and diagnosis with some custom IPMI LAN logic.
+ The built-in IPMI LAN also makes the Windows version able to use it.
+ COMPLETE in ipmiutil-1.7.0 with ipmilan.c
+
+pefconfig: Fix fSOL20 logic to work on supported platforms, currently
+ returns completion code 0x80.
+ COMPLETE in ipmiutil-1.6.5
+
+Update hpiutil source for 1.1.9 changes
+ COMPLETE in ipmiutil-1.6.3
+
+Add pre-built Windows *.exe files to the ipmiutil.sf.net home page.
+ COMPLETE in ipmiutil-1.6.3
+
+sensor: Add an option to display timestamp for this run. Write it on each SDR line if -w is also specified.
+ COMPLETE in ipmiutil-1.5.6
+
+fruconfig: Get FRU data from all FRU devices, not just baseboard.
+ COMPLETE in ipmiutil-1.5.6
+
+Add User settings, like tmconfig has, to pefconfig
+ - added more Get User Access messages to pefconfig v1.30 in ipmiutil 1.4.9
+ - added -u option with ipmiutil 1.5.3
+ COMPLETE
+
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..6b265a6
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,7261 @@
+# generated automatically by aclocal 1.9.6 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005 Free Software Foundation, Inc.
+# This file 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.
+
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+
+# serial 48 AC_PROG_LIBTOOL
+
+
+# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)
+# -----------------------------------------------------------
+# If this macro is not defined by Autoconf, define it here.
+m4_ifdef([AC_PROVIDE_IFELSE],
+ [],
+ [m4_define([AC_PROVIDE_IFELSE],
+ [m4_ifdef([AC_PROVIDE_$1],
+ [$2], [$3])])])
+
+
+# AC_PROG_LIBTOOL
+# ---------------
+AC_DEFUN([AC_PROG_LIBTOOL],
+[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl
+dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX
+dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX.
+ AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [AC_LIBTOOL_CXX],
+ [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX
+ ])])
+dnl And a similar setup for Fortran 77 support
+ AC_PROVIDE_IFELSE([AC_PROG_F77],
+ [AC_LIBTOOL_F77],
+ [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77
+])])
+
+dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly.
+dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run
+dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both.
+ AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+ [AC_LIBTOOL_GCJ],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+ [AC_LIBTOOL_GCJ],
+ [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],
+ [AC_LIBTOOL_GCJ],
+ [ifdef([AC_PROG_GCJ],
+ [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+ ifdef([A][M_PROG_GCJ],
+ [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+ ifdef([LT_AC_PROG_GCJ],
+ [define([LT_AC_PROG_GCJ],
+ defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])])
+])])# AC_PROG_LIBTOOL
+
+
+# _AC_PROG_LIBTOOL
+# ----------------
+AC_DEFUN([_AC_PROG_LIBTOOL],
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Prevent multiple expansion
+define([AC_PROG_LIBTOOL], [])
+])# _AC_PROG_LIBTOOL
+
+
+# AC_LIBTOOL_SETUP
+# ----------------
+AC_DEFUN([AC_LIBTOOL_SETUP],
+[AC_PREREQ(2.50)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+
+AC_REQUIRE([AC_PROG_LN_S])dnl
+AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+AC_REQUIRE([AC_OBJEXT])dnl
+AC_REQUIRE([AC_EXEEXT])dnl
+dnl
+
+AC_LIBTOOL_SYS_MAX_CMD_LEN
+AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+AC_LIBTOOL_OBJDIR
+
+AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+_LT_AC_PROG_ECHO_BACKSLASH
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g']
+
+# Same as above, but do not quote variable references.
+[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g']
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+AC_CHECK_TOOL(AR, ar, false)
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(STRIP, strip, :)
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ AC_PATH_MAGIC
+ fi
+ ;;
+esac
+
+AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+enable_win32_dll=yes, enable_win32_dll=no)
+
+AC_ARG_ENABLE([libtool-lock],
+ [AC_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+AC_ARG_WITH([pic],
+ [AC_HELP_STRING([--with-pic],
+ [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+ [pic_mode="$withval"],
+ [pic_mode=default])
+test -z "$pic_mode" && pic_mode=default
+
+# Use C for the default configuration in the libtool script
+tagname=
+AC_LIBTOOL_LANG_C_CONFIG
+_LT_AC_TAGCONFIG
+])# AC_LIBTOOL_SETUP
+
+
+# _LT_AC_SYS_COMPILER
+# -------------------
+AC_DEFUN([_LT_AC_SYS_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_AC_SYS_COMPILER
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+AC_DEFUN([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+ case $cc_temp in
+ compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+ distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+])
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+AC_DEFUN([_LT_COMPILER_BOILERPLATE],
+[ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+AC_DEFUN([_LT_LINKER_BOILERPLATE],
+[ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+])# _LT_LINKER_BOILERPLATE
+
+
+# _LT_AC_SYS_LIBPATH_AIX
+# ----------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX],
+[AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_AC_SYS_LIBPATH_AIX
+
+
+# _LT_AC_SHELL_INIT(ARG)
+# ----------------------
+AC_DEFUN([_LT_AC_SHELL_INIT],
+[ifdef([AC_DIVERSION_NOTICE],
+ [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+ [AC_DIVERT_PUSH(NOTICE)])
+$1
+AC_DIVERT_POP
+])# _LT_AC_SHELL_INIT
+
+
+# _LT_AC_PROG_ECHO_BACKSLASH
+# --------------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
+[_LT_AC_SHELL_INIT([
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+ ;;
+esac
+
+echo=${ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X[$]1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+[$]*
+EOF
+ exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if (echo_test_string=`eval $cmd`) 2>/dev/null &&
+ echo_test_string=`eval $cmd` &&
+ (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+ then
+ break
+ fi
+ done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ if test "X$echo" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ echo='print -r'
+ elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+ else
+ # Try using printf.
+ echo='printf %s\n'
+ if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ echo="$CONFIG_SHELL [$]0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$CONFIG_SHELL [$]0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+ if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "[$]0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ echo=echo
+ fi
+ fi
+ fi
+ fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+ ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(ECHO)
+])])# _LT_AC_PROG_ECHO_BACKSLASH
+
+
+# _LT_AC_LOCK
+# -----------
+AC_DEFUN([_LT_AC_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+ [AC_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE="32"
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE="64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ ppc*-*linux*|powerpc*-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+ [AC_LANG_PUSH(C)
+ AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+ AC_LANG_POP])
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+sparc*-*solaris*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*) LD="${LD-ld} -m elf64_sparc" ;;
+ *) LD="${LD-ld} -64" ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+ AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+ AC_CHECK_TOOL(AS, as, false)
+ AC_CHECK_TOOL(OBJDUMP, objdump, false)
+ ;;
+ ])
+esac
+
+need_locks="$enable_libtool_lock"
+
+])# _LT_AC_LOCK
+
+
+# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION],
+[AC_REQUIRE([LT_AC_PROG_SED])
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$3"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ fi
+ $rm conftest*
+])
+
+if test x"[$]$2" = xyes; then
+ ifelse([$5], , :, [$5])
+else
+ ifelse([$6], , :, [$6])
+fi
+])# AC_LIBTOOL_COMPILER_OPTION
+
+
+# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [ACTION-SUCCESS], [ACTION-FAILURE])
+# ------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_LINKER_OPTION],
+[AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $3"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&AS_MESSAGE_LOG_FD
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ else
+ $2=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+ ifelse([$4], , :, [$4])
+else
+ ifelse([$5], , :, [$5])
+fi
+])# AC_LIBTOOL_LINKER_OPTION
+
+
+# AC_LIBTOOL_SYS_MAX_CMD_LEN
+# --------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN],
+[# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+ i=0
+ teststring="ABCD"
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \
+ = "XX$teststring") >/dev/null 2>&1 &&
+ new_result=`expr "X$teststring" : ".*" 2>&1` &&
+ lt_cv_sys_max_cmd_len=$new_result &&
+ test $i != 17 # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on massive
+ # amounts of additional arguments before passing them to the linker.
+ # It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ ;;
+ esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+ AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+ AC_MSG_RESULT(none)
+fi
+])# AC_LIBTOOL_SYS_MAX_CMD_LEN
+
+
+# _LT_AC_CHECK_DLFCN
+# ------------------
+AC_DEFUN([_LT_AC_CHECK_DLFCN],
+[AC_CHECK_HEADERS(dlfcn.h)dnl
+])# _LT_AC_CHECK_DLFCN
+
+
+# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ---------------------------------------------------------------------
+AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+ [$4]
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ exit (status);
+}]
+EOF
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) $1 ;;
+ x$lt_dlneed_uscore) $2 ;;
+ x$lt_dlunknown|x*) $3 ;;
+ esac
+ else :
+ # compilation failed
+ $3
+ fi
+fi
+rm -fr conftest*
+])# _LT_AC_TRY_DLOPEN_SELF
+
+
+# AC_LIBTOOL_DLOPEN_SELF
+# ----------------------
+AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ])
+ ;;
+
+ *)
+ AC_CHECK_FUNC([shl_load],
+ [lt_cv_dlopen="shl_load"],
+ [AC_CHECK_LIB([dld], [shl_load],
+ [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
+ [AC_CHECK_FUNC([dlopen],
+ [lt_cv_dlopen="dlopen"],
+ [AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+ [AC_CHECK_LIB([svld], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+ [AC_CHECK_LIB([dld], [dld_link],
+ [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
+ ])
+ ])
+ ])
+ ])
+ ])
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ AC_CACHE_CHECK([whether a program can dlopen itself],
+ lt_cv_dlopen_self, [dnl
+ _LT_AC_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+ lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+ ])
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+ lt_cv_dlopen_self_static, [dnl
+ _LT_AC_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+ lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
+ ])
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+])# AC_LIBTOOL_DLOPEN_SELF
+
+
+# AC_LIBTOOL_PROG_CC_C_O([TAGNAME])
+# ---------------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler
+AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O],
+[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+ [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+ [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+ fi
+ fi
+ chmod u+w . 2>&AS_MESSAGE_LOG_FD
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+])
+])# AC_LIBTOOL_PROG_CC_C_O
+
+
+# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME])
+# -----------------------------------------
+# Check to see if we can do hard links to lock some files if needed
+AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS],
+[AC_REQUIRE([_LT_AC_LOCK])dnl
+
+hard_links="nottested"
+if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ AC_MSG_CHECKING([if we can lock with hard links])
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ AC_MSG_RESULT([$hard_links])
+ if test "$hard_links" = no; then
+ AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS
+
+
+# AC_LIBTOOL_OBJDIR
+# -----------------
+AC_DEFUN([AC_LIBTOOL_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+])# AC_LIBTOOL_OBJDIR
+
+
+# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME])
+# ----------------------------------------------
+# Check hardcoding attributes.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_AC_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \
+ test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \
+ test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+ test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then
+ # Linking always hardcodes the temporary library directory.
+ _LT_AC_TAGVAR(hardcode_action, $1)=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ _LT_AC_TAGVAR(hardcode_action, $1)=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ _LT_AC_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH
+
+
+# AC_LIBTOOL_SYS_LIB_STRIP
+# ------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP],
+[striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+fi
+ ;;
+ *)
+ AC_MSG_RESULT([no])
+ ;;
+ esac
+fi
+])# AC_LIBTOOL_SYS_LIB_STRIP
+
+
+# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER],
+[AC_MSG_CHECKING([dynamic linker characteristics])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[[01]] | aix4.[[01]].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[[45]]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[[123]]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # find out which ABI we are using
+ libsuff=
+ case "$host_cpu" in
+ x86_64*|s390x*|powerpc64*)
+ echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *64-bit*)
+ libsuff=64
+ sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+ esac
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[[89]] | openbsd2.[[89]].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+])# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+
+
+# _LT_AC_TAGCONFIG
+# ----------------
+AC_DEFUN([_LT_AC_TAGCONFIG],
+[AC_ARG_WITH([tags],
+ [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@],
+ [include additional configurations @<:@automatic@:>@])],
+ [tagnames="$withval"])
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+ if test ! -f "${ofile}"; then
+ AC_MSG_WARN([output file `$ofile' does not exist])
+ fi
+
+ if test -z "$LTCC"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+ if test -z "$LTCC"; then
+ AC_MSG_WARN([output file `$ofile' does not look like a libtool script])
+ else
+ AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile'])
+ fi
+ fi
+ if test -z "$LTCFLAGS"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`"
+ fi
+
+ # Extract list of available tagged configurations in $ofile.
+ # Note that this assumes the entire list is on one line.
+ available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for tagname in $tagnames; do
+ IFS="$lt_save_ifs"
+ # Check whether tagname contains only valid characters
+ case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in
+ "") ;;
+ *) AC_MSG_ERROR([invalid tag name: $tagname])
+ ;;
+ esac
+
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+ then
+ AC_MSG_ERROR([tag name \"$tagname\" already exists])
+ fi
+
+ # Update the list of available tags.
+ if test -n "$tagname"; then
+ echo appending configuration tag \"$tagname\" to $ofile
+
+ case $tagname in
+ CXX)
+ if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ AC_LIBTOOL_LANG_CXX_CONFIG
+ else
+ tagname=""
+ fi
+ ;;
+
+ F77)
+ if test -n "$F77" && test "X$F77" != "Xno"; then
+ AC_LIBTOOL_LANG_F77_CONFIG
+ else
+ tagname=""
+ fi
+ ;;
+
+ GCJ)
+ if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+ AC_LIBTOOL_LANG_GCJ_CONFIG
+ else
+ tagname=""
+ fi
+ ;;
+
+ RC)
+ AC_LIBTOOL_LANG_RC_CONFIG
+ ;;
+
+ *)
+ AC_MSG_ERROR([Unsupported tag name: $tagname])
+ ;;
+ esac
+
+ # Append the new tag name to the list of available tags.
+ if test -n "$tagname" ; then
+ available_tags="$available_tags $tagname"
+ fi
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ # Now substitute the updated list of available tags.
+ if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+ mv "${ofile}T" "$ofile"
+ chmod +x "$ofile"
+ else
+ rm -f "${ofile}T"
+ AC_MSG_ERROR([unable to update list of available tagged configurations.])
+ fi
+fi
+])# _LT_AC_TAGCONFIG
+
+
+# AC_LIBTOOL_DLOPEN
+# -----------------
+# enable checks for dlopen support
+AC_DEFUN([AC_LIBTOOL_DLOPEN],
+ [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_DLOPEN
+
+
+# AC_LIBTOOL_WIN32_DLL
+# --------------------
+# declare package support for building win32 DLLs
+AC_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_BEFORE([$0], [AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_WIN32_DLL
+
+
+# AC_ENABLE_SHARED([DEFAULT])
+# ---------------------------
+# implement the --enable-shared flag
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_SHARED],
+[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([shared],
+ [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+ [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_shared=]AC_ENABLE_SHARED_DEFAULT)
+])# AC_ENABLE_SHARED
+
+
+# AC_DISABLE_SHARED
+# -----------------
+# set the default shared flag to --disable-shared
+AC_DEFUN([AC_DISABLE_SHARED],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_SHARED(no)
+])# AC_DISABLE_SHARED
+
+
+# AC_ENABLE_STATIC([DEFAULT])
+# ---------------------------
+# implement the --enable-static flag
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_STATIC],
+[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([static],
+ [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+ [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_static=]AC_ENABLE_STATIC_DEFAULT)
+])# AC_ENABLE_STATIC
+
+
+# AC_DISABLE_STATIC
+# -----------------
+# set the default static flag to --disable-static
+AC_DEFUN([AC_DISABLE_STATIC],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_STATIC(no)
+])# AC_DISABLE_STATIC
+
+
+# AC_ENABLE_FAST_INSTALL([DEFAULT])
+# ---------------------------------
+# implement the --enable-fast-install flag
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_FAST_INSTALL],
+[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([fast-install],
+ [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+ [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT)
+])# AC_ENABLE_FAST_INSTALL
+
+
+# AC_DISABLE_FAST_INSTALL
+# -----------------------
+# set the default to --disable-fast-install
+AC_DEFUN([AC_DISABLE_FAST_INSTALL],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_FAST_INSTALL(no)
+])# AC_DISABLE_FAST_INSTALL
+
+
+# AC_LIBTOOL_PICMODE([MODE])
+# --------------------------
+# implement the --with-pic flag
+# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
+AC_DEFUN([AC_LIBTOOL_PICMODE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+pic_mode=ifelse($#,1,$1,default)
+])# AC_LIBTOOL_PICMODE
+
+
+# AC_PROG_EGREP
+# -------------
+# This is predefined starting with Autoconf 2.54, so this conditional
+# definition can be removed once we require Autoconf 2.54 or later.
+m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP],
+[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep],
+ [if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi])
+ EGREP=$ac_cv_prog_egrep
+ AC_SUBST([EGREP])
+])])
+
+
+# AC_PATH_TOOL_PREFIX
+# -------------------
+# find a file program which can recognise shared library
+AC_DEFUN([AC_PATH_TOOL_PREFIX],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] | ?:[\\/]*])
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word. This closes a longstanding sh security hole.
+ ac_dummy="ifelse([$2], , $PATH, [$2])"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$1; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ AC_MSG_RESULT($MAGIC_CMD)
+else
+ AC_MSG_RESULT(no)
+fi
+])# AC_PATH_TOOL_PREFIX
+
+
+# AC_PATH_MAGIC
+# -------------
+# find a file program which can recognise a shared library
+AC_DEFUN([AC_PATH_MAGIC],
+[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+ else
+ MAGIC_CMD=:
+ fi
+fi
+])# AC_PATH_MAGIC
+
+
+# AC_PROG_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([AC_PROG_LD],
+[AC_ARG_WITH([gnu-ld],
+ [AC_HELP_STRING([--with-gnu-ld],
+ [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+ [test "$withval" = no || with_gnu_ld=yes],
+ [with_gnu_ld=no])
+AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by $CC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]]* | ?:[[\\/]]*)
+ re_direlt='/[[^/]][[^/]]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_PROG_LD_GNU
+])# AC_PROG_LD
+
+
+# AC_PROG_LD_GNU
+# --------------
+AC_DEFUN([AC_PROG_LD_GNU],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# AC_PROG_LD_GNU
+
+
+# AC_PROG_LD_RELOAD_FLAG
+# ----------------------
+# find reload flag for linker
+# -- PORTME Some linkers may need a different reload flag.
+AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+ lt_cv_ld_reload_flag,
+ [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+])# AC_PROG_LD_RELOAD_FLAG
+
+
+# AC_DEPLIBS_CHECK_METHOD
+# -----------------------
+# how to check for library dependencies
+# -- PORTME fill in with the dynamic library characteristics
+AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
+[AC_CACHE_CHECK([how to recognise dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[[45]]*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump'.
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | kfreebsd*-gnu | dragonfly*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix3*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+nto-qnx*)
+ lt_cv_deplibs_check_method=unknown
+ ;;
+
+openbsd*)
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+])# AC_DEPLIBS_CHECK_METHOD
+
+
+# AC_PROG_NM
+# ----------
+# find the pathname to a BSD-compatible name lister
+AC_DEFUN([AC_PROG_NM],
+[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM,
+[if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ lt_nm_to_check="${ac_tool_prefix}nm"
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm="$ac_dir/$lt_tmp_nm"
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+ done
+ test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi])
+NM="$lt_cv_path_NM"
+])# AC_PROG_NM
+
+
+# AC_CHECK_LIBM
+# -------------
+# check for math library
+AC_DEFUN([AC_CHECK_LIBM],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
+ # These system don't have libm, or don't need it
+ ;;
+*-ncr-sysv4.3*)
+ AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+ AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+ ;;
+*)
+ AC_CHECK_LIB(m, cos, LIBM="-lm")
+ ;;
+esac
+])# AC_CHECK_LIBM
+
+
+# AC_LIBLTDL_CONVENIENCE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl convenience library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-convenience to the configure arguments. Note that
+# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided,
+# it is assumed to be `libltdl'. LIBLTDL will be prefixed with
+# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/'
+# (note the single quotes!). If your package is not flat and you're not
+# using automake, define top_builddir and top_srcdir appropriately in
+# the Makefiles.
+AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+ case $enable_ltdl_convenience in
+ no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+ "") enable_ltdl_convenience=yes
+ ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+ esac
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+ LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+ # For backwards non-gettext consistent compatibility...
+ INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_CONVENIENCE
+
+
+# AC_LIBLTDL_INSTALLABLE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl installable library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-install to the configure arguments. Note that
+# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided,
+# and an installed libltdl is not found, it is assumed to be `libltdl'.
+# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with
+# '${top_srcdir}/' (note the single quotes!). If your package is not
+# flat and you're not using automake, define top_builddir and top_srcdir
+# appropriately in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+ AC_CHECK_LIB(ltdl, lt_dlinit,
+ [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+ [if test x"$enable_ltdl_install" = xno; then
+ AC_MSG_WARN([libltdl not installed, but installation disabled])
+ else
+ enable_ltdl_install=yes
+ fi
+ ])
+ if test x"$enable_ltdl_install" = x"yes"; then
+ ac_configure_args="$ac_configure_args --enable-ltdl-install"
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+ LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+ else
+ ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+ LIBLTDL="-lltdl"
+ LTDLINCL=
+ fi
+ # For backwards non-gettext consistent compatibility...
+ INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_INSTALLABLE
+
+
+# AC_LIBTOOL_CXX
+# --------------
+# enable support for C++ libraries
+AC_DEFUN([AC_LIBTOOL_CXX],
+[AC_REQUIRE([_LT_AC_LANG_CXX])
+])# AC_LIBTOOL_CXX
+
+
+# _LT_AC_LANG_CXX
+# ---------------
+AC_DEFUN([_LT_AC_LANG_CXX],
+[AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([_LT_AC_PROG_CXXCPP])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX])
+])# _LT_AC_LANG_CXX
+
+# _LT_AC_PROG_CXXCPP
+# ------------------
+AC_DEFUN([_LT_AC_PROG_CXXCPP],
+[
+AC_REQUIRE([AC_PROG_CXX])
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ AC_PROG_CXXCPP
+fi
+])# _LT_AC_PROG_CXXCPP
+
+# AC_LIBTOOL_F77
+# --------------
+# enable support for Fortran 77 libraries
+AC_DEFUN([AC_LIBTOOL_F77],
+[AC_REQUIRE([_LT_AC_LANG_F77])
+])# AC_LIBTOOL_F77
+
+
+# _LT_AC_LANG_F77
+# ---------------
+AC_DEFUN([_LT_AC_LANG_F77],
+[AC_REQUIRE([AC_PROG_F77])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77])
+])# _LT_AC_LANG_F77
+
+
+# AC_LIBTOOL_GCJ
+# --------------
+# enable support for GCJ libraries
+AC_DEFUN([AC_LIBTOOL_GCJ],
+[AC_REQUIRE([_LT_AC_LANG_GCJ])
+])# AC_LIBTOOL_GCJ
+
+
+# _LT_AC_LANG_GCJ
+# ---------------
+AC_DEFUN([_LT_AC_LANG_GCJ],
+[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[],
+ [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[],
+ [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])],
+ [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])],
+ [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ])
+])# _LT_AC_LANG_GCJ
+
+
+# AC_LIBTOOL_RC
+# -------------
+# enable support for Windows resource files
+AC_DEFUN([AC_LIBTOOL_RC],
+[AC_REQUIRE([LT_AC_PROG_RC])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC])
+])# AC_LIBTOOL_RC
+
+
+# AC_LIBTOOL_LANG_C_CONFIG
+# ------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG])
+AC_DEFUN([_LT_AC_LANG_C_CONFIG],
+[lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}\n'
+
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+AC_LIBTOOL_DLOPEN_SELF
+
+# Report which library types will actually be built
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_C_CONFIG
+
+
+# AC_LIBTOOL_LANG_CXX_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)])
+AC_DEFUN([_LT_AC_LANG_CXX_CONFIG],
+[AC_LANG_PUSH(C++)
+AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([_LT_AC_PROG_CXXCPP])
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Dependencies to place before and after the object being linked:
+_LT_AC_TAGVAR(predep_objects, $1)=
+_LT_AC_TAGVAR(postdep_objects, $1)=
+_LT_AC_TAGVAR(predeps, $1)=
+_LT_AC_TAGVAR(postdeps, $1)=
+_LT_AC_TAGVAR(compiler_lib_search_path, $1)=
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+ $as_unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+ $as_unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+else
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+fi
+
+if test "$GXX" = yes; then
+ # Set up default GNU C++ configuration
+
+ AC_PROG_LD
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test "$with_gnu_ld" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='${wl}'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+ grep 'no-whole-archive' > /dev/null; then
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+_LT_AC_TAGVAR(ld_shlibs, $1)=yes
+case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_AC_TAGVAR(archive_cmds, $1)=''
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ if test "$GXX" = yes; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ else
+ # We have old collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(always_export_symbols, $1)=no
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ if test "$GXX" = yes ; then
+ lt_int_apple_cc_single_mod=no
+ output_verbose_link_cmd='echo'
+ if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
+ lt_int_apple_cc_single_mod=yes
+ fi
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ fi
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ fi
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ freebsd[[12]]*)
+ # C++ shared libraries reported to be fairly broken before switch to ELF
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ freebsd-elf*)
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ ;;
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+ gnu*)
+ ;;
+ hpux9*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+ ;;
+ *)
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ interix3*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+ fi
+ fi
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+ esac
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc*)
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ ;;
+ pgCC*)
+ # Portland Group C++ compiler
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ esac
+ ;;
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ m88k*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ openbsd*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ fi
+ output_verbose_link_cmd='echo'
+ ;;
+ osf3*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~
+ $rm $lib.exp'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ psos*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The C++ compiler is used as linker so we must use $wl
+ # flag to pass the commands to the underlying system
+ # linker. We must also pass each convience library through
+ # to the system linker between allextract/defaultextract.
+ # The C++ compiler will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract'
+ ;;
+ esac
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ output_verbose_link_cmd='echo'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+ if $CC --version | grep -v '^2\.7' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ fi
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+ fi
+ ;;
+ esac
+ ;;
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ # So that behaviour is only enabled if SCOABSPATH is set to a
+ # non-empty value in the environment. Most likely only useful for
+ # creating official distributions of packages.
+ # This is a hack until libtool officially supports absolute path
+ # names for shared libraries.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+esac
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_AC_TAGVAR(GCC, $1)="$GXX"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+AC_LIBTOOL_POSTDEP_PREDEP($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+])# AC_LIBTOOL_LANG_CXX_CONFIG
+
+# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME])
+# ------------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library. It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+ifelse([$1],[],[cat > conftest.$ac_ext <<EOF
+int a;
+void foo (void) { a = 0; }
+EOF
+],[$1],[CXX],[cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+EOF
+],[$1],[F77],[cat > conftest.$ac_ext <<EOF
+ subroutine foo
+ implicit none
+ integer*4 a
+ a=0
+ return
+ end
+EOF
+],[$1],[GCJ],[cat > conftest.$ac_ext <<EOF
+public class foo {
+ private int a;
+ public void bar (void) {
+ a = 0;
+ }
+};
+EOF
+])
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ # The `*' in the case matches for architectures that use `case' in
+ # $output_verbose_cmd can trigger glob expansion during the loop
+ # eval without this substitution.
+ output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
+
+ for p in `eval $output_verbose_link_cmd`; do
+ case $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" \
+ || test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p in
+ -L* | -R*)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then
+ _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+ else
+ _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$_LT_AC_TAGVAR(postdeps, $1)"; then
+ _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}"
+ else
+ _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${prev}${p}"
+ fi
+ fi
+ ;;
+
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ if test -z "$_LT_AC_TAGVAR(predep_objects, $1)"; then
+ _LT_AC_TAGVAR(predep_objects, $1)="$p"
+ else
+ _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p"
+ fi
+ else
+ if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then
+ _LT_AC_TAGVAR(postdep_objects, $1)="$p"
+ else
+ _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$rm -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+ifelse([$1],[CXX],
+[case $host_os in
+interix3*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ _LT_AC_TAGVAR(predep_objects,$1)=
+ _LT_AC_TAGVAR(postdep_objects,$1)=
+ _LT_AC_TAGVAR(postdeps,$1)=
+ ;;
+
+solaris*)
+ case $cc_basename in
+ CC*)
+ # Adding this requires a known-good setup of shared libraries for
+ # Sun compiler versions before 5.6, else PIC objects from an old
+ # archive will be linked into the output, leading to subtle bugs.
+ _LT_AC_TAGVAR(postdeps,$1)='-lCstd -lCrun'
+ ;;
+ esac
+ ;;
+esac
+])
+
+case " $_LT_AC_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+])# AC_LIBTOOL_POSTDEP_PREDEP
+
+# AC_LIBTOOL_LANG_F77_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)])
+AC_DEFUN([_LT_AC_LANG_F77_CONFIG],
+[AC_REQUIRE([AC_PROG_F77])
+AC_LANG_PUSH(Fortran 77)
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code=" subroutine t\n return\n end\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code=" program t\n end\n"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+_LT_AC_TAGVAR(GCC, $1)="$G77"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_F77_CONFIG
+
+
+# AC_LIBTOOL_LANG_GCJ_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)])
+AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_GCJ_CONFIG
+
+
+# AC_LIBTOOL_LANG_RC_CONFIG
+# -------------------------
+# Ensure that the configuration vars for the Windows resource compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)])
+AC_DEFUN([_LT_AC_LANG_RC_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_RC_CONFIG
+
+
+# AC_LIBTOOL_CONFIG([TAGNAME])
+# ----------------------------
+# If TAGNAME is not passed, then create an initial libtool script
+# with a default configuration from the untagged config vars. Otherwise
+# add code to config.status for appending the configuration named by
+# TAGNAME from the matching tagged config vars.
+AC_DEFUN([AC_LIBTOOL_CONFIG],
+[# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ _LT_AC_TAGVAR(compiler, $1) \
+ _LT_AC_TAGVAR(CC, $1) \
+ _LT_AC_TAGVAR(LD, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \
+ _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \
+ _LT_AC_TAGVAR(old_archive_cmds, $1) \
+ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \
+ _LT_AC_TAGVAR(predep_objects, $1) \
+ _LT_AC_TAGVAR(postdep_objects, $1) \
+ _LT_AC_TAGVAR(predeps, $1) \
+ _LT_AC_TAGVAR(postdeps, $1) \
+ _LT_AC_TAGVAR(compiler_lib_search_path, $1) \
+ _LT_AC_TAGVAR(archive_cmds, $1) \
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1) \
+ _LT_AC_TAGVAR(postinstall_cmds, $1) \
+ _LT_AC_TAGVAR(postuninstall_cmds, $1) \
+ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \
+ _LT_AC_TAGVAR(allow_undefined_flag, $1) \
+ _LT_AC_TAGVAR(no_undefined_flag, $1) \
+ _LT_AC_TAGVAR(export_symbols_cmds, $1) \
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \
+ _LT_AC_TAGVAR(hardcode_automatic, $1) \
+ _LT_AC_TAGVAR(module_cmds, $1) \
+ _LT_AC_TAGVAR(module_expsym_cmds, $1) \
+ _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \
+ _LT_AC_TAGVAR(exclude_expsyms, $1) \
+ _LT_AC_TAGVAR(include_expsyms, $1); do
+
+ case $var in
+ _LT_AC_TAGVAR(old_archive_cmds, $1) | \
+ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \
+ _LT_AC_TAGVAR(archive_cmds, $1) | \
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \
+ _LT_AC_TAGVAR(module_cmds, $1) | \
+ _LT_AC_TAGVAR(module_expsym_cmds, $1) | \
+ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \
+ _LT_AC_TAGVAR(export_symbols_cmds, $1) | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\[$]0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'`
+ ;;
+ esac
+
+ifelse([$1], [],
+ [cfgfile="${ofile}T"
+ trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+ $rm -f "$cfgfile"
+ AC_MSG_NOTICE([creating $ofile])],
+ [cfgfile="$ofile"])
+
+ cat <<__EOF__ >> "$cfgfile"
+ifelse([$1], [],
+[#! $SHELL
+
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# 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
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e 1s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG],
+[# ### BEGIN LIBTOOL TAG CONFIG: $tagname])
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_[]_LT_AC_TAGVAR(compiler, $1)
+
+# Is the compiler the GNU C compiler?
+with_gcc=$_LT_AC_TAGVAR(GCC, $1)
+
+gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\`
+gcc_ver=\`gcc -dumpversion\`
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_[]_LT_AC_TAGVAR(LD, $1)
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1)
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1)
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1)
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1)
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1)
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1)
+archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1)
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1)
+module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1)
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=\`echo $lt_[]_LT_AC_TAGVAR(predep_objects, $1) | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=\`echo $lt_[]_LT_AC_TAGVAR(postdep_objects, $1) | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1)
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=\`echo $lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1)
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1)
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1)
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1)
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1)
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1)
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1)
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1)
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1)
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1)
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1)
+
+# Symbols that must always be exported.
+include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1)
+
+ifelse([$1],[],
+[# ### END LIBTOOL CONFIG],
+[# ### END LIBTOOL TAG CONFIG: $tagname])
+
+__EOF__
+
+ifelse([$1],[], [
+ case $host_os in
+ aix3*)
+ cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+EOF
+ ;;
+ esac
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" || \
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+])
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+])# AC_LIBTOOL_CONFIG
+
+
+# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI],
+[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+
+_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+
+ AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+ lt_cv_prog_compiler_rtti_exceptions,
+ [-fno-rtti -fno-exceptions], [],
+ [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI
+
+
+# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+# ---------------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_NM])
+AC_REQUIRE([AC_OBJEXT])
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[[BCDT]]'
+ ;;
+cygwin* | mingw* | pw32*)
+ symcode='[[ABCDGISTW]]'
+ ;;
+hpux*) # Its linker distinguishes data from code symbols
+ if test "$host_cpu" = ia64; then
+ symcode='[[ABCDEGRST]]'
+ fi
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ ;;
+linux*)
+ if test "$host_cpu" = ia64; then
+ symcode='[[ABCDGIRSTW]]'
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[[BCDEGRST]]'
+ ;;
+osf*)
+ symcode='[[BCDEGQRST]]'
+ ;;
+solaris*)
+ symcode='[[BDRT]]'
+ ;;
+sco3.2v5*)
+ symcode='[[DT]]'
+ ;;
+sysv4.2uw2*)
+ symcode='[[DT]]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[[ABDT]]'
+ ;;
+sysv4)
+ symcode='[[DFNSTU]]'
+ ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+ if AC_TRY_EVAL(ac_compile); then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if grep ' nm_test_var$' "$nlist" >/dev/null; then
+ if grep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+ cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[[]] =
+{
+EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+ cat <<\EOF >> conftest.$ac_ext
+ {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_save_LIBS="$LIBS"
+ lt_save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+ pipe_works=yes
+ fi
+ LIBS="$lt_save_LIBS"
+ CFLAGS="$lt_save_CFLAGS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+ cat conftest.$ac_ext >&5
+ fi
+ rm -f conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ AC_MSG_RESULT(failed)
+else
+ AC_MSG_RESULT(ok)
+fi
+]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+
+
+# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME])
+# ---------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC],
+[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=
+
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+ ifelse([$1],[CXX],[
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | os2* | pw32*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix4* | aix5*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ esac
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ if test "$host_cpu" != ia64; then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ fi
+ ;;
+ aCC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ icpc* | ecpc*)
+ # Intel C++
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgCC*)
+ # Portland Group C++ compiler.
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd*)
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+],
+[
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC (with -KPIC) is the default.
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ newsos6)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ linux*)
+ case $cc_basename in
+ icc* | ecc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ ccc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All Alpha code is PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All OSF/1 code is PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ solaris*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ unicos*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+
+ uts4*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)])
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then
+ AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works],
+ _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1),
+ [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [],
+ [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in
+ "" | " "*) ;;
+ *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+ esac],
+ [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\"
+AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+ _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1),
+ $lt_tmp_static_flag,
+ [],
+ [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=])
+])
+
+
+# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME])
+# ------------------------------------
+# See if the linker supports building shared libraries.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS],
+[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ifelse([$1],[CXX],[
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ case $host_os in
+ aix4* | aix5*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+ ;;
+ cygwin* | mingw*)
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ *)
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+],[
+ runpath_var=
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+ _LT_AC_TAGVAR(archive_cmds, $1)=
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)=
+ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ _LT_AC_TAGVAR(thread_safe_flag_spec, $1)=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+ _LT_AC_TAGVAR(hardcode_automatic, $1)=no
+ _LT_AC_TAGVAR(module_cmds, $1)=
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)=
+ _LT_AC_TAGVAR(always_export_symbols, $1)=no
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ _LT_AC_TAGVAR(include_expsyms, $1)=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ _LT_CC_BASENAME([$compiler])
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(always_export_symbols, $1)=no
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ interix3*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+
+ if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then
+ runpath_var=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_AC_TAGVAR(archive_cmds, $1)=''
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ else
+ # We have old collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ # see comment about different semantics on the GNU ld section
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ bsdi[[45]]*)
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true'
+ # FIXME: Should let the user specify the lib program.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ freebsd1*)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ newsos6)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ openbsd*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ else
+ case $host_os in
+ openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ else
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ solaris*)
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl, iff we do not link with $LD.
+ # Luckily, gcc supports the same syntax we need for Sun Studio.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ case $wlarc in
+ '')
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;;
+ *)
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
+ esac ;;
+ esac
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ ;;
+ motorola)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4.3*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*)
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+ # Assume -lc should be added
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $_LT_AC_TAGVAR(archive_cmds, $1) in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+ pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+ if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
+ then
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ else
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+ fi
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)])
+ ;;
+ esac
+ fi
+ ;;
+esac
+])# AC_LIBTOOL_PROG_LD_SHLIBS
+
+
+# _LT_AC_FILE_LTDLL_C
+# -------------------
+# Be careful that the start marker always follows a newline.
+AC_DEFUN([_LT_AC_FILE_LTDLL_C], [
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# # ifdef __CYGWIN32__
+# # define __CYGWIN__ __CYGWIN32__
+# # endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+# __hDllInstance_base = hInst;
+# return TRUE;
+# }
+# /* ltdll.c ends here */
+])# _LT_AC_FILE_LTDLL_C
+
+
+# _LT_AC_TAGVAR(VARNAME, [TAGNAME])
+# ---------------------------------
+AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])])
+
+
+# old names
+AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL])
+AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+AC_DEFUN([AM_PROG_LD], [AC_PROG_LD])
+AC_DEFUN([AM_PROG_NM], [AC_PROG_NM])
+
+# This is just to silence aclocal about the macro not being used
+ifelse([AC_DISABLE_FAST_INSTALL])
+
+AC_DEFUN([LT_AC_PROG_GCJ],
+[AC_CHECK_TOOL(GCJ, gcj, no)
+ test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+ AC_SUBST(GCJFLAGS)
+])
+
+AC_DEFUN([LT_AC_PROG_RC],
+[AC_CHECK_TOOL(RC, windres, no)
+])
+
+# NOTE: This macro has been submitted for inclusion into #
+# GNU Autoconf as AC_PROG_SED. When it is available in #
+# a released version of Autoconf we should remove this #
+# macro and use it instead. #
+# LT_AC_PROG_SED
+# --------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible. Prefer GNU sed if found.
+AC_DEFUN([LT_AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f $lt_ac_sed && continue
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test $lt_ac_count -gt 10 && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test $lt_ac_count -gt $lt_ac_max; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])
+
+# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file 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.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION so it can be traced.
+# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+ [AM_AUTOMAKE_VERSION([1.9.6])])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file 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.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file 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.
+
+# serial 7
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])
+AC_SUBST([$1_FALSE])
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file 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.
+
+# serial 8
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
+ [$1], CXX, [depcc="$CXX" am_compiler_list=],
+ [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file 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.
+
+#serial 3
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # So let's grep whole file.
+ if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. FIXME. This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file 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.
+
+# serial 8
+
+# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS.
+AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file 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.
+
+# serial 12
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.58])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+# test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" &&
+ test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES(CC)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+])
+])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $1 | $1:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file 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.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+#
+# This file 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.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file 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.
+
+# serial 3
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+ am__include=include
+ am__quote=
+ _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ fi
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file 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.
+
+# serial 4
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+#
+# This file 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.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise.
+#
+# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories
+# created by `make install' are always world readable, even if the
+# installer happens to have an overly restrictive umask (e.g. 077).
+# This was a mistake. There are at least two reasons why we must not
+# use `-m 0755':
+# - it causes special bits like SGID to be ignored,
+# - it may be too restrictive (some setups expect 775 directories).
+#
+# Do not use -m 0755 and let people choose whatever they expect by
+# setting umask.
+#
+# We cannot accept any implementation of `mkdir' that recognizes `-p'.
+# Some implementations (such as Solaris 8's) are not thread-safe: if a
+# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c'
+# concurrently, both version can detect that a/ is missing, but only
+# one can create it and the other will error out. Consequently we
+# restrict ourselves to GNU make (using the --version option ensures
+# this.)
+AC_DEFUN([AM_PROG_MKDIR_P],
+[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+ # We used to keeping the `.' as first argument, in order to
+ # allow $(mkdir_p) to be used without argument. As in
+ # $(mkdir_p) $(somedir)
+ # where $(somedir) is conditionally defined. However this is wrong
+ # for two reasons:
+ # 1. if the package is installed by a user who cannot write `.'
+ # make install will fail,
+ # 2. the above comment should most certainly read
+ # $(mkdir_p) $(DESTDIR)$(somedir)
+ # so it does not work when $(somedir) is undefined and
+ # $(DESTDIR) is not.
+ # To support the latter case, we have to write
+ # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
+ # so the `.' trick is pointless.
+ mkdir_p='mkdir -p --'
+else
+ # On NextStep and OpenStep, the `mkdir' command does not
+ # recognize any option. It will interpret all options as
+ # directories to create, and then abort because `.' already
+ # exists.
+ for d in ./-p ./--version;
+ do
+ test -d $d && rmdir $d
+ done
+ # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
+ if test -f "$ac_aux_dir/mkinstalldirs"; then
+ mkdir_p='$(mkinstalldirs)'
+ else
+ mkdir_p='$(install_sh) -d'
+ fi
+fi
+AC_SUBST([mkdir_p])])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file 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.
+
+# serial 3
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file 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.
+
+# serial 4
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file 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.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+#
+# This file 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.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [m4_case([$1], [ustar],, [pax],,
+ [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar;
+ do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
diff --git a/beforeconf.sh b/beforeconf.sh
new file mode 100755
index 0000000..535a597
--- /dev/null
+++ b/beforeconf.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+# beforeconf.sh
+# Run this to reconfigure after unpacking the tarball,
+# before running ./configure
+#
+am_files="mkinstalldirs missing"
+am_dir=`ls -d /usr/share/automake* |tail -n1`
+lt_files="ltmain.sh config.guess config.sub"
+lt_dir=/usr/share/libtool/libltdl
+my_dir=`pwd`
+
+#ltver=`rpm -q libtool |cut -f2 -d'-'`
+ltver=`libtool --version | head -n1 |awk '{ print $4 }'`
+ltv1=`echo $ltver |cut -f1 -d'.'`
+if [ "$ltv1" != "1" ]; then
+ # many distros have libtool-2.x.x
+ lt_dir="/usr/share/libtool/config"
+ lt_files="compile config.guess config.sub depcomp install-sh ltmain.sh missing"
+fi
+
+cd $my_dir
+rm -rf autom4te.cache
+aclocal
+
+# Note that MacOS Darwin returns 0 to which even if error.
+which libtoolize >/dev/null 2>&1
+if [ $? -eq 0 ]; then
+ # use libtoolize if possible
+ cd $my_dir
+ libtoolize --automake --copy --force
+elif [ -d $lt_dir ]; then
+ cp -f /usr/bin/libtool $my_dir
+ cd $lt_dir
+ cp -f ${lt_files} $my_dir
+fi
+# copy missing am_files if needed
+if [ -d $am_dir ]; then
+ cd $am_dir
+ for f in ${am_files}
+ do
+ if [ ! -f $my_dir/$f ]; then
+ cp -f $f $my_dir
+ fi
+ done
+fi
+
+cd $my_dir
+# autoreconf -fiv
+autoheader
+automake --foreign --add-missing --copy
+
+aclocal
+autoconf
+automake --foreign
+
diff --git a/buildsamp.cmd b/buildsamp.cmd
new file mode 100644
index 0000000..886125c
--- /dev/null
+++ b/buildsamp.cmd
@@ -0,0 +1,13 @@
+
+set | findstr VCINSTALLDIR
+if %errorlevel% EQU 1 goto vcerror
+
+cd util
+nmake -f ipmi_sample.mak all
+cd ..
+goto done
+
+:vcerror
+echo Need to first run vcvars.bat
+
+:done
diff --git a/buildwin.cmd b/buildwin.cmd
new file mode 100644
index 0000000..2057935
--- /dev/null
+++ b/buildwin.cmd
@@ -0,0 +1,45 @@
+@echo off
+REM # buildwin.cmd
+REM # build ipmiutil for windows
+REM #
+REM # First download a copy of getopt.c getopt.h.
+REM # copy getopt.* util
+REM # Then download and build a copy of openssl for Windows,
+REM # and copy the built openssl files needed to lib & inc.
+REM # copy libeay32.lib ssleay32.lib lib
+REM # copy libeay32.dll ssleay32.dll util
+REM # copy include\openssl\*.h lib\lanplus\inc\openssl
+REM #
+REM # You should either run this from the Visual Studio Command Line,
+REM # or first run the appropriate vcvars.bat script.
+set | findstr VCINSTALLDIR
+if %errorlevel% EQU 1 goto vcerror
+
+REM TODO, prebuild checking:
+REM check for getopt.c,h
+REM check for ssl libs
+REM check for ssl includes
+REM call mkssl
+
+set UTMAKE=ipmiutil.mak
+echo %LIBPATH% |findstr /C:amd64 >NUL
+if %errorlevel% EQU 0 set UTMAKE=ipmiutil64.mak
+
+cd lib
+nmake /nologo -f ipmilib.mak all
+cd ..
+REM # echo make lib done
+
+cd util
+nmake /nologo -f %UTMAKE% all
+cd ..
+REM # echo make util done
+
+echo buildwin ipmiutil done
+goto done
+
+:vcerror
+echo First need to run vcvars.bat
+
+:done
+
diff --git a/buildwin2.cmd b/buildwin2.cmd
new file mode 100644
index 0000000..c4fff81
--- /dev/null
+++ b/buildwin2.cmd
@@ -0,0 +1,31 @@
+@echo off
+REM # buildwin2.cmd
+REM # build ipmiutil for windows in standalone mode
+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
+
+set UTMAKE=ipmiutil2.mak
+echo %LIBPATH% |findstr /C:amd64 >NUL
+if %errorlevel% EQU 0 set UTMAKE=ipmiutil2-64.mak
+
+cd util
+nmake /nologo -f %UTMAKE% all
+cd ..
+
+echo buildwin2 ipmiutil done
+goto done
+
+:vcerror
+echo Need to first run vcvars.bat
+
+:done
+
diff --git a/cleanwin.cmd b/cleanwin.cmd
new file mode 100644
index 0000000..0fbd64e
--- /dev/null
+++ b/cleanwin.cmd
@@ -0,0 +1,23 @@
+@echo off
+REM # cleanwin.cmd
+REM # clean ipmiutil for windows
+REM #
+
+REM call cleanssl (?)
+
+set UTMAKE=ipmiutil.mak
+echo %LIBPATH% |findstr /C:amd64 >NUL
+if %errorlevel% EQU 0 set UTMAKE=ipmiutil64.mak
+
+cd lib
+nmake /nologo -f ipmilib.mak clean
+cd ..
+REM # echo make lib done
+
+cd util
+nmake /nologo -f %UTMAKE% clean
+del *.pdb 2>NUL
+cd ..
+REM # echo make util done
+
+echo cleanwin ipmiutil done
diff --git a/config.guess b/config.guess
new file mode 100755
index 0000000..2fc3acc
--- /dev/null
+++ b/config.guess
@@ -0,0 +1,1411 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2003-06-17'
+
+# This file 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
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+## for Red Hat Linux
+if test -f /etc/redhat-release ; then
+ VENDOR=redhat ;
+else
+ VENDOR= ;
+fi
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvmeppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mipseb-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ if test $UNAME_RELEASE = "V4.0"; then
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ fi
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha*:OpenVMS:*:*)
+ echo alpha-hp-vms
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit 0;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit 0 ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit 0 ;;
+ DRS?6000:UNIX_SV:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7 && exit 0 ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c \
+ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && exit 0
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ # avoid double evaluation of $set_cc_for_build
+ test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ *:UNICOS/mp:*:*)
+ echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*|*:GNU/FreeBSD:*:*)
+ # Determine whether the default compiler uses glibc.
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #if __GLIBC__ >= 2
+ LIBC=gnu
+ #else
+ LIBC=
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit 0 ;;
+ x86:Interix*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit 0 ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit 0 ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit 0 ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR:-unknown}-linux-gnu
+ exit 0 ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ ppc:Linux:*:*)
+ echo powerpc-${VENDOR:-unknown}-linux-gnu
+ exit 0 ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-${VENDOR:-unknown}-linux-gnu
+ exit 0 ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit 0 ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit 0 ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit 0 ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-${VENDOR:-ibm}-linux-gnu
+ exit 0 ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ x86_64:Linux:*:*)
+ echo x86_64-${VENDOR:-unknown}-linux-gnu
+ exit 0 ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit 0 ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit 0 ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit 0 ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-${VENDOR:-pc}-linux-${LIBC}" && exit 0
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit 0 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit 0 ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit 0 ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit 0 ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit 0 ;;
+ i*86:*:5:[78]*)
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit 0 ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+ case `uname -p` in
+ *86) UNAME_PROCESSOR=i686 ;;
+ powerpc) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit 0 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit 0 ;;
+ NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit 0 ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit 0 ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit 0 ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit 0 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit 0 ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit 0 ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit 0 ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit 0 ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit 0 ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit 0 ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..95d7e2c
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,118 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the <dlfcn.h> 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 <fcntl.h> 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 <inttypes.h> 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 <memory.h> 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 <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> 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 <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> 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 <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
+
+/* 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 <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to 1 if your <sys/time.h> 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' if <sys/types.h> does not define. */
+#undef off_t
+
+/* if socklen_t is not defined, provide something useful */
+#undef socklen_t
diff --git a/config.sub b/config.sub
new file mode 100755
index 0000000..6b2ff9f
--- /dev/null
+++ b/config.sub
@@ -0,0 +1,1500 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2003-06-18'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file 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 WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit 0;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k \
+ | m32r | m68000 | m68k | m88k | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | msp430 \
+ | ns16k | ns32k \
+ | openrisc | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | s390 | s390x \
+ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* \
+ | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* \
+ | m32r-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | msp430-* \
+ | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | s390-* | s390x-* \
+ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+ | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ mmix*)
+ basic_machine=mmix-knuth
+ os=-mmixware
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nv1)
+ basic_machine=nv1-cray
+ os=-unicosmp
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ or32 | or32-*)
+ basic_machine=or32-unknown
+ os=-coff
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure b/configure
new file mode 100755
index 0000000..9bd7483
--- /dev/null
+++ b/configure
@@ -0,0 +1,22199 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','`
+ ;;
+esac
+
+echo=${ECHO-echo}
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if (echo_test_string=`eval $cmd`) 2>/dev/null &&
+ echo_test_string=`eval $cmd` &&
+ (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+ then
+ break
+ fi
+ done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ if test "X$echo" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ echo='print -r'
+ elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
+ else
+ # Try using printf.
+ echo='printf %s\n'
+ if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+ if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "$0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ echo=echo
+ fi
+ fi
+ fi
+ fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+ ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
+fi
+
+
+
+
+tagnames=${tagnames+${tagnames},}CXX
+
+tagnames=${tagnames+${tagnames},}F77
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete. It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="util/ipmiutil.c"
+ac_default_prefix=/usr
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE LN_S SED CPP EGREP build build_cpu build_vendor build_os host host_cpu host_vendor host_os ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL LANDESK_CFLAGS LANDESK_LDADD IA64_CFLAGS LANPLUS_CFLAGS LANPLUS_LDADD LANPLUS_LIB LANPLUS_CRYPTO LANPLUS_SAM LD_SAMX GPL_CFLAGS OS_CFLAGS OS_LFLAGS OS_DRIVERS PKG_DIR INIT_DIR LIB_DIR INS_LIB SUBDIR_S CROSS_CFLAGS CROSS_LFLAGS SYSTEMD_DIR SHR_LINK LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_option in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ eval "enable_$ac_feature=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_$ac_feature='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_$ac_package='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/-/_/g'`
+ eval "with_$ac_package=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ eval "$ac_envvar='$ac_optarg'"
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+ localstatedir libdir includedir oldincludedir infodir mandir
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+ { (exit 1); exit 1; }; }
+ else
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+ fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+ { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+ac_env_CXX_set=${CXX+set}
+ac_env_CXX_value=$CXX
+ac_cv_env_CXX_set=${CXX+set}
+ac_cv_env_CXX_value=$CXX
+ac_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_env_CXXFLAGS_value=$CXXFLAGS
+ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_cv_env_CXXFLAGS_value=$CXXFLAGS
+ac_env_CXXCPP_set=${CXXCPP+set}
+ac_env_CXXCPP_value=$CXXCPP
+ac_cv_env_CXXCPP_set=${CXXCPP+set}
+ac_cv_env_CXXCPP_value=$CXXCPP
+ac_env_F77_set=${F77+set}
+ac_env_F77_value=$F77
+ac_cv_env_F77_set=${F77+set}
+ac_cv_env_F77_value=$F77
+ac_env_FFLAGS_set=${FFLAGS+set}
+ac_env_FFLAGS_value=$FFLAGS
+ac_cv_env_FFLAGS_set=${FFLAGS+set}
+ac_cv_env_FFLAGS_value=$FFLAGS
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+ cat <<_ACEOF
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --infodir=DIR info documentation [PREFIX/info]
+ --mandir=DIR man documentation [PREFIX/man]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors
+ --enable-shared[=PKGS]
+ build shared libraries [default=yes]
+ --enable-static[=PKGS]
+ build static libraries [default=yes]
+ --enable-fast-install[=PKGS]
+ optimize for fast installation [default=yes]
+ --disable-libtool-lock avoid locking (might break parallel builds)
+ --enable-landesk adds landesk library support [default=no]
+ --disable-lanplus disable lanplus support [default=enabled]
+ --enable-sha256 build with SHA256 support, requires later openssl.
+ --enable-standalone build standalone, with no GPL or LanPlus libs.
+ --enable-gpl build with some GPL code [default=no]
+ --enable-systemd enable systemd service type=notify support and %_unitdir [default=disabled]
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-gnu-ld assume the C compiler uses GNU ld [default=no]
+ --with-pic try to use only PIC/non-PIC objects [default=use
+ both]
+ --with-tags[=TAGS]
+ include additional configurations [automatic]
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
+ headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ CXXCPP C++ preprocessor
+ F77 Fortran 77 compiler command
+ FFLAGS Fortran 77 compiler flags
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ ac_popdir=`pwd`
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d $ac_dir || continue
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+ cd $ac_dir
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_srcdir/configure.gnu; then
+ echo
+ $SHELL $ac_srcdir/configure.gnu --help=recursive
+ elif test -f $ac_srcdir/configure; then
+ echo
+ $SHELL $ac_srcdir/configure --help=recursive
+ elif test -f $ac_srcdir/configure.ac ||
+ test -f $ac_srcdir/configure.in; then
+ echo
+ $ac_configure --help
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi
+ cd $ac_popdir
+ done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+ cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+ # Get rid of the leading space.
+ ac_sep=" "
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+{
+ (set) 2>&1 |
+ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ sed -n \
+ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+ ;;
+ *)
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+}
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ sed "/^$/d" confdefs.h | sort
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core &&
+ rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+ ' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . $cache_file;;
+ *) . ./$cache_file;;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+ eval ac_new_val="\$ac_env_${ac_var}_value"
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+am__api_version="1.9"
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f $ac_dir/shtool; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL=$ac_install_sh
+ fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,$program_prefix,;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$,$program_suffix,;$program_transform_name"
+# Double any \ or $. echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm conftest.sed
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+ # We used to keeping the `.' as first argument, in order to
+ # allow $(mkdir_p) to be used without argument. As in
+ # $(mkdir_p) $(somedir)
+ # where $(somedir) is conditionally defined. However this is wrong
+ # for two reasons:
+ # 1. if the package is installed by a user who cannot write `.'
+ # make install will fail,
+ # 2. the above comment should most certainly read
+ # $(mkdir_p) $(DESTDIR)$(somedir)
+ # so it does not work when $(somedir) is undefined and
+ # $(DESTDIR) is not.
+ # To support the latter case, we have to write
+ # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
+ # so the `.' trick is pointless.
+ mkdir_p='mkdir -p --'
+else
+ # On NextStep and OpenStep, the `mkdir' command does not
+ # recognize any option. It will interpret all options as
+ # directories to create, and then abort because `.' already
+ # exists.
+ for d in ./-p ./--version;
+ do
+ test -d $d && rmdir $d
+ done
+ # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
+ if test -f "$ac_aux_dir/mkinstalldirs"; then
+ mkdir_p='$(mkinstalldirs)'
+ else
+ mkdir_p='$(install_sh) -d'
+ fi
+fi
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AWK+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AWK="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$AWK" && break
+done
+
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.make <<\_ACEOF
+all:
+ @echo 'ac_maketemp="$(MAKE)"'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftest.make
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ SET_MAKE=
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+# test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" &&
+ test -f $srcdir/config.status; then
+ { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE=ipmiutil
+ VERSION=2.9.3
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":"
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ STRIP=$ac_ct_STRIP
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+ ac_config_headers="$ac_config_headers config.h"
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_CC" && break
+done
+
+ CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+ "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+ (eval $ac_link_default) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Find the output, starting from the most likely. This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+ ;;
+ conftest.$ac_ext )
+ # This is the source file.
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ # FIXME: I believe we export ac_cv_exeext for Libtool,
+ # but it would be cool to find out if it's true. Does anybody
+ # maintain Libtool? --akim.
+ export ac_cv_exeext
+ break;;
+ * )
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ export ac_cv_exeext
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std1 is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std1. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX 10.20 and later -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+ x|xno)
+ echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+ *)
+ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+ CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C. Since we use `exit',
+# in C++ we need to declare it. In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+ choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ for ac_declaration in \
+ '' \
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);'
+do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+DEPDIR="${am__leading_dot}deps"
+
+ ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
+echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+ am__include=include
+ am__quote=
+ _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ fi
+fi
+
+
+echo "$as_me:$LINENO: result: $_am_result" >&5
+echo "${ECHO_T}$_am_result" >&6
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+ enableval="$enable_dependency_tracking"
+
+fi;
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+
+
+if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+
+
+depcc="$CC" am_compiler_list=
+
+echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+
+
+if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL=$ac_install_sh
+ fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+ echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6
+fi
+
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.make <<\_ACEOF
+all:
+ @echo 'ac_maketemp="$(MAKE)"'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftest.make
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ SET_MAKE=
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+# Extract the first word of "sed", so it can be a program name with args.
+set dummy sed; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_SED+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$SED"; then
+ ac_cv_prog_SED="$SED" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_SED="sed"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+SED=$ac_cv_prog_SED
+if test -n "$SED"; then
+ echo "$as_me:$LINENO: result: $SED" >&5
+echo "${ECHO_T}$SED" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ exit(2);
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+for ac_header in fcntl.h sys/ioctl.h syslog.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
+if test "${ac_cv_c_const+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this. */
+ typedef int charset[2];
+ const charset x;
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *ccp;
+ char **p;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ ccp = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++ccp;
+ p = (char**) ccp;
+ ccp = (char const *const *) p;
+ { /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ }
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_const=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_const=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for off_t" >&5
+echo $ECHO_N "checking for off_t... $ECHO_C" >&6
+if test "${ac_cv_type_off_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((off_t *) 0)
+ return 0;
+if (sizeof (off_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_off_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_off_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
+echo "${ECHO_T}$ac_cv_type_off_t" >&6
+if test $ac_cv_type_off_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off_t long
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5
+echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6
+if test "${ac_cv_header_time+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_time=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_time=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
+echo "${ECHO_T}$ac_cv_header_time" >&6
+if test $ac_cv_header_time = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TIME_WITH_SYS_TIME 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5
+echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6
+if test "${ac_cv_struct_tm+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm *tp; tp->tm_sec;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_struct_tm=time.h
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_struct_tm=sys/time.h
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5
+echo "${ECHO_T}$ac_cv_struct_tm" >&6
+if test $ac_cv_struct_tm = sys/time.h; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TM_IN_SYS_TIME 1
+_ACEOF
+
+fi
+
+
+if test $ac_cv_c_compiler_gnu = yes; then
+ echo "$as_me:$LINENO: checking whether $CC needs -traditional" >&5
+echo $ECHO_N "checking whether $CC needs -traditional... $ECHO_C" >&6
+if test "${ac_cv_prog_gcc_traditional+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_pattern="Autoconf.*'x'"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then
+ ac_cv_prog_gcc_traditional=yes
+else
+ ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+ if test $ac_cv_prog_gcc_traditional = no; then
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then
+ ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_gcc_traditional" >&5
+echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6
+ if test $ac_cv_prog_gcc_traditional = yes; then
+ CC="$CC -traditional"
+ fi
+fi
+
+
+
+for ac_header in stdlib.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in getpagesize
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+echo "$as_me:$LINENO: checking for working mmap" >&5
+echo $ECHO_N "checking for working mmap... $ECHO_C" >&6
+if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_mmap_fixed_mapped=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+/* malloc might have been renamed as rpl_malloc. */
+#undef malloc
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+ Here is a matrix of mmap possibilities:
+ mmap private not fixed
+ mmap private fixed at somewhere currently unmapped
+ mmap private fixed at somewhere already mapped
+ mmap shared not fixed
+ mmap shared fixed at somewhere currently unmapped
+ mmap shared fixed at somewhere already mapped
+ For private mappings, we should verify that changes cannot be read()
+ back from the file, nor mmap's back from the file at a different
+ address. (There have been systems where private was not correctly
+ implemented like the infamous i386 svr4.0, and systems where the
+ VM page cache was not coherent with the file system buffer cache
+ like early versions of FreeBSD and possibly contemporary NetBSD.)
+ For shared mappings, we should conversely verify that changes get
+ propagated back to all the places they're supposed to be.
+
+ Grep wants private fixed already mapped.
+ The main things grep needs to know about mmap are:
+ * does it exist and is it safe to write into the mmap'd area
+ * how to use it (BSD variants) */
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#if !STDC_HEADERS && !HAVE_STDLIB_H
+char *malloc ();
+#endif
+
+/* This mess was copied from the GNU getpagesize.h. */
+#if !HAVE_GETPAGESIZE
+/* Assume that all systems that can run configure have sys/param.h. */
+# if !HAVE_SYS_PARAM_H
+# define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+# define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+# if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else /* no EXEC_PAGESIZE */
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif /* no CLSIZE */
+# else /* no NBPG */
+# ifdef NBPC
+# define getpagesize() NBPC
+# else /* no NBPC */
+# ifdef PAGESIZE
+# define getpagesize() PAGESIZE
+# endif /* PAGESIZE */
+# endif /* no NBPC */
+# endif /* no NBPG */
+# endif /* no EXEC_PAGESIZE */
+# else /* no HAVE_SYS_PARAM_H */
+# define getpagesize() 8192 /* punt totally */
+# endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+int
+main ()
+{
+ char *data, *data2, *data3;
+ int i, pagesize;
+ int fd;
+
+ pagesize = getpagesize ();
+
+ /* First, make a file with some known garbage in it. */
+ data = (char *) malloc (pagesize);
+ if (!data)
+ exit (1);
+ for (i = 0; i < pagesize; ++i)
+ *(data + i) = rand ();
+ umask (0);
+ fd = creat ("conftest.mmap", 0600);
+ if (fd < 0)
+ exit (1);
+ if (write (fd, data, pagesize) != pagesize)
+ exit (1);
+ close (fd);
+
+ /* Next, try to mmap the file at a fixed address which already has
+ something else allocated at it. If we can, also make sure that
+ we see the same garbage. */
+ fd = open ("conftest.mmap", O_RDWR);
+ if (fd < 0)
+ exit (1);
+ data2 = (char *) malloc (2 * pagesize);
+ if (!data2)
+ exit (1);
+ data2 += (pagesize - ((long) data2 & (pagesize - 1))) & (pagesize - 1);
+ if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED, fd, 0L))
+ exit (1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data2 + i))
+ exit (1);
+
+ /* Finally, make sure that changes to the mapped area do not
+ percolate back to the file as seen by read(). (This is a bug on
+ some variants of i386 svr4.0.) */
+ for (i = 0; i < pagesize; ++i)
+ *(data2 + i) = *(data2 + i) + 1;
+ data3 = (char *) malloc (pagesize);
+ if (!data3)
+ exit (1);
+ if (read (fd, data3, pagesize) != pagesize)
+ exit (1);
+ for (i = 0; i < pagesize; ++i)
+ if (*(data + i) != *(data3 + i))
+ exit (1);
+ close (fd);
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_mmap_fixed_mapped=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5
+echo "${ECHO_T}$ac_cv_func_mmap_fixed_mapped" >&6
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MMAP 1
+_ACEOF
+
+fi
+rm -f conftest.mmap
+
+
+for ac_func in strftime
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+ # strftime is in -lintl on SCO UNIX.
+echo "$as_me:$LINENO: checking for strftime in -lintl" >&5
+echo $ECHO_N "checking for strftime in -lintl... $ECHO_C" >&6
+if test "${ac_cv_lib_intl_strftime+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lintl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strftime ();
+int
+main ()
+{
+strftime ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_intl_strftime=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_intl_strftime=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_intl_strftime" >&5
+echo "${ECHO_T}$ac_cv_lib_intl_strftime" >&6
+if test $ac_cv_lib_intl_strftime = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRFTIME 1
+_ACEOF
+
+LIBS="-lintl $LIBS"
+fi
+
+fi
+done
+
+
+for ac_func in vprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+echo "$as_me:$LINENO: checking for _doprnt" >&5
+echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6
+if test "${ac_cv_func__doprnt+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define _doprnt to an innocuous variant, in case <limits.h> declares _doprnt.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define _doprnt innocuous__doprnt
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char _doprnt (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef _doprnt
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char _doprnt ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub__doprnt) || defined (__stub____doprnt)
+choke me
+#else
+char (*f) () = _doprnt;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != _doprnt;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func__doprnt=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func__doprnt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5
+echo "${ECHO_T}$ac_cv_func__doprnt" >&6
+if test $ac_cv_func__doprnt = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DOPRNT 1
+_ACEOF
+
+fi
+
+fi
+done
+
+
+
+
+
+
+
+
+
+for ac_func in select socket strcspn strdup strspn strtoul memcpy
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+ p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_shared=yes
+fi;
+
+# Check whether --enable-static or --disable-static was given.
+if test "${enable_static+set}" = set; then
+ enableval="$enable_static"
+ p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_static=yes
+fi;
+
+# Check whether --enable-fast-install or --disable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+ enableval="$enable_fast_install"
+ p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_fast_install=yes
+fi;
+
+# Make sure we can run config.sub.
+$ac_config_sub sun4 >/dev/null 2>&1 ||
+ { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5
+echo "$as_me: error: cannot run $ac_config_sub" >&2;}
+ { (exit 1); exit 1; }; }
+
+echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6
+if test "${ac_cv_build+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_build_alias=$build_alias
+test -z "$ac_cv_build_alias" &&
+ ac_cv_build_alias=`$ac_config_guess`
+test -z "$ac_cv_build_alias" &&
+ { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+ { (exit 1); exit 1; }; }
+ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
+ { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6
+build=$ac_cv_build
+build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6
+if test "${ac_cv_host+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_host_alias=$host_alias
+test -z "$ac_cv_host_alias" &&
+ ac_cv_host_alias=$ac_cv_build_alias
+ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
+ { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6
+host=$ac_cv_host
+host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5
+echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6
+if test "${lt_cv_path_SED+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f $lt_ac_sed && continue
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test $lt_ac_count -gt 10 && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test $lt_ac_count -gt $lt_ac_max; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+
+fi
+
+SED=$lt_cv_path_SED
+
+echo "$as_me:$LINENO: result: $SED" >&5
+echo "${ECHO_T}$SED" >&6
+
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval="$with_gnu_ld"
+ test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi;
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
+else
+ echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+ { (exit 1); exit 1; }; }
+echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5
+echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6
+if test "${lt_cv_ld_reload_flag+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_ld_reload_flag='-r'
+fi
+echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5
+echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
+echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6
+if test "${lt_cv_path_NM+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ lt_nm_to_check="${ac_tool_prefix}nm"
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm="$ac_dir/$lt_tmp_nm"
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+ done
+ test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi
+fi
+echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5
+echo "${ECHO_T}$lt_cv_path_NM" >&6
+NM="$lt_cv_path_NM"
+
+echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5
+echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6
+if test "${lt_cv_deplibs_check_method+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[45]*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump'.
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | kfreebsd*-gnu | dragonfly*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix3*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+nto-qnx*)
+ lt_cv_deplibs_check_method=unknown
+ ;;
+
+openbsd*)
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5
+echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+ enableval="$enable_libtool_lock"
+
+fi;
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE="32"
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE="64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '#line 5710 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ ppc*-*linux*|powerpc*-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
+echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6
+if test "${lt_cv_cc_needs_belf+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ lt_cv_cc_needs_belf=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+lt_cv_cc_needs_belf=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
+echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+sparc*-*solaris*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*) LD="${LD-ld} -m elf64_sparc" ;;
+ *) LD="${LD-ld} -64" ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+
+esac
+
+need_locks="$enable_libtool_lock"
+
+
+
+for ac_header in dlfcn.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_CXX" && break
+done
+test -n "$ac_ct_CXX" || ac_ct_CXX="g++"
+
+ CXX=$ac_ct_CXX
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+ "checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cxx_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+for ac_declaration in \
+ '' \
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);'
+do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+depcc="$CXX" am_compiler_list=
+
+echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6
+if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CXX_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CXX_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+
+
+if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+ am__fastdepCXX_TRUE=
+ am__fastdepCXX_FALSE='#'
+else
+ am__fastdepCXX_TRUE='#'
+ am__fastdepCXX_FALSE=
+fi
+
+
+
+
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
+echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6
+if test -z "$CXXCPP"; then
+ if test "${ac_cv_prog_CXXCPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CXXCPP needs to be expanded
+ for CXXCPP in "$CXX -E" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+ CXXCPP=$ac_cv_prog_CXXCPP
+else
+ ac_cv_prog_CXXCPP=$CXXCPP
+fi
+echo "$as_me:$LINENO: result: $CXXCPP" >&5
+echo "${ECHO_T}$CXXCPP" >&6
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+fi
+
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$F77"; then
+ ac_cv_prog_F77="$F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_F77="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+F77=$ac_cv_prog_F77
+if test -n "$F77"; then
+ echo "$as_me:$LINENO: result: $F77" >&5
+echo "${ECHO_T}$F77" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$F77" && break
+ done
+fi
+if test -z "$F77"; then
+ ac_ct_F77=$F77
+ for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_F77"; then
+ ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_F77="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_F77=$ac_cv_prog_ac_ct_F77
+if test -n "$ac_ct_F77"; then
+ echo "$as_me:$LINENO: result: $ac_ct_F77" >&5
+echo "${ECHO_T}$ac_ct_F77" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_F77" && break
+done
+
+ F77=$ac_ct_F77
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:6836:" \
+ "checking for Fortran 77 compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+rm -f a.out
+
+# If we don't use `.F' as extension, the preprocessor is not run on the
+# input file. (Note that this only needs to work for GNU compilers.)
+ac_save_ext=$ac_ext
+ac_ext=F
+echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6
+if test "${ac_cv_f77_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+#ifndef __GNUC__
+ choke me
+#endif
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_f77_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6
+ac_ext=$ac_save_ext
+ac_test_FFLAGS=${FFLAGS+set}
+ac_save_FFLAGS=$FFLAGS
+FFLAGS=
+echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5
+echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_f77_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ FFLAGS=-g
+cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_f77_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_f77_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5
+echo "${ECHO_T}$ac_cv_prog_f77_g" >&6
+if test "$ac_test_FFLAGS" = set; then
+ FFLAGS=$ac_save_FFLAGS
+elif test $ac_cv_prog_f77_g = yes; then
+ if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+ FFLAGS="-g -O2"
+ else
+ FFLAGS="-g"
+ fi
+else
+ if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+ FFLAGS="-O2"
+ else
+ FFLAGS=
+ fi
+fi
+
+G77=`test $ac_compiler_gnu = yes && echo yes`
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+
+# find the maximum length of command line arguments
+echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5
+echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6
+if test "${lt_cv_sys_max_cmd_len+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ i=0
+ teststring="ABCD"
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \
+ = "XX$teststring") >/dev/null 2>&1 &&
+ new_result=`expr "X$teststring" : ".*" 2>&1` &&
+ lt_cv_sys_max_cmd_len=$new_result &&
+ test $i != 17 # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on massive
+ # amounts of additional arguments before passing them to the linker.
+ # It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ ;;
+ esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+ echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5
+echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6
+else
+ echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
+fi
+
+
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5
+echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6
+if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[BCDT]'
+ ;;
+cygwin* | mingw* | pw32*)
+ symcode='[ABCDGISTW]'
+ ;;
+hpux*) # Its linker distinguishes data from code symbols
+ if test "$host_cpu" = ia64; then
+ symcode='[ABCDEGRST]'
+ fi
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ ;;
+linux*)
+ if test "$host_cpu" = ia64; then
+ symcode='[ABCDGIRSTW]'
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[BCDEGRST]'
+ ;;
+osf*)
+ symcode='[BCDEGQRST]'
+ ;;
+solaris*)
+ symcode='[BDRT]'
+ ;;
+sco3.2v5*)
+ symcode='[DT]'
+ ;;
+sysv4.2uw2*)
+ symcode='[DT]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[ABDT]'
+ ;;
+sysv4)
+ symcode='[DFNSTU]'
+ ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5
+ (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if grep ' nm_test_var$' "$nlist" >/dev/null; then
+ if grep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+ cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+ cat <<\EOF >> conftest.$ac_ext
+ {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_save_LIBS="$LIBS"
+ lt_save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext}; then
+ pipe_works=yes
+ fi
+ LIBS="$lt_save_LIBS"
+ CFLAGS="$lt_save_CFLAGS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&5
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&5
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+ fi
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ fi
+ rm -f conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ echo "$as_me:$LINENO: result: failed" >&5
+echo "${ECHO_T}failed" >&6
+else
+ echo "$as_me:$LINENO: result: ok" >&5
+echo "${ECHO_T}ok" >&6
+fi
+
+echo "$as_me:$LINENO: checking for objdir" >&5
+echo $ECHO_N "checking for objdir... $ECHO_C" >&6
+if test "${lt_cv_objdir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5
+echo "${ECHO_T}$lt_cv_objdir" >&6
+objdir=$lt_cv_objdir
+
+
+
+
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_AR" && ac_cv_prog_ac_ct_AR="false"
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
+echo "${ECHO_T}$ac_ct_AR" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ AR=$ac_ct_AR
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ RANLIB=$ac_ct_RANLIB
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":"
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ STRIP=$ac_ct_STRIP
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5
+echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/${ac_tool_prefix}file; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ echo "$as_me:$LINENO: checking for file" >&5
+echo $ECHO_N "checking for file... $ECHO_C" >&6
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/file; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ else
+ MAGIC_CMD=:
+ fi
+fi
+
+ fi
+ ;;
+esac
+
+enable_dlopen=no
+enable_win32_dll=no
+
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+ enableval="$enable_libtool_lock"
+
+fi;
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+
+# Check whether --with-pic or --without-pic was given.
+if test "${with_pic+set}" = set; then
+ withval="$with_pic"
+ pic_mode="$withval"
+else
+ pic_mode=default
+fi;
+test -z "$pic_mode" && pic_mode=default
+
+# Use C for the default configuration in the libtool script
+tagname=
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}\n'
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+ lt_prog_compiler_no_builtin_flag=' -fno-builtin'
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_rtti_exceptions=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="-fno-rtti -fno-exceptions"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:7899: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:7903: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_rtti_exceptions=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+ lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+ :
+fi
+
+fi
+
+lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_static='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic='-fno-common'
+ ;;
+
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ else
+ lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic='-qnocommon'
+ lt_prog_compiler_wl='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ linux*)
+ case $cc_basename in
+ icc* | ecc*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fpic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ lt_prog_compiler_wl='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl='-Qoption ld '
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic='-Kconform_pic'
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_can_build_shared=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic='-pic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic" >&6
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6
+if test "${lt_prog_compiler_pic_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:8167: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:8171: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6
+
+if test x"$lt_prog_compiler_pic_works" = xyes; then
+ case $lt_prog_compiler_pic in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+ esac
+else
+ lt_prog_compiler_pic=
+ lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic=
+ ;;
+ *)
+ lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
+if test "${lt_prog_compiler_static_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works=yes
+ fi
+ else
+ lt_prog_compiler_static_works=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works" >&6
+
+if test x"$lt_prog_compiler_static_works" = xyes; then
+ :
+else
+ lt_prog_compiler_static=
+fi
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:8271: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:8275: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
+
+ runpath_var=
+ allow_undefined_flag=
+ enable_shared_with_static_runtimes=no
+ archive_cmds=
+ archive_expsym_cmds=
+ old_archive_From_new_cmds=
+ old_archive_from_expsyms_cmds=
+ export_dynamic_flag_spec=
+ whole_archive_flag_spec=
+ thread_safe_flag_spec=
+ hardcode_libdir_flag_spec=
+ hardcode_libdir_flag_spec_ld=
+ hardcode_libdir_separator=
+ hardcode_direct=no
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=unsupported
+ link_all_deplibs=unknown
+ hardcode_automatic=no
+ module_cmds=
+ module_expsym_cmds=
+ always_export_symbols=no
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ ld_shlibs=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ allow_undefined_flag=unsupported
+ always_export_symbols=no
+ enable_shared_with_static_runtimes=yes
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ interix3*)
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ archive_cmds='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs" = no; then
+ runpath_var=
+ hardcode_libdir_flag_spec=
+ export_dynamic_flag_spec=
+ whole_archive_flag_spec=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds=''
+ hardcode_direct=yes
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct=yes
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag="-z nodefs"
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag=' ${wl}-bernotok'
+ allow_undefined_flag=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec='$convenience'
+ archive_cmds_need_lc=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs=no
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_From_new_cmds='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc=no
+ hardcode_direct=no
+ hardcode_automatic=yes
+ hardcode_shlibpath_var=unsupported
+ whole_archive_flag_spec=''
+ link_all_deplibs=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ export_dynamic_flag_spec='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+
+ hardcode_direct=yes
+ export_dynamic_flag_spec='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld='+b $libdir'
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ ;;
+ *)
+ hardcode_direct=yes
+ export_dynamic_flag_spec='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_ld='-rpath $libdir'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ link_all_deplibs=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ newsos6)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_shlibpath_var=no
+ ;;
+
+ openbsd*)
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ *)
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ hardcode_libdir_separator=:
+ ;;
+
+ solaris*)
+ no_undefined_flag=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl, iff we do not link with $LD.
+ # Luckily, gcc supports the same syntax we need for Sun Studio.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ case $wlarc in
+ '')
+ whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+ *)
+ whole_archive_flag_spec='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
+ esac ;;
+ esac
+ link_all_deplibs=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds='$CC -r -o $output$reload_objs'
+ hardcode_direct=no
+ ;;
+ motorola)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ export_dynamic_flag_spec='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
+ no_undefined_flag='${wl}-z,text'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag='${wl}-z,text'
+ allow_undefined_flag='${wl}-z,nodefs'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+ export_dynamic_flag_spec='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $ld_shlibs" >&5
+echo "${ECHO_T}$ld_shlibs" >&6
+test "$ld_shlibs" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl
+ pic_flag=$lt_prog_compiler_pic
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag
+ allow_undefined_flag=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc=no
+ else
+ archive_cmds_need_lc=yes
+ fi
+ allow_undefined_flag=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5
+echo "${ECHO_T}$archive_cmds_need_lc" >&6
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # find out which ABI we are using
+ libsuff=
+ case "$host_cpu" in
+ x86_64*|s390x*|powerpc64*)
+ echo '#line 9740 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *64-bit*)
+ libsuff=64
+ sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+ esac
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+ test -n "$runpath_var" || \
+ test "X$hardcode_automatic" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no &&
+ test "$hardcode_minus_L" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action=unsupported
+fi
+echo "$as_me:$LINENO: result: $hardcode_action" >&5
+echo "${ECHO_T}$hardcode_action" >&6
+
+if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+striplib=
+old_striplib=
+echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
+echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+ ;;
+ *)
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ ;;
+ esac
+fi
+
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+int
+main ()
+{
+dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dl_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
+if test $ac_cv_lib_dl_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+
+fi
+
+ ;;
+
+ *)
+ echo "$as_me:$LINENO: checking for shl_load" >&5
+echo $ECHO_N "checking for shl_load... $ECHO_C" >&6
+if test "${ac_cv_func_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define shl_load innocuous_shl_load
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shl_load (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef shl_load
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char shl_load ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_shl_load) || defined (__stub___shl_load)
+choke me
+#else
+char (*f) () = shl_load;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != shl_load;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_shl_load=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
+echo "${ECHO_T}$ac_cv_func_shl_load" >&6
+if test $ac_cv_func_shl_load = yes; then
+ lt_cv_dlopen="shl_load"
+else
+ echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char shl_load ();
+int
+main ()
+{
+shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dld_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dld_shl_load=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6
+if test $ac_cv_lib_dld_shl_load = yes; then
+ lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"
+else
+ echo "$as_me:$LINENO: checking for dlopen" >&5
+echo $ECHO_N "checking for dlopen... $ECHO_C" >&6
+if test "${ac_cv_func_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define dlopen innocuous_dlopen
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char dlopen (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef dlopen
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_dlopen) || defined (__stub___dlopen)
+choke me
+#else
+char (*f) () = dlopen;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != dlopen;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
+echo "${ECHO_T}$ac_cv_func_dlopen" >&6
+if test $ac_cv_func_dlopen = yes; then
+ lt_cv_dlopen="dlopen"
+else
+ echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+int
+main ()
+{
+dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dl_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
+if test $ac_cv_lib_dl_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+ echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
+echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+int
+main ()
+{
+dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_svld_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_svld_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6
+if test $ac_cv_lib_svld_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+ echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
+echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dld_link ();
+int
+main ()
+{
+dld_link ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_dld_dld_link=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dld_dld_link=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6
+if test $ac_cv_lib_dld_dld_link = yes; then
+ lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
+echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6
+if test "${lt_cv_dlopen_self+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+#line 10637 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ exit (status);
+}
+EOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self" >&6
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
+echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self_static=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+#line 10737 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ exit (status);
+}
+EOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self_static=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+
+
+# Report which library types will actually be built
+echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6
+
+echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6
+
+echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler \
+ CC \
+ LD \
+ lt_prog_compiler_wl \
+ lt_prog_compiler_pic \
+ lt_prog_compiler_static \
+ lt_prog_compiler_no_builtin_flag \
+ export_dynamic_flag_spec \
+ thread_safe_flag_spec \
+ whole_archive_flag_spec \
+ enable_shared_with_static_runtimes \
+ old_archive_cmds \
+ old_archive_from_new_cmds \
+ predep_objects \
+ postdep_objects \
+ predeps \
+ postdeps \
+ compiler_lib_search_path \
+ archive_cmds \
+ archive_expsym_cmds \
+ postinstall_cmds \
+ postuninstall_cmds \
+ old_archive_from_expsyms_cmds \
+ allow_undefined_flag \
+ no_undefined_flag \
+ export_symbols_cmds \
+ hardcode_libdir_flag_spec \
+ hardcode_libdir_flag_spec_ld \
+ hardcode_libdir_separator \
+ hardcode_automatic \
+ module_cmds \
+ module_expsym_cmds \
+ lt_cv_prog_compiler_c_o \
+ exclude_expsyms \
+ include_expsyms; do
+
+ case $var in
+ old_archive_cmds | \
+ old_archive_from_new_cmds | \
+ archive_cmds | \
+ archive_expsym_cmds | \
+ module_cmds | \
+ module_expsym_cmds | \
+ old_archive_from_expsyms_cmds | \
+ export_symbols_cmds | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="${ofile}T"
+ trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+ $rm -f "$cfgfile"
+ { echo "$as_me:$LINENO: creating $ofile" >&5
+echo "$as_me: creating $ofile" >&6;}
+
+ cat <<__EOF__ >> "$cfgfile"
+#! $SHELL
+
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# 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
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e 1s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC
+
+gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\`
+gcc_ver=\`gcc -dumpversion\`
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=\`echo $lt_predep_objects | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=\`echo $lt_postdep_objects | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=\`echo $lt_compiler_lib_search_path | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# ### END LIBTOOL CONFIG
+
+__EOF__
+
+
+ case $host_os in
+ aix3*)
+ cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+EOF
+ ;;
+ esac
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" || \
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+# Check whether --with-tags or --without-tags was given.
+if test "${with_tags+set}" = set; then
+ withval="$with_tags"
+ tagnames="$withval"
+fi;
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+ if test ! -f "${ofile}"; then
+ { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5
+echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;}
+ fi
+
+ if test -z "$LTCC"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+ if test -z "$LTCC"; then
+ { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5
+echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;}
+ else
+ { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5
+echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;}
+ fi
+ fi
+ if test -z "$LTCFLAGS"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`"
+ fi
+
+ # Extract list of available tagged configurations in $ofile.
+ # Note that this assumes the entire list is on one line.
+ available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for tagname in $tagnames; do
+ IFS="$lt_save_ifs"
+ # Check whether tagname contains only valid characters
+ case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in
+ "") ;;
+ *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5
+echo "$as_me: error: invalid tag name: $tagname" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+ then
+ { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5
+echo "$as_me: error: tag name \"$tagname\" already exists" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ # Update the list of available tags.
+ if test -n "$tagname"; then
+ echo appending configuration tag \"$tagname\" to $ofile
+
+ case $tagname in
+ CXX)
+ if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+
+archive_cmds_need_lc_CXX=no
+allow_undefined_flag_CXX=
+always_export_symbols_CXX=no
+archive_expsym_cmds_CXX=
+export_dynamic_flag_spec_CXX=
+hardcode_direct_CXX=no
+hardcode_libdir_flag_spec_CXX=
+hardcode_libdir_flag_spec_ld_CXX=
+hardcode_libdir_separator_CXX=
+hardcode_minus_L_CXX=no
+hardcode_shlibpath_var_CXX=unsupported
+hardcode_automatic_CXX=no
+module_cmds_CXX=
+module_expsym_cmds_CXX=
+link_all_deplibs_CXX=unknown
+old_archive_cmds_CXX=$old_archive_cmds
+no_undefined_flag_CXX=
+whole_archive_flag_spec_CXX=
+enable_shared_with_static_runtimes_CXX=no
+
+# Dependencies to place before and after the object being linked:
+predep_objects_CXX=
+postdep_objects_CXX=
+predeps_CXX=
+postdeps_CXX=
+compiler_lib_search_path_CXX=
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+objext_CXX=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+ $as_unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+ $as_unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+compiler_CXX=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+ lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
+else
+ lt_prog_compiler_no_builtin_flag_CXX=
+fi
+
+if test "$GXX" = yes; then
+ # Set up default GNU C++ configuration
+
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval="$with_gnu_ld"
+ test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi;
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
+else
+ echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+ { (exit 1); exit 1; }; }
+echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test "$with_gnu_ld" = yes; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='${wl}'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+ grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_CXX=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
+ld_shlibs_CXX=yes
+case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_CXX=''
+ hardcode_direct_CXX=yes
+ hardcode_libdir_separator_CXX=':'
+ link_all_deplibs_CXX=yes
+
+ if test "$GXX" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct_CXX=yes
+ else
+ # We have old collect2
+ hardcode_direct_CXX=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_CXX=yes
+ hardcode_libdir_flag_spec_CXX='-L$libdir'
+ hardcode_libdir_separator_CXX=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols_CXX=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_CXX='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+ archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_CXX="-z nodefs"
+ archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_cxx_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_CXX=' ${wl}-bernotok'
+ allow_undefined_flag_CXX=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_CXX='$convenience'
+ archive_cmds_need_lc_CXX=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_CXX=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_CXX=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_CXX='-L$libdir'
+ allow_undefined_flag_CXX=unsupported
+ always_export_symbols_CXX=no
+ enable_shared_with_static_runtimes_CXX=yes
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc_CXX=no
+ hardcode_direct_CXX=no
+ hardcode_automatic_CXX=yes
+ hardcode_shlibpath_var_CXX=unsupported
+ whole_archive_flag_spec_CXX=''
+ link_all_deplibs_CXX=yes
+
+ if test "$GXX" = yes ; then
+ lt_int_apple_cc_single_mod=no
+ output_verbose_link_cmd='echo'
+ if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
+ lt_int_apple_cc_single_mod=yes
+ fi
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ else
+ archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ fi
+ module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ fi
+ module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ freebsd[12]*)
+ # C++ shared libraries reported to be fairly broken before switch to ELF
+ ld_shlibs_CXX=no
+ ;;
+ freebsd-elf*)
+ archive_cmds_need_lc_CXX=no
+ ;;
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ ld_shlibs_CXX=yes
+ ;;
+ gnu*)
+ ;;
+ hpux9*)
+ hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ hardcode_direct_CXX=yes
+ hardcode_minus_L_CXX=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aCC*)
+ archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; then
+ hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld_CXX='+b $libdir'
+ ;;
+ *)
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ ;;
+ *)
+ hardcode_direct_CXX=yes
+ hardcode_minus_L_CXX=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ interix3*)
+ hardcode_direct_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+ fi
+ fi
+ link_all_deplibs_CXX=yes
+ ;;
+ esac
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc*)
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ archive_cmds_need_lc_CXX=no
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ ;;
+ pgCC*)
+ # Portland Group C++ compiler
+ archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ esac
+ ;;
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ m88k*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ hardcode_direct_CXX=yes
+ hardcode_shlibpath_var_CXX=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ ld_shlibs_CXX=no
+ ;;
+ openbsd*)
+ hardcode_direct_CXX=yes
+ hardcode_shlibpath_var_CXX=no
+ archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ fi
+ output_verbose_link_cmd='echo'
+ ;;
+ osf3*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ cxx*)
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -o $oldlib $oldobjs'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ cxx*)
+ allow_undefined_flag_CXX=' -expect_unresolved \*'
+ archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~
+ $rm $lib.exp'
+
+ hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ psos*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ archive_cmds_need_lc_CXX=yes
+ no_undefined_flag_CXX=' -zdefs'
+ archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ hardcode_shlibpath_var_CXX=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The C++ compiler is used as linker so we must use $wl
+ # flag to pass the commands to the underlying system
+ # linker. We must also pass each convience library through
+ # to the system linker between allextract/defaultextract.
+ # The C++ compiler will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract'
+ ;;
+ esac
+ link_all_deplibs_CXX=yes
+
+ output_verbose_link_cmd='echo'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ no_undefined_flag_CXX=' ${wl}-z ${wl}defs'
+ if $CC --version | grep -v '^2\.7' > /dev/null; then
+ archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir'
+ fi
+ ;;
+ esac
+ ;;
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ no_undefined_flag_CXX='${wl}-z,text'
+ archive_cmds_need_lc_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ # So that behaviour is only enabled if SCOABSPATH is set to a
+ # non-empty value in the environment. Most likely only useful for
+ # creating official distributions of packages.
+ # This is a hack until libtool officially supports absolute path
+ # names for shared libraries.
+ no_undefined_flag_CXX='${wl}-z,text'
+ allow_undefined_flag_CXX='${wl}-z,nodefs'
+ archive_cmds_need_lc_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator_CXX=':'
+ link_all_deplibs_CXX=yes
+ export_dynamic_flag_spec_CXX='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+esac
+echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+GCC_CXX="$GXX"
+LD_CXX="$LD"
+
+
+cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+EOF
+
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ # The `*' in the case matches for architectures that use `case' in
+ # $output_verbose_cmd can trigger glob expansion during the loop
+ # eval without this substitution.
+ output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"`
+
+ for p in `eval $output_verbose_link_cmd`; do
+ case $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" \
+ || test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p in
+ -L* | -R*)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$compiler_lib_search_path_CXX"; then
+ compiler_lib_search_path_CXX="${prev}${p}"
+ else
+ compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$postdeps_CXX"; then
+ postdeps_CXX="${prev}${p}"
+ else
+ postdeps_CXX="${postdeps_CXX} ${prev}${p}"
+ fi
+ fi
+ ;;
+
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ if test -z "$predep_objects_CXX"; then
+ predep_objects_CXX="$p"
+ else
+ predep_objects_CXX="$predep_objects_CXX $p"
+ fi
+ else
+ if test -z "$postdep_objects_CXX"; then
+ postdep_objects_CXX="$p"
+ else
+ postdep_objects_CXX="$postdep_objects_CXX $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling CXX test program"
+fi
+
+$rm -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+case $host_os in
+interix3*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ predep_objects_CXX=
+ postdep_objects_CXX=
+ postdeps_CXX=
+ ;;
+
+solaris*)
+ case $cc_basename in
+ CC*)
+ # Adding this requires a known-good setup of shared libraries for
+ # Sun compiler versions before 5.6, else PIC objects from an old
+ # archive will be linked into the output, leading to subtle bugs.
+ postdeps_CXX='-lCstd -lCrun'
+ ;;
+ esac
+ ;;
+esac
+
+
+case " $postdeps_CXX " in
+*" -lc "*) archive_cmds_need_lc_CXX=no ;;
+esac
+
+lt_prog_compiler_wl_CXX=
+lt_prog_compiler_pic_CXX=
+lt_prog_compiler_static_CXX=
+
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
+
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; then
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_CXX='-Bstatic'
+ fi
+ ;;
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | os2* | pw32*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_CXX='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ lt_prog_compiler_pic_CXX=
+ ;;
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_CXX=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ esac
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix4* | aix5*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_CXX='-Bstatic'
+ else
+ lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic_CXX='-qnocommon'
+ lt_prog_compiler_wl_CXX='-Wl,'
+ ;;
+ esac
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ lt_prog_compiler_pic_CXX='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+ if test "$host_cpu" != ia64; then
+ lt_prog_compiler_pic_CXX='+Z'
+ fi
+ ;;
+ aCC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ lt_prog_compiler_wl_CXX='--backend -Wl,'
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ icpc* | ecpc*)
+ # Intel C++
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-static'
+ ;;
+ pgCC*)
+ # Portland Group C++ compiler.
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-fpic'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_static_CXX='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ lt_prog_compiler_pic_CXX='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd*)
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ lt_prog_compiler_wl_CXX='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ lt_prog_compiler_wl_CXX='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_static_CXX='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ lt_prog_compiler_wl_CXX='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ lt_prog_compiler_pic_CXX='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ lt_prog_compiler_pic_CXX='-pic'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ lt_prog_compiler_pic_CXX='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ lt_prog_compiler_can_build_shared_CXX=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_CXX"; then
+
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6
+if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works_CXX=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:13080: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:13084: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works_CXX=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6
+
+if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then
+ case $lt_prog_compiler_pic_CXX in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;;
+ esac
+else
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_can_build_shared_CXX=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_CXX=
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
+if test "${lt_prog_compiler_static_works_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works_CXX=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works_CXX=yes
+ fi
+ else
+ lt_prog_compiler_static_works_CXX=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6
+
+if test x"$lt_prog_compiler_static_works_CXX" = xyes; then
+ :
+else
+ lt_prog_compiler_static_CXX=
+fi
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o_CXX=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:13184: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:13188: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_CXX=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
+
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ case $host_os in
+ aix4* | aix5*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ export_symbols_cmds_CXX="$ltdll_cmds"
+ ;;
+ cygwin* | mingw*)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([^ ]*\) [^ ]*/\1 DATA/;/^I /d;/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ *)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+
+echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_CXX" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_CXX=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_CXX in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_CXX
+ pic_flag=$lt_prog_compiler_pic_CXX
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
+ allow_undefined_flag_CXX=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc_CXX=no
+ else
+ archive_cmds_need_lc_CXX=yes
+ fi
+ allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # find out which ABI we are using
+ libsuff=
+ case "$host_cpu" in
+ x86_64*|s390x*|powerpc64*)
+ echo '#line 13720 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *64-bit*)
+ libsuff=64
+ sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+ esac
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
+hardcode_action_CXX=
+if test -n "$hardcode_libdir_flag_spec_CXX" || \
+ test -n "$runpath_var_CXX" || \
+ test "X$hardcode_automatic_CXX" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct_CXX" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no &&
+ test "$hardcode_minus_L_CXX" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_CXX=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_CXX=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_CXX=unsupported
+fi
+echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5
+echo "${ECHO_T}$hardcode_action_CXX" >&6
+
+if test "$hardcode_action_CXX" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_CXX \
+ CC_CXX \
+ LD_CXX \
+ lt_prog_compiler_wl_CXX \
+ lt_prog_compiler_pic_CXX \
+ lt_prog_compiler_static_CXX \
+ lt_prog_compiler_no_builtin_flag_CXX \
+ export_dynamic_flag_spec_CXX \
+ thread_safe_flag_spec_CXX \
+ whole_archive_flag_spec_CXX \
+ enable_shared_with_static_runtimes_CXX \
+ old_archive_cmds_CXX \
+ old_archive_from_new_cmds_CXX \
+ predep_objects_CXX \
+ postdep_objects_CXX \
+ predeps_CXX \
+ postdeps_CXX \
+ compiler_lib_search_path_CXX \
+ archive_cmds_CXX \
+ archive_expsym_cmds_CXX \
+ postinstall_cmds_CXX \
+ postuninstall_cmds_CXX \
+ old_archive_from_expsyms_cmds_CXX \
+ allow_undefined_flag_CXX \
+ no_undefined_flag_CXX \
+ export_symbols_cmds_CXX \
+ hardcode_libdir_flag_spec_CXX \
+ hardcode_libdir_flag_spec_ld_CXX \
+ hardcode_libdir_separator_CXX \
+ hardcode_automatic_CXX \
+ module_cmds_CXX \
+ module_expsym_cmds_CXX \
+ lt_cv_prog_compiler_c_o_CXX \
+ exclude_expsyms_CXX \
+ include_expsyms_CXX; do
+
+ case $var in
+ old_archive_cmds_CXX | \
+ old_archive_from_new_cmds_CXX | \
+ archive_cmds_CXX | \
+ archive_expsym_cmds_CXX | \
+ module_cmds_CXX | \
+ module_expsym_cmds_CXX | \
+ old_archive_from_expsyms_cmds_CXX | \
+ export_symbols_cmds_CXX | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_CXX
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_CXX
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_CXX
+
+gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\`
+gcc_ver=\`gcc -dumpversion\`
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_CXX
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_CXX
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_CXX
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_CXX
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_CXX
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_CXX
+archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_CXX
+module_expsym_cmds=$lt_module_expsym_cmds_CXX
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=\`echo $lt_predep_objects_CXX | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=\`echo $lt_postdep_objects_CXX | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_CXX
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_CXX
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_CXX | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_CXX
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_CXX
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_CXX
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_CXX
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_CXX
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_CXX
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_CXX
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_CXX"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_CXX
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_CXX
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_CXX
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_CXX
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+
+ else
+ tagname=""
+ fi
+ ;;
+
+ F77)
+ if test -n "$F77" && test "X$F77" != "Xno"; then
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+archive_cmds_need_lc_F77=no
+allow_undefined_flag_F77=
+always_export_symbols_F77=no
+archive_expsym_cmds_F77=
+export_dynamic_flag_spec_F77=
+hardcode_direct_F77=no
+hardcode_libdir_flag_spec_F77=
+hardcode_libdir_flag_spec_ld_F77=
+hardcode_libdir_separator_F77=
+hardcode_minus_L_F77=no
+hardcode_automatic_F77=no
+module_cmds_F77=
+module_expsym_cmds_F77=
+link_all_deplibs_F77=unknown
+old_archive_cmds_F77=$old_archive_cmds
+no_undefined_flag_F77=
+whole_archive_flag_spec_F77=
+enable_shared_with_static_runtimes_F77=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+objext_F77=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code=" subroutine t\n return\n end\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code=" program t\n end\n"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+compiler_F77=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6
+
+echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case $host_os in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6
+
+echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6
+
+GCC_F77="$G77"
+LD_F77="$LD"
+
+lt_prog_compiler_wl_F77=
+lt_prog_compiler_pic_F77=
+lt_prog_compiler_static_F77=
+
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_static_F77='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_F77='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_F77='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_F77='-fno-common'
+ ;;
+
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared_F77=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_F77=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_F77='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ lt_prog_compiler_pic_F77='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_F77='-Bstatic'
+ else
+ lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic_F77='-qnocommon'
+ lt_prog_compiler_wl_F77='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_F77='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_F77='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static_F77='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static_F77='-non_shared'
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ linux*)
+ case $cc_basename in
+ icc* | ecc*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-fpic'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static_F77='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static_F77='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ lt_prog_compiler_wl_F77='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl_F77='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl_F77='-Qoption ld '
+ lt_prog_compiler_pic_F77='-PIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic_F77='-Kconform_pic'
+ lt_prog_compiler_static_F77='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_can_build_shared_F77=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic_F77='-pic'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared_F77=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_F77"; then
+
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6
+if test "${lt_prog_compiler_pic_works_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works_F77=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_F77"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:14778: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:14782: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works_F77=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6
+
+if test x"$lt_prog_compiler_pic_works_F77" = xyes; then
+ case $lt_prog_compiler_pic_F77 in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;;
+ esac
+else
+ lt_prog_compiler_pic_F77=
+ lt_prog_compiler_can_build_shared_F77=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_F77=
+ ;;
+ *)
+ lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\"
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
+if test "${lt_prog_compiler_static_works_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works_F77=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works_F77=yes
+ fi
+ else
+ lt_prog_compiler_static_works_F77=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6
+
+if test x"$lt_prog_compiler_static_works_F77" = xyes; then
+ :
+else
+ lt_prog_compiler_static_F77=
+fi
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o_F77=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:14882: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:14886: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_F77=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
+
+ runpath_var=
+ allow_undefined_flag_F77=
+ enable_shared_with_static_runtimes_F77=no
+ archive_cmds_F77=
+ archive_expsym_cmds_F77=
+ old_archive_From_new_cmds_F77=
+ old_archive_from_expsyms_cmds_F77=
+ export_dynamic_flag_spec_F77=
+ whole_archive_flag_spec_F77=
+ thread_safe_flag_spec_F77=
+ hardcode_libdir_flag_spec_F77=
+ hardcode_libdir_flag_spec_ld_F77=
+ hardcode_libdir_separator_F77=
+ hardcode_direct_F77=no
+ hardcode_minus_L_F77=no
+ hardcode_shlibpath_var_F77=unsupported
+ link_all_deplibs_F77=unknown
+ hardcode_automatic_F77=no
+ module_cmds_F77=
+ module_expsym_cmds_F77=
+ always_export_symbols_F77=no
+ export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms_F77=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs_F77=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_F77='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_F77=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs_F77=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_minus_L_F77=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ ld_shlibs_F77=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_F77=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ allow_undefined_flag_F77=unsupported
+ always_export_symbols_F77=no
+ enable_shared_with_static_runtimes_F77=yes
+ export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ interix3*)
+ hardcode_direct_F77=no
+ hardcode_shlibpath_var_F77=no
+ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_F77='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ archive_cmds_F77='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs_F77=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs_F77=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs_F77" = no; then
+ runpath_var=
+ hardcode_libdir_flag_spec_F77=
+ export_dynamic_flag_spec_F77=
+ whole_archive_flag_spec_F77=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag_F77=unsupported
+ always_export_symbols_F77=yes
+ archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L_F77=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct_F77=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_F77=''
+ hardcode_direct_F77=yes
+ hardcode_libdir_separator_F77=':'
+ link_all_deplibs_F77=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct_F77=yes
+ else
+ # We have old collect2
+ hardcode_direct_F77=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_F77=yes
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_libdir_separator_F77=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols_F77=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_F77='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_F77="-z nodefs"
+ archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_f77_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_F77=' ${wl}-bernotok'
+ allow_undefined_flag_F77=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_F77='$convenience'
+ archive_cmds_need_lc_F77=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_minus_L_F77=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs_F77=no
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec_F77=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec_F77=' '
+ allow_undefined_flag_F77=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_From_new_cmds_F77='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path_F77='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes_F77=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag_F77='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc_F77=no
+ hardcode_direct_F77=no
+ hardcode_automatic_F77=yes
+ hardcode_shlibpath_var_F77=unsupported
+ whole_archive_flag_spec_F77=''
+ link_all_deplibs_F77=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs_F77=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs_F77=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes
+ hardcode_minus_L_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ hardcode_direct_F77=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+
+ hardcode_direct_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_F77=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld_F77='+b $libdir'
+ hardcode_direct_F77=no
+ hardcode_shlibpath_var_F77=no
+ ;;
+ *)
+ hardcode_direct_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_F77=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_ld_F77='-rpath $libdir'
+ fi
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ link_all_deplibs_F77=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ newsos6)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ openbsd*)
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_F77='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ ;;
+ *)
+ archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_minus_L_F77=yes
+ allow_undefined_flag_F77=unsupported
+ archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag_F77=' -expect_unresolved \*'
+ archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag_F77=' -expect_unresolved \*'
+ archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec_F77='-rpath $libdir'
+ fi
+ hardcode_libdir_separator_F77=:
+ ;;
+
+ solaris*)
+ no_undefined_flag_F77=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_shlibpath_var_F77=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl, iff we do not link with $LD.
+ # Luckily, gcc supports the same syntax we need for Sun Studio.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ case $wlarc in
+ '')
+ whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;;
+ *)
+ whole_archive_flag_spec_F77='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
+ esac ;;
+ esac
+ link_all_deplibs_F77=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_direct_F77=yes
+ hardcode_minus_L_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds_F77='$CC -r -o $output$reload_objs'
+ hardcode_direct_F77=no
+ ;;
+ motorola)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_F77=no
+ export_dynamic_flag_spec_F77='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_F77=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs_F77=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
+ no_undefined_flag_F77='${wl}-z,text'
+ archive_cmds_need_lc_F77=no
+ hardcode_shlibpath_var_F77=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag_F77='${wl}-z,text'
+ allow_undefined_flag_F77='${wl}-z,nodefs'
+ archive_cmds_need_lc_F77=no
+ hardcode_shlibpath_var_F77=no
+ hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator_F77=':'
+ link_all_deplibs_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ *)
+ ld_shlibs_F77=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5
+echo "${ECHO_T}$ld_shlibs_F77" >&6
+test "$ld_shlibs_F77" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_F77" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_F77=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_F77 in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_F77
+ pic_flag=$lt_prog_compiler_pic_F77
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_F77
+ allow_undefined_flag_F77=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc_F77=no
+ else
+ archive_cmds_need_lc_F77=yes
+ fi
+ allow_undefined_flag_F77=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # find out which ABI we are using
+ libsuff=
+ case "$host_cpu" in
+ x86_64*|s390x*|powerpc64*)
+ echo '#line 16331 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *64-bit*)
+ libsuff=64
+ sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+ esac
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
+hardcode_action_F77=
+if test -n "$hardcode_libdir_flag_spec_F77" || \
+ test -n "$runpath_var_F77" || \
+ test "X$hardcode_automatic_F77" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct_F77" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no &&
+ test "$hardcode_minus_L_F77" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_F77=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_F77=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_F77=unsupported
+fi
+echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5
+echo "${ECHO_T}$hardcode_action_F77" >&6
+
+if test "$hardcode_action_F77" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_F77 \
+ CC_F77 \
+ LD_F77 \
+ lt_prog_compiler_wl_F77 \
+ lt_prog_compiler_pic_F77 \
+ lt_prog_compiler_static_F77 \
+ lt_prog_compiler_no_builtin_flag_F77 \
+ export_dynamic_flag_spec_F77 \
+ thread_safe_flag_spec_F77 \
+ whole_archive_flag_spec_F77 \
+ enable_shared_with_static_runtimes_F77 \
+ old_archive_cmds_F77 \
+ old_archive_from_new_cmds_F77 \
+ predep_objects_F77 \
+ postdep_objects_F77 \
+ predeps_F77 \
+ postdeps_F77 \
+ compiler_lib_search_path_F77 \
+ archive_cmds_F77 \
+ archive_expsym_cmds_F77 \
+ postinstall_cmds_F77 \
+ postuninstall_cmds_F77 \
+ old_archive_from_expsyms_cmds_F77 \
+ allow_undefined_flag_F77 \
+ no_undefined_flag_F77 \
+ export_symbols_cmds_F77 \
+ hardcode_libdir_flag_spec_F77 \
+ hardcode_libdir_flag_spec_ld_F77 \
+ hardcode_libdir_separator_F77 \
+ hardcode_automatic_F77 \
+ module_cmds_F77 \
+ module_expsym_cmds_F77 \
+ lt_cv_prog_compiler_c_o_F77 \
+ exclude_expsyms_F77 \
+ include_expsyms_F77; do
+
+ case $var in
+ old_archive_cmds_F77 | \
+ old_archive_from_new_cmds_F77 | \
+ archive_cmds_F77 | \
+ archive_expsym_cmds_F77 | \
+ module_cmds_F77 | \
+ module_expsym_cmds_F77 | \
+ old_archive_from_expsyms_cmds_F77 | \
+ export_symbols_cmds_F77 | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_F77
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_F77
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_F77
+
+gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\`
+gcc_ver=\`gcc -dumpversion\`
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_F77
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_F77
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_F77
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_F77
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_F77
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_F77
+archive_expsym_cmds=$lt_archive_expsym_cmds_F77
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_F77
+module_expsym_cmds=$lt_module_expsym_cmds_F77
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=\`echo $lt_predep_objects_F77 | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=\`echo $lt_postdep_objects_F77 | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_F77
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_F77
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_F77 | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_F77
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_F77
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_F77
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_F77
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_F77
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_F77
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_F77
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_F77
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_F77"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_F77
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_F77
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_F77
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_F77
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+ else
+ tagname=""
+ fi
+ ;;
+
+ GCJ)
+ if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+
+
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+objext_GCJ=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+compiler_GCJ=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+archive_cmds_need_lc_GCJ=no
+
+old_archive_cmds_GCJ=$old_archive_cmds
+
+
+lt_prog_compiler_no_builtin_flag_GCJ=
+
+if test "$GCC" = yes; then
+ lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin'
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_rtti_exceptions=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="-fno-rtti -fno-exceptions"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:17109: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:17113: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_rtti_exceptions=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+ lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions"
+else
+ :
+fi
+
+fi
+
+lt_prog_compiler_wl_GCJ=
+lt_prog_compiler_pic_GCJ=
+lt_prog_compiler_static_GCJ=
+
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_static_GCJ='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_GCJ='-fno-common'
+ ;;
+
+ interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared_GCJ=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_GCJ=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_GCJ='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ lt_prog_compiler_pic_GCJ='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ else
+ lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case $cc_basename in
+ xlc*)
+ lt_prog_compiler_pic_GCJ='-qnocommon'
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_GCJ='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static_GCJ='-non_shared'
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ linux*)
+ case $cc_basename in
+ icc* | ecc*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-fpic'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static_GCJ='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static_GCJ='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ lt_prog_compiler_wl_GCJ='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl_GCJ='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl_GCJ='-Qoption ld '
+ lt_prog_compiler_pic_GCJ='-PIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic_GCJ='-Kconform_pic'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_can_build_shared_GCJ=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic_GCJ='-pic'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared_GCJ=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_GCJ"; then
+
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6
+if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works_GCJ=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_GCJ"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:17377: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:17381: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_pic_works_GCJ=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6
+
+if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then
+ case $lt_prog_compiler_pic_GCJ in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;;
+ esac
+else
+ lt_prog_compiler_pic_GCJ=
+ lt_prog_compiler_can_build_shared_GCJ=no
+fi
+
+fi
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_GCJ=
+ ;;
+ *)
+ lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ"
+ ;;
+esac
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\"
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
+if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works_GCJ=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_prog_compiler_static_works_GCJ=yes
+ fi
+ else
+ lt_prog_compiler_static_works_GCJ=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6
+
+if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then
+ :
+else
+ lt_prog_compiler_static_GCJ=
+fi
+
+
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
+if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o_GCJ=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:17481: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:17485: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_GCJ=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
+
+ runpath_var=
+ allow_undefined_flag_GCJ=
+ enable_shared_with_static_runtimes_GCJ=no
+ archive_cmds_GCJ=
+ archive_expsym_cmds_GCJ=
+ old_archive_From_new_cmds_GCJ=
+ old_archive_from_expsyms_cmds_GCJ=
+ export_dynamic_flag_spec_GCJ=
+ whole_archive_flag_spec_GCJ=
+ thread_safe_flag_spec_GCJ=
+ hardcode_libdir_flag_spec_GCJ=
+ hardcode_libdir_flag_spec_ld_GCJ=
+ hardcode_libdir_separator_GCJ=
+ hardcode_direct_GCJ=no
+ hardcode_minus_L_GCJ=no
+ hardcode_shlibpath_var_GCJ=unsupported
+ link_all_deplibs_GCJ=unknown
+ hardcode_automatic_GCJ=no
+ module_cmds_GCJ=
+ module_expsym_cmds_GCJ=
+ always_export_symbols_GCJ=no
+ export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms_GCJ=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+ # Just being paranoid about ensuring that cc_basename is set.
+ for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs_GCJ=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_GCJ='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_GCJ=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs_GCJ=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_minus_L_GCJ=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ ld_shlibs_GCJ=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_GCJ=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ allow_undefined_flag_GCJ=unsupported
+ always_export_symbols_GCJ=no
+ enable_shared_with_static_runtimes_GCJ=yes
+ export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ interix3*)
+ hardcode_direct_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_addflag=
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ esac
+ archive_cmds_GCJ='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test $supports_anon_versioning = yes; then
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ $echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs_GCJ=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs_GCJ=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs_GCJ" = no; then
+ runpath_var=
+ hardcode_libdir_flag_spec_GCJ=
+ export_dynamic_flag_spec_GCJ=
+ whole_archive_flag_spec_GCJ=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag_GCJ=unsupported
+ always_export_symbols_GCJ=yes
+ archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L_GCJ=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct_GCJ=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_GCJ=''
+ hardcode_direct_GCJ=yes
+ hardcode_libdir_separator_GCJ=':'
+ link_all_deplibs_GCJ=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct_GCJ=yes
+ else
+ # We have old collect2
+ hardcode_direct_GCJ=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_GCJ=yes
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_libdir_separator_GCJ=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols_GCJ=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_GCJ='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_GCJ="-z nodefs"
+ archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_GCJ=' ${wl}-bernotok'
+ allow_undefined_flag_GCJ=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_GCJ='$convenience'
+ archive_cmds_need_lc_GCJ=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_minus_L_GCJ=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs_GCJ=no
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec_GCJ=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec_GCJ=' '
+ allow_undefined_flag_GCJ=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_From_new_cmds_GCJ='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes_GCJ=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc_GCJ=no
+ hardcode_direct_GCJ=no
+ hardcode_automatic_GCJ=yes
+ hardcode_shlibpath_var_GCJ=unsupported
+ whole_archive_flag_spec_GCJ=''
+ link_all_deplibs_GCJ=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case $cc_basename in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
+ archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs_GCJ=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs_GCJ=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes
+ hardcode_minus_L_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu | dragonfly*)
+ archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ hardcode_direct_GCJ=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+
+ hardcode_direct_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_GCJ=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_libdir_flag_spec_ld_GCJ='+b $libdir'
+ hardcode_direct_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+ *)
+ hardcode_direct_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_GCJ=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir'
+ fi
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ link_all_deplibs_GCJ=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ newsos6)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ openbsd*)
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ ;;
+ *)
+ archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_minus_L_GCJ=yes
+ allow_undefined_flag_GCJ=unsupported
+ archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag_GCJ=' -expect_unresolved \*'
+ archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag_GCJ=' -expect_unresolved \*'
+ archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec_GCJ='-rpath $libdir'
+ fi
+ hardcode_libdir_separator_GCJ=:
+ ;;
+
+ solaris*)
+ no_undefined_flag_GCJ=' -z text'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ wlarc=''
+ archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_shlibpath_var_GCJ=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine linker options so we
+ # cannot just pass the convience library names through
+ # without $wl, iff we do not link with $LD.
+ # Luckily, gcc supports the same syntax we need for Sun Studio.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ case $wlarc in
+ '')
+ whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;;
+ *)
+ whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;;
+ esac ;;
+ esac
+ link_all_deplibs_GCJ=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_minus_L_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds_GCJ='$CC -r -o $output$reload_objs'
+ hardcode_direct_GCJ=no
+ ;;
+ motorola)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_GCJ=no
+ export_dynamic_flag_spec_GCJ='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_GCJ=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs_GCJ=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*)
+ no_undefined_flag_GCJ='${wl}-z,text'
+ archive_cmds_need_lc_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag_GCJ='${wl}-z,text'
+ allow_undefined_flag_GCJ='${wl}-z,nodefs'
+ archive_cmds_need_lc_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator_GCJ=':'
+ link_all_deplibs_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ *)
+ ld_shlibs_GCJ=no
+ ;;
+ esac
+ fi
+
+echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5
+echo "${ECHO_T}$ld_shlibs_GCJ" >&6
+test "$ld_shlibs_GCJ" = no && can_build_shared=no
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_GCJ" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_GCJ=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_GCJ in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_GCJ
+ pic_flag=$lt_prog_compiler_pic_GCJ
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ
+ allow_undefined_flag_GCJ=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc_GCJ=no
+ else
+ archive_cmds_need_lc_GCJ=yes
+ fi
+ allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ freebsd*) # from 4.6 on
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix3*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # find out which ABI we are using
+ libsuff=
+ case "$host_cpu" in
+ x86_64*|s390x*|powerpc64*)
+ echo '#line 18950 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *64-bit*)
+ libsuff=64
+ sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+ esac
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ shlibpath_overrides_runpath=no
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ shlibpath_overrides_runpath=yes
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
+hardcode_action_GCJ=
+if test -n "$hardcode_libdir_flag_spec_GCJ" || \
+ test -n "$runpath_var_GCJ" || \
+ test "X$hardcode_automatic_GCJ" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct_GCJ" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no &&
+ test "$hardcode_minus_L_GCJ" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_GCJ=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_GCJ=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_GCJ=unsupported
+fi
+echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5
+echo "${ECHO_T}$hardcode_action_GCJ" >&6
+
+if test "$hardcode_action_GCJ" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_GCJ \
+ CC_GCJ \
+ LD_GCJ \
+ lt_prog_compiler_wl_GCJ \
+ lt_prog_compiler_pic_GCJ \
+ lt_prog_compiler_static_GCJ \
+ lt_prog_compiler_no_builtin_flag_GCJ \
+ export_dynamic_flag_spec_GCJ \
+ thread_safe_flag_spec_GCJ \
+ whole_archive_flag_spec_GCJ \
+ enable_shared_with_static_runtimes_GCJ \
+ old_archive_cmds_GCJ \
+ old_archive_from_new_cmds_GCJ \
+ predep_objects_GCJ \
+ postdep_objects_GCJ \
+ predeps_GCJ \
+ postdeps_GCJ \
+ compiler_lib_search_path_GCJ \
+ archive_cmds_GCJ \
+ archive_expsym_cmds_GCJ \
+ postinstall_cmds_GCJ \
+ postuninstall_cmds_GCJ \
+ old_archive_from_expsyms_cmds_GCJ \
+ allow_undefined_flag_GCJ \
+ no_undefined_flag_GCJ \
+ export_symbols_cmds_GCJ \
+ hardcode_libdir_flag_spec_GCJ \
+ hardcode_libdir_flag_spec_ld_GCJ \
+ hardcode_libdir_separator_GCJ \
+ hardcode_automatic_GCJ \
+ module_cmds_GCJ \
+ module_expsym_cmds_GCJ \
+ lt_cv_prog_compiler_c_o_GCJ \
+ exclude_expsyms_GCJ \
+ include_expsyms_GCJ; do
+
+ case $var in
+ old_archive_cmds_GCJ | \
+ old_archive_from_new_cmds_GCJ | \
+ archive_cmds_GCJ | \
+ archive_expsym_cmds_GCJ | \
+ module_cmds_GCJ | \
+ module_expsym_cmds_GCJ | \
+ old_archive_from_expsyms_cmds_GCJ | \
+ export_symbols_cmds_GCJ | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_GCJ
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_GCJ
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_GCJ
+
+gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\`
+gcc_ver=\`gcc -dumpversion\`
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_GCJ
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_GCJ
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_GCJ
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_GCJ
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_GCJ
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_GCJ
+archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_GCJ
+module_expsym_cmds=$lt_module_expsym_cmds_GCJ
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=\`echo $lt_predep_objects_GCJ | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=\`echo $lt_postdep_objects_GCJ | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_GCJ
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_GCJ
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_GCJ | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_GCJ
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_GCJ
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_GCJ
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_GCJ
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_GCJ
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_GCJ
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_GCJ
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_GCJ"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_GCJ
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_GCJ
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_GCJ
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_GCJ
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+ else
+ tagname=""
+ fi
+ ;;
+
+ RC)
+
+
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+objext_RC=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$rm conftest*
+
+ac_outfile=conftest.$ac_objext
+printf "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$rm conftest*
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+compiler_RC=$CC
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+lt_cv_prog_compiler_c_o_RC=yes
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_RC \
+ CC_RC \
+ LD_RC \
+ lt_prog_compiler_wl_RC \
+ lt_prog_compiler_pic_RC \
+ lt_prog_compiler_static_RC \
+ lt_prog_compiler_no_builtin_flag_RC \
+ export_dynamic_flag_spec_RC \
+ thread_safe_flag_spec_RC \
+ whole_archive_flag_spec_RC \
+ enable_shared_with_static_runtimes_RC \
+ old_archive_cmds_RC \
+ old_archive_from_new_cmds_RC \
+ predep_objects_RC \
+ postdep_objects_RC \
+ predeps_RC \
+ postdeps_RC \
+ compiler_lib_search_path_RC \
+ archive_cmds_RC \
+ archive_expsym_cmds_RC \
+ postinstall_cmds_RC \
+ postuninstall_cmds_RC \
+ old_archive_from_expsyms_cmds_RC \
+ allow_undefined_flag_RC \
+ no_undefined_flag_RC \
+ export_symbols_cmds_RC \
+ hardcode_libdir_flag_spec_RC \
+ hardcode_libdir_flag_spec_ld_RC \
+ hardcode_libdir_separator_RC \
+ hardcode_automatic_RC \
+ module_cmds_RC \
+ module_expsym_cmds_RC \
+ lt_cv_prog_compiler_c_o_RC \
+ exclude_expsyms_RC \
+ include_expsyms_RC; do
+
+ case $var in
+ old_archive_cmds_RC | \
+ old_archive_from_new_cmds_RC | \
+ archive_cmds_RC | \
+ archive_expsym_cmds_RC | \
+ module_cmds_RC | \
+ module_expsym_cmds_RC | \
+ old_archive_from_expsyms_cmds_RC | \
+ export_symbols_cmds_RC | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_RC
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_LTCFLAGS
+
+# A language-specific compiler.
+CC=$lt_compiler_RC
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_RC
+
+gcc_dir=\`gcc -print-file-name=. | $SED 's,/\.$,,'\`
+gcc_ver=\`gcc -dumpversion\`
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_RC
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_RC
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_RC
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_RC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_RC
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_RC
+archive_expsym_cmds=$lt_archive_expsym_cmds_RC
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_RC
+module_expsym_cmds=$lt_module_expsym_cmds_RC
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=\`echo $lt_predep_objects_RC | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=\`echo $lt_postdep_objects_RC | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_RC
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_RC
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=\`echo $lt_compiler_lib_search_path_RC | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_RC
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_RC
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_RC
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_RC
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_RC
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_RC
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_RC
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_RC
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=\`echo $lt_sys_lib_search_path_spec | \$SED -e "s@\${gcc_dir}@\\\${gcc_dir}@g;s@\${gcc_ver}@\\\${gcc_ver}@g"\`
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_RC"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_RC
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_RC
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_RC
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_RC
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+ ;;
+
+ *)
+ { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5
+echo "$as_me: error: Unsupported tag name: $tagname" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+
+ # Append the new tag name to the list of available tags.
+ if test -n "$tagname" ; then
+ available_tags="$available_tags $tagname"
+ fi
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ # Now substitute the updated list of available tags.
+ if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+ mv "${ofile}T" "$ofile"
+ chmod +x "$ofile"
+ else
+ rm -f "${ofile}T"
+ { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5
+echo "$as_me: error: unable to update list of available tagged configurations." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+fi
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Prevent multiple expansion
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
+if test "${ac_cv_c_const+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this. */
+ typedef int charset[2];
+ const charset x;
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *ccp;
+ char **p;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ ccp = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++ccp;
+ p = (char**) ccp;
+ ccp = (char const *const *) p;
+ { /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ }
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_const=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_const=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/socket.h>
+int
+main ()
+{
+socklen_t len = 42; return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_socklen_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_socklen_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+if test $ac_cv_type_socklen_t != yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define socklen_t int
+_ACEOF
+
+else
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SOCKLEN_T 1
+_ACEOF
+
+fi
+
+tmpspec=/tmp/iuspec.tmp$$
+archm=`uname -m`
+sysname=`uname -s`
+LIB_DIR="/usr/lib"
+isredhat=0
+init_scripts="scripts/ipmi_port.sh scripts/ipmiutil_evt scripts/ipmiutil_asy scripts/ipmiutil_wdt"
+projdir=`pwd`
+SUBDIR_S="doc scripts lib util"
+os=Linux
+
+# ltmain.sh, config.sub, et al should have been created, but check to be sure.
+beforeprog="./beforeconf.sh"
+progs="config.sub ltmain.sh"
+for p in $progs
+do
+ echo -e "checking for $p... \c"
+ if test -f "$p"; then
+ echo "yes"
+ else
+ echo "no"
+ echo "Run $beforeprog to configure the build environment."
+ exit 1
+ fi
+done
+
+#[ if test -n "$GCC"; then
+# CFLAGS="$CFLAGS -Wall -D_REENTRANT"
+# fi]
+
+drv_landesk=0
+# Check whether --enable-landesk or --disable-landesk was given.
+if test "${enable_landesk+set}" = set; then
+ enableval="$enable_landesk"
+ if test "x$enableval" = "xyes"; then
+ drv_landesk=1
+ LANDESK_CFLAGS="-DLINK_LANDESK"
+ LANDESK_LDADD="-lipmiapi -L../lib"
+
+
+ fi
+
+fi;
+
+# Check whether --enable-lanplus or --disable-lanplus was given.
+if test "${enable_lanplus+set}" = set; then
+ enableval="$enable_lanplus"
+
+fi;
+if test "x$enable_lanplus" = "xno"; then
+ drv_lanplus=""
+ LANPLUS_CFLAGS=""
+ LANPLUS_LDADD=""
+ LANPLUS_LIB=""
+ LANPLUS_CRYPTO=""
+ LANPLUS_SAM="no"
+ LD_SAMX=""
+else
+ drv_lanplus="lanplus"
+ LANPLUS_CFLAGS="-DHAVE_LANPLUS"
+ # LANPLUS_CFLAGS="-DHAVE_LANPLUS -I${projdir}/lib/lanplus/inc"
+ # LANPLUS_LDADD="-L../lib -lintf_lanplus -L/usr/local/lib -lcrypto"
+ LANPLUS_LDADD="-L../lib -lipmi_lanplus -L/usr/local/lib -lcrypto"
+ LANPLUS_LIB="../lib/libipmi_lanplus.a"
+ LANPLUS_CRYPTO="-lcrypto"
+ LANPLUS_SAM="yes"
+ LD_SAMX="../lib/libipmi_lanplus.a -lcrypto"
+fi
+
+#AC_ARG_ENABLE([liblanplus],
+# [ --enable-liblanplus build libipmiutil.a with lanplus [[default=disabled]]],)
+#if test "x$enable_liblanplus" = "xyes"; then
+# LANPLUS_SAM="yes"
+# LD_SAMX= "../lib/libipmi_lanplus.a -lcrypto"
+#else
+# LANPLUS_SAM="no"
+# LD_SAMX=""
+#fi
+
+# strings /lib/libssl.so* |grep EVP_sha256
+# Check whether --enable-sha256 or --disable-sha256 was given.
+if test "${enable_sha256+set}" = set; then
+ enableval="$enable_sha256"
+ if test "x$enableval" = "xyes"; then
+ LANPLUS_CFLAGS="$LANPLUS_CFLAGS -DHAVE_SHA256"
+ fi
+
+fi;
+
+CROSS_LFLAGS=""
+CROSS_CFLAGS=""
+
+# Check whether --enable-standalone or --disable-standalone was given.
+if test "${enable_standalone+set}" = set; then
+ enableval="$enable_standalone"
+ if test "x$enableval" = "xyes"; then
+ GPL_CFLAGS=""
+ LANPLUS_CFLAGS=""
+ LANPLUS_LDADD=""
+ LANPLUS_LIB=""
+ LANPLUS_CRYPTO=""
+ LANPLUS_SAM="no"
+ LD_SAMX=""
+ CFLAGS="-O2"
+ SUBDIR_S="doc scripts util"
+ if test "x$cross_compiling" = "xyes"; then
+ # cross-compiling, so link with -static (e.g. Android ARM)
+ CROSS_LFLAGS="-static"
+ CROSS_CFLAGS="-DCROSS_COMPILE"
+ sed -i -e 's/^# ipmiutil: $(METASOURCE:.c=.o)/ipmiutil:\t$(METASOURCE:.c=.o)\n\t$(CC) $(CFLAGS) $(LDFLAGS) -o ipmiutil $(METASOURCE:.c=.o) $(LDADD)/' util/Makefile.am
+ fi
+ fi
+
+fi;
+
+# Check whether --enable-gpl or --disable-gpl was given.
+if test "${enable_gpl+set}" = set; then
+ enableval="$enable_gpl"
+ if test "x$enableval" = "xyes"; then
+ GPL_CFLAGS="-DALLOW_GPL"
+ else
+ GPL_CFLAGS=""
+ fi
+
+fi;
+
+# Check whether --enable-systemd or --disable-systemd was given.
+if test "${enable_systemd+set}" = set; then
+ enableval="$enable_systemd"
+
+fi;
+if test "x$enable_systemd" = "xyes"; then
+ GPL_CFLAGS="$GPL_CFLAGS -DENABLE_SYSTEMD"
+ # if systemd enabled, install service scripts in unitdir
+ SYSTEMD_DIR=`rpm --eval "%{_unitdir}"`
+else
+ # otherwise install the systemd service scripts in the data dir
+ if test "x$sysname" = "xDarwin" ; then
+ # MacOS 'which' command returns 0 always
+ SYSTEMD_DIR=/usr/share/ipmiutil
+ else
+ which rpm >/dev/null 2>&1
+ if test $? -eq 0 ; then
+ datad=`rpm --eval "%{_datadir}"`
+ SYSTEMD_DIR=${datad}/ipmiutil
+ else
+ SYSTEMD_DIR=/usr/share/ipmiutil
+ fi
+ fi
+fi
+
+case "$archm" in
+ ia64)
+ IA64_CFLAGS="-D__IA64__"
+ LIB_DIR="/usr/lib64"
+ ;;
+ ppc64)
+ IA64_CFLAGS="-DSTUB_IO"
+ LIB_DIR="/usr/lib64"
+ ;;
+ x86_64)
+ IA64_CFLAGS=""
+ LIB_DIR="/usr/lib64"
+ ;;
+ i386)
+ IA64_CFLAGS=""
+ ;;
+ i586)
+ IA64_CFLAGS=""
+ ;;
+ i686)
+ IA64_CFLAGS=""
+ ;;
+ sun4u)
+ IA64_CFLAGS="-D__SPARC__"
+ ;;
+ *)
+ IA64_CFLAGS="-DSTUB_IO"
+ ;;
+esac
+
+echo $libdir |grep exec_prefix >/dev/null 2>&1
+if test $? -ne 0; then
+ LIB_DIR="$libdir"
+ echo "libdir set to $libdir"
+fi
+
+PKG_DIR=/usr/src/packages
+INS_LIB=""
+SHR_LINK="libipmiutil.so"
+init0=
+if test "x$sysname" = "xSunOS"; then
+ echo "Detected Solaris"
+ os=solaris
+ archp=`uname -p`
+ if test -d "/usr/sfw/lib"; then
+ sfwdir=/usr/sfw
+ else
+ sfwdir=/usr/local
+ fi
+ OS_CFLAGS="-DSOLARIS -I${sfwdir}/include"
+ OS_LFLAGS="-L${sfwdir}/lib -lxnet -lsocket -lnsl -lresolv"
+ OS_DRIVERS="ipmibmc.c ipmilipmi.c"
+ drivers="bmc lipmi"
+ INS_LIB="# "
+ SHR_LINK=""
+else
+ if test "x$sysname" = "xLinux"; then
+ MD2_CFLAGS=""
+ OS_LFLAGS=""
+ OS_DRIVERS="imbapi.c ipmimv.c ipmild.c ipmidir.c"
+ if test $drv_landesk -eq 1; then
+ drivers="open imb landesk direct"
+ else
+ drivers="open imb direct"
+ fi
+ os=linux
+ tmpc=/tmp/tmp.c
+ tmpo=/tmp/tmp.o
+ echo $ECHO_N "checking compile warning flags ... $ECHO_C"
+ cfwarn="-Wno-pointer-sign -Wno-sign-conversion -Wunused-result -Wgnu-designator"
+ echo "int main() { return(1); }" >$tmpc
+ gcc -o $tmpo -c $cfwarn $tmpc >/dev/null 2>&1
+ if test $? -ne 0 ; then
+ cfwarn=
+ echo "skip"
+ else
+ echo "ok, suppress excess warnings"
+ fi
+ rm -f $tmpc $tmpo >/dev/null 2>&1
+ echo $ECHO_N "checking compile fortify flags ... $ECHO_C"
+ cfhard="-fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2"
+ echo "int main() { return(1); }" >$tmpc
+ gcc -o $tmpo -c $cfhard $tmpc >/dev/null 2>&1
+ if test $? -ne 0 ; then
+ cfhard=
+ echo "skip"
+ else
+ echo "ok, add"
+ fi
+ rm -f $tmpc $tmpo >/dev/null 2>&1
+ if test -f "/etc/debian_version"; then
+ echo "Detected Debian Linux"
+ os=debian
+ PKG_DIR=..
+ INS_LIB="# "
+ # use dpkg-buildpackage instead of rpmbuild
+ else
+ which rpm >/dev/null 2>&1
+ if test $? -eq 0; then
+ pkgtop=`rpm --eval "%{_topdir}"`
+ PKG_DIR=$pkgtop
+ fi
+ fi
+ if test -f "/etc/redhat-release"; then
+ echo "Detected Red Hat Linux"
+ os=redhat
+ isredhat=1
+ fi
+ if test -f "/etc/SuSE-release"; then
+ echo "Detected SuSE Linux"
+ os=suse
+ sed -e 's/# POST_INSTALL/if [ ! -f \/etc\/snmp\/snmpd.conf ]; then\n if [ -f \/etc\/ucdsnmpd.conf ]; then\n mkdir -p \/etc\/snmp; ln -s \/etc\/ucdsnmpd.conf \/etc\/snmp\/snmpd.conf\n fi\nif [ -f \/etc\/snmpd.conf ]; then\nmkdir -p \/etc\/snmp; ln -s \/etc\/snmpd.conf \/etc\/snmp\/snmpd.conf\nfi\nfi\n#/' -e 's/make install DEST/make install-strip DEST/' doc/ipmiutil.spec >$tmpspec
+ cp -f $tmpspec doc/ipmiutil.spec
+ fi
+ if test -f "/etc/mvl-release"; then
+ echo "Detected MontaVista Linux"
+ os=montavista
+ init0=/etc/init.d
+ sed -e 's/openssl-devel/openssl-dev\n%ifarch x86_pentium3 x86_pentium4\nAutoReqProv: No\n%endif/' -e 's/%{_mandir}/\/usr\/share\/man/' -e 's/%{_initrddir}/\/etc\/init.d/' -e 's/%{_sysconfdir}/\/etc/' -e 's/# POST_INSTALL/newcrypto=%{_libdir}\/libcrypto.so.4\nif [ ! -f $newcrypto ]; then\n cp -f %{_libdir}\/libcrypto.so.0 $newcrypto\nfi\n#/' -e 's/make install DEST/make install-strip DEST/' doc/ipmiutil.spec >$tmpspec
+ cp -f $tmpspec doc/ipmiutil.spec
+ fi
+ if test -f "/etc/wrs-release" -o -d "$WIND_HOME"; then
+ echo "Detected WindRiver Linux"
+ os=windriver
+ echo "Be sure to set up the WR build environment first"
+ # WR requires extra steps in the spec file.
+ grep "%configure_target" doc/ipmiutil.spec >/dev/null 2>&1
+ if test $? -ne 0; then
+ # WR changes have not been patched in, so make them.
+ sed -e 's/Release: 1%{?dist}/Release: 1_WR/' -e 's/%build/%build\n%configure_target\n%define _config_cache config.cache\n/' -e 's/^make$/make CC="$CC" TARGET_CFLAGS="$CFLAGS" TARGET_LDADD="-L%{_host_cross_lib_dir}" LDFLAGS="$LDFLAGS" CXX="$CXX" CXXFLAGS="$CXXFLAGS" LD="$LD" AS="$AS" AR="$AR" CPP="$CPP" NM="$NM" OBJCOPY="$OPBJCOPY" OBJDUMP="$OPBJDUMP" RANLIB="$RANLIB" STRIP="$STRIP"/' -e 's/%install/%install\n%configure_target\n/' doc/ipmiutil.spec >$tmpspec
+ cp -f $tmpspec doc/ipmiutil.spec
+ fi
+ # WRL libcrypto does not have MD2
+ MD2_CFLAGS="-DSKIP_MD2"
+ init0=/etc/rc.d/init.d
+ fi
+ if test $isredhat -eq 0 ; then
+ # set default start/stop for init scripts
+ sed -i 's/# Default-Start:/# Default-Start: 3 4 5/' $init_scripts
+ sed -i 's/# Default-Stop:/# Default-Stop: 0 1 2 6/' $init_scripts
+ fi
+ if test -f "$LIB_DIR/libcrypto.so"; then
+ strings $LIB_DIR/libcrypto.so | grep EVP_md2 >/dev/null 2>&1
+ if test $? -ne 0; then
+ echo "No MD2 detected in openssl libcrypto.so"
+ MD2_CFLAGS="-DSKIP_MD2"
+ fi
+ else
+ echo "No openssl $LIB_DIR/libcrypto.so detected"
+ MD2_CFLAGS="-DSKIP_MD2"
+ fi
+ OS_CFLAGS="-DLINUX $MD2_CFLAGS -fPIC $cfwarn $cfhard"
+ else
+ # usually "x$sysname" = "xFreeBSD", but allow NetBSD
+ echo $sysname | grep BSD >/dev/null 2>&1
+ if test $? -eq 0; then
+ os=bsd
+ OS_CFLAGS="-DBSD"
+ OS_LFLAGS=""
+ OS_DRIVERS="ipmimv.c ipmidir.c"
+ drivers="open direct"
+ else
+ uname -a | grep -i HP-UX >/dev/null 2>&1
+ hpux=$?
+ if test $hpux -eq 0; then
+ echo "Detected HP-UX"
+ os=hpux
+ MD2_CFLAGS="-DSKIP_MD2"
+ OS_CFLAGS="-DHPUX"
+ OS_LFLAGS=""
+ OS_DRIVERS="ipmimv.c"
+ drivers="open"
+ SHR_LINK=""
+ elif test "x$sysname" = "xDarwin" ; then
+ echo "Detected MacOSX"
+ os=macos
+ MD2_CFLAGS="-DSKIP_MD2"
+ OS_CFLAGS="-DMACOS"
+ OS_LFLAGS=""
+ OS_DRIVERS="ipmimv.c ipmidir.c"
+ drivers="open direct"
+ SHR_LINK=""
+ # optionally check for AppleBMC.kext here?
+ else
+ # not Solaris, Linux, BSD, or HP-UX = error
+ echo "OS $sysname not yet supported"
+ exit 1
+ fi
+ fi
+ fi
+fi
+
+if test "x$init0" = "x" ; then
+ if test "x$os" != "xmacos" ; then
+ which rpmbuild >/dev/null 2>&1
+ if test $? -eq 0 ; then
+ init1=`rpmbuild --showrc |grep " _initrddir" | cut -d'}' -f2`
+ if test "x$init1" != "x" ; then
+ init0=/etc/${init1}
+ fi
+ fi
+ fi
+fi
+if test "x$init0" = "x" ; then
+ if test -d ${etcdir}/rc.d/init.d ; then
+ init0=/etc/rc.d/init.d;
+ else
+ init0=/etc/init.d;
+ fi
+fi
+INIT_DIR=${init0}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ac_config_files="$ac_config_files Makefile util/Makefile lib/lanplus/Makefile doc/Makefile scripts/Makefile"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+ (set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+} |
+ sed '
+ t clear
+ : clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+ if test -w $cache_file; then
+ test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+ cat confcache >$cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_i=`echo "$ac_i" |
+ sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+ # 2. Add them.
+ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling. Logging --version etc. is OK.
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+ echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+ echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+ echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+ echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "x$1" : 'x\([^=]*\)='`
+ ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ -*)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ *) # This is not an option, so the user has probably given explicit
+ # arguments.
+ ac_option=$1
+ ac_need_defaults=false;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --vers* | -V )
+ echo "$ac_cs_version"; exit 0 ;;
+ --he | --h)
+ # Conflict between --help and --header
+ { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1" ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS section.
+#
+
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+ case "$ac_config_target" in
+ # Handling of arguments.
+ "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "util/Makefile" ) CONFIG_FILES="$CONFIG_FILES util/Makefile" ;;
+ "lib/lanplus/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/lanplus/Makefile" ;;
+ "doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
+ "scripts/Makefile" ) CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;;
+ "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./confstat$$-$RANDOM
+ (umask 077 && mkdir $tmp)
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+ # Protect against being on the right side of a sed subst in config.status.
+ sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+ s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@CYGPATH_W@,$CYGPATH_W,;t t
+s,@PACKAGE@,$PACKAGE,;t t
+s,@VERSION@,$VERSION,;t t
+s,@ACLOCAL@,$ACLOCAL,;t t
+s,@AUTOCONF@,$AUTOCONF,;t t
+s,@AUTOMAKE@,$AUTOMAKE,;t t
+s,@AUTOHEADER@,$AUTOHEADER,;t t
+s,@MAKEINFO@,$MAKEINFO,;t t
+s,@install_sh@,$install_sh,;t t
+s,@STRIP@,$STRIP,;t t
+s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t
+s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t
+s,@mkdir_p@,$mkdir_p,;t t
+s,@AWK@,$AWK,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@am__leading_dot@,$am__leading_dot,;t t
+s,@AMTAR@,$AMTAR,;t t
+s,@am__tar@,$am__tar,;t t
+s,@am__untar@,$am__untar,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@DEPDIR@,$DEPDIR,;t t
+s,@am__include@,$am__include,;t t
+s,@am__quote@,$am__quote,;t t
+s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t
+s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t
+s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t
+s,@CCDEPMODE@,$CCDEPMODE,;t t
+s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t
+s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t
+s,@LN_S@,$LN_S,;t t
+s,@SED@,$SED,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@build@,$build,;t t
+s,@build_cpu@,$build_cpu,;t t
+s,@build_vendor@,$build_vendor,;t t
+s,@build_os@,$build_os,;t t
+s,@host@,$host,;t t
+s,@host_cpu@,$host_cpu,;t t
+s,@host_vendor@,$host_vendor,;t t
+s,@host_os@,$host_os,;t t
+s,@ECHO@,$ECHO,;t t
+s,@AR@,$AR,;t t
+s,@ac_ct_AR@,$ac_ct_AR,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@CXX@,$CXX,;t t
+s,@CXXFLAGS@,$CXXFLAGS,;t t
+s,@ac_ct_CXX@,$ac_ct_CXX,;t t
+s,@CXXDEPMODE@,$CXXDEPMODE,;t t
+s,@am__fastdepCXX_TRUE@,$am__fastdepCXX_TRUE,;t t
+s,@am__fastdepCXX_FALSE@,$am__fastdepCXX_FALSE,;t t
+s,@CXXCPP@,$CXXCPP,;t t
+s,@F77@,$F77,;t t
+s,@FFLAGS@,$FFLAGS,;t t
+s,@ac_ct_F77@,$ac_ct_F77,;t t
+s,@LIBTOOL@,$LIBTOOL,;t t
+s,@LANDESK_CFLAGS@,$LANDESK_CFLAGS,;t t
+s,@LANDESK_LDADD@,$LANDESK_LDADD,;t t
+s,@IA64_CFLAGS@,$IA64_CFLAGS,;t t
+s,@LANPLUS_CFLAGS@,$LANPLUS_CFLAGS,;t t
+s,@LANPLUS_LDADD@,$LANPLUS_LDADD,;t t
+s,@LANPLUS_LIB@,$LANPLUS_LIB,;t t
+s,@LANPLUS_CRYPTO@,$LANPLUS_CRYPTO,;t t
+s,@LANPLUS_SAM@,$LANPLUS_SAM,;t t
+s,@LD_SAMX@,$LD_SAMX,;t t
+s,@GPL_CFLAGS@,$GPL_CFLAGS,;t t
+s,@OS_CFLAGS@,$OS_CFLAGS,;t t
+s,@OS_LFLAGS@,$OS_LFLAGS,;t t
+s,@OS_DRIVERS@,$OS_DRIVERS,;t t
+s,@PKG_DIR@,$PKG_DIR,;t t
+s,@INIT_DIR@,$INIT_DIR,;t t
+s,@LIB_DIR@,$LIB_DIR,;t t
+s,@INS_LIB@,$INS_LIB,;t t
+s,@SUBDIR_S@,$SUBDIR_S,;t t
+s,@CROSS_CFLAGS@,$CROSS_CFLAGS,;t t
+s,@CROSS_LFLAGS@,$CROSS_LFLAGS,;t t
+s,@SYSTEMD_DIR@,$SYSTEMD_DIR,;t t
+s,@SHR_LINK@,$SHR_LINK,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+ cat >>$CONFIG_STATUS <<\_ACEOF
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+ ac_max_sed_lines=48
+ ac_sed_frag=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_lines # Line after last line for current file.
+ ac_more_lines=:
+ ac_sed_cmds=
+ while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ else
+ sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ fi
+ if test ! -s $tmp/subs.frag; then
+ ac_more_lines=false
+ else
+ # The purpose of the label and of the branching condition is to
+ # speed up the sed processing (if there are no `@' at all, there
+ # is no need to browse any of the substitutions).
+ # These are the two extra sed commands mentioned above.
+ (echo ':t
+ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+ fi
+ ac_sed_frag=`expr $ac_sed_frag + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_lines`
+ fi
+ done
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+ fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+ esac
+
+ if test x"$ac_file" != x-; then
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ rm -f "$ac_file"
+ fi
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ configure_input=
+ else
+ configure_input="$ac_file. "
+ fi
+ configure_input=$configure_input"Generated from `echo $ac_file_in |
+ sed 's,.*/,,'` by configure."
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+ rm -f $tmp/stdin
+ if test x"$ac_file" != x-; then
+ mv $tmp/out $ac_file
+ else
+ cat $tmp/out
+ rm -f $tmp/out
+ fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='[ ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ # Do quote $f, to prevent DOS paths from being IFS'd.
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+ # Remove the trailing spaces.
+ sed 's/[ ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h. The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status. Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless. Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo ' :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+ # Write a limited-size here document to $tmp/defines.sed.
+ echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#define' lines.
+ echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/defines.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo ' fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+ # Write a limited-size here document to $tmp/undefs.sed.
+ echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#undef'
+ echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+ rm -f conftest.undefs
+ mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ echo "/* Generated by configure. */" >$tmp/config.h
+ else
+ echo "/* $ac_file. Generated by configure. */" >$tmp/config.h
+ fi
+ cat $tmp/in >>$tmp/config.h
+ rm -f $tmp/in
+ if test x"$ac_file" != x-; then
+ if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ rm -f $ac_file
+ mv $tmp/config.h $ac_file
+ fi
+ else
+ cat $tmp/config.h
+ rm -f $tmp/config.h
+ fi
+# Compute $ac_file's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $ac_file | $ac_file:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null ||
+$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X$ac_file : 'X\(//\)[^/]' \| \
+ X$ac_file : 'X\(//\)$' \| \
+ X$ac_file : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X$ac_file |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`/stamp-h$_am_stamp_count
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_COMMANDS section.
+#
+for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
+ ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+ ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
+$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_dest" : 'X\(//\)[^/]' \| \
+ X"$ac_dest" : 'X\(//\)$' \| \
+ X"$ac_dest" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_dest" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+
+ { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
+echo "$as_me: executing $ac_dest commands" >&6;}
+ case $ac_dest in
+ depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # So let's grep whole file.
+ if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
+ dirpart=`(dirname "$mf") 2>/dev/null ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`(dirname "$file") 2>/dev/null ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p $dirpart/$fdir
+ else
+ as_dir=$dirpart/$fdir
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5
+echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+ ;;
+ esac
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+
+if test "x$sysname" = "xSunOS"; then
+ sed -e 's/^LDFLAGS = /LDFLAGS = -L\/usr\/sfw\/lib -lxnet -lsocket -lnsl /' -e 's/-DLINUX/-DSOLARIS -I\/usr\/sfw\/include/' util/Makefile >/tmp/make
+ # -e 's/ipmidir.c/ipmibmc.c/'
+ cp -f /tmp/make util/Makefile
+fi
+
+echo "$as_me:$LINENO: result: " >&5
+echo "${ECHO_T}" >&6
+echo "$as_me:$LINENO: result: ipmiutil $VERSION" >&5
+echo "${ECHO_T}ipmiutil $VERSION" >&6
+echo "$as_me:$LINENO: result: OS : $os" >&5
+echo "${ECHO_T} OS : $os" >&6
+echo "$as_me:$LINENO: result: ARCH : $archm" >&5
+echo "${ECHO_T} ARCH : $archm" >&6
+echo "$as_me:$LINENO: result: DRIVERS : $drivers lan $drv_lanplus" >&5
+echo "${ECHO_T} DRIVERS : $drivers lan $drv_lanplus" >&6
+echo "$as_me:$LINENO: result: " >&5
+echo "${ECHO_T}" >&6
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..8f3e301
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,441 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(util/ipmiutil.c)
+AM_INIT_AUTOMAKE(ipmiutil,2.9.3)
+AM_CONFIG_HEADER(config.h)
+
+AC_PREFIX_DEFAULT(/usr)
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_CHECK_PROG([SED], [sed], [sed])
+
+dnl Checks for libraries.
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h sys/ioctl.h syslog.h unistd.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_OFF_T
+AC_HEADER_TIME
+AC_STRUCT_TM
+
+dnl Checks for library functions.
+AC_PROG_GCC_TRADITIONAL
+AC_FUNC_MMAP
+AC_FUNC_STRFTIME
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS(select socket strcspn strdup strspn strtoul memcpy)
+
+AM_PROG_LIBTOOL
+
+AC_CONST
+AC_TRY_COMPILE([#include <sys/types.h>
+ #include <sys/socket.h>],
+ [socklen_t len = 42; return 0;],
+ ac_cv_type_socklen_t=yes,
+ ac_cv_type_socklen_t=no)
+if test $ac_cv_type_socklen_t != yes; then
+ AC_DEFINE(socklen_t, int, [if socklen_t is not defined, provide something useful])
+else
+ AC_DEFINE(HAVE_SOCKLEN_T, 1, [if socklen_t is defined, make note of it])
+fi
+
+tmpspec=/tmp/iuspec.tmp$$
+archm=`uname -m`
+sysname=`uname -s`
+LIB_DIR="/usr/lib"
+isredhat=0
+init_scripts="scripts/ipmi_port.sh scripts/ipmiutil_evt scripts/ipmiutil_asy scripts/ipmiutil_wdt"
+projdir=`pwd`
+SUBDIR_S="doc scripts lib util"
+os=Linux
+
+# ltmain.sh, config.sub, et al should have been created, but check to be sure.
+beforeprog="./beforeconf.sh"
+progs="config.sub ltmain.sh"
+for p in $progs
+do
+ echo -e "checking for $p... \c"
+ if test -f "$p"; then
+ echo "yes"
+ else
+ echo "no"
+ echo "Run $beforeprog to configure the build environment."
+ exit 1
+ fi
+done
+
+#[ if test -n "$GCC"; then
+# CFLAGS="$CFLAGS -Wall -D_REENTRANT"
+# fi]
+
+drv_landesk=0
+dnl configure for LANDESK libipmiapi or not
+AC_ARG_ENABLE([landesk],
+ [ --enable-landesk adds landesk library support [[default=no]]],
+ [if test "x$enableval" = "xyes"; then
+ drv_landesk=1
+ LANDESK_CFLAGS="-DLINK_LANDESK"
+ LANDESK_LDADD="-lipmiapi -L../lib"
+ AC_SUBST(LANDESK_CFLAGS)
+ AC_SUBST(LANDESK_LDADD)
+ fi]
+ )
+
+dnl Configure ipmiutil for lanplus (libipmi_lanplus.a) or not (default yes)
+AC_ARG_ENABLE([lanplus],
+ [ --disable-lanplus disable lanplus support [[default=enabled]]],)
+if test "x$enable_lanplus" = "xno"; then
+ drv_lanplus=""
+ LANPLUS_CFLAGS=""
+ LANPLUS_LDADD=""
+ LANPLUS_LIB=""
+ LANPLUS_CRYPTO=""
+ LANPLUS_SAM="no"
+ LD_SAMX=""
+else
+ drv_lanplus="lanplus"
+ LANPLUS_CFLAGS="-DHAVE_LANPLUS"
+ # LANPLUS_CFLAGS="-DHAVE_LANPLUS -I${projdir}/lib/lanplus/inc"
+ # LANPLUS_LDADD="-L../lib -lintf_lanplus -L/usr/local/lib -lcrypto"
+ LANPLUS_LDADD="-L../lib -lipmi_lanplus -L/usr/local/lib -lcrypto"
+ LANPLUS_LIB="../lib/libipmi_lanplus.a"
+ LANPLUS_CRYPTO="-lcrypto"
+ LANPLUS_SAM="yes"
+ LD_SAMX="../lib/libipmi_lanplus.a -lcrypto"
+fi
+
+dnl Configure libipmiutil.a for lanplus or not
+dnl Only SOL requires lanplus, so usually build libipmiutil.a without lanplus
+#AC_ARG_ENABLE([liblanplus],
+# [ --enable-liblanplus build libipmiutil.a with lanplus [[default=disabled]]],)
+#if test "x$enable_liblanplus" = "xyes"; then
+# LANPLUS_SAM="yes"
+# LD_SAMX= "../lib/libipmi_lanplus.a -lcrypto"
+#else
+# LANPLUS_SAM="no"
+# LD_SAMX=""
+#fi
+
+# strings /lib/libssl.so* |grep EVP_sha256
+dnl configure for SHA256, build lanplus with SHA256 support, uses later openssl.
+AC_ARG_ENABLE([sha256],
+ [ --enable-sha256 build with SHA256 support, requires later openssl.],
+ [if test "x$enableval" = "xyes"; then
+ LANPLUS_CFLAGS="$LANPLUS_CFLAGS -DHAVE_SHA256"
+ fi]
+ )
+
+CROSS_LFLAGS=""
+CROSS_CFLAGS=""
+
+dnl configure for standalone, with no lanplus or GPL libs
+AC_ARG_ENABLE([standalone],
+ [ --enable-standalone build standalone, with no GPL or LanPlus libs.],
+ [if test "x$enableval" = "xyes"; then
+ GPL_CFLAGS=""
+ LANPLUS_CFLAGS=""
+ LANPLUS_LDADD=""
+ LANPLUS_LIB=""
+ LANPLUS_CRYPTO=""
+ LANPLUS_SAM="no"
+ LD_SAMX=""
+ CFLAGS="-O2"
+ SUBDIR_S="doc scripts util"
+ if test "x$cross_compiling" = "xyes"; then
+ # cross-compiling, so link with -static (e.g. Android ARM)
+ CROSS_LFLAGS="-static"
+ CROSS_CFLAGS="-DCROSS_COMPILE"
+ sed -i -e 's/^# ipmiutil: $(METASOURCE:.c=.o)/ipmiutil:\t$(METASOURCE:.c=.o)\n\t$(CC) $(CFLAGS) $(LDFLAGS) -o ipmiutil $(METASOURCE:.c=.o) $(LDADD)/' util/Makefile.am
+ fi
+ fi]
+ )
+
+dnl configure for GPL build or not (GPL files: md2.h, ipmi_ioctl.h)
+AC_ARG_ENABLE([gpl],
+ [ --enable-gpl build with some GPL code [[default=no]]],
+ [if test "x$enableval" = "xyes"; then
+ GPL_CFLAGS="-DALLOW_GPL"
+ else
+ GPL_CFLAGS=""
+ fi]
+ )
+
+dnl Does this Linux have systemd enabled? Otherwise use sysv init.
+AC_ARG_ENABLE([systemd],
+ [ --enable-systemd enable systemd service type=notify support and %_unitdir [[default=disabled]]],)
+if test "x$enable_systemd" = "xyes"; then
+ GPL_CFLAGS="$GPL_CFLAGS -DENABLE_SYSTEMD"
+ # if systemd enabled, install service scripts in unitdir
+ SYSTEMD_DIR=`rpm --eval "%{_unitdir}"`
+else
+ # otherwise install the systemd service scripts in the data dir
+ if test "x$sysname" = "xDarwin" ; then
+ # MacOS 'which' command returns 0 always
+ SYSTEMD_DIR=/usr/share/ipmiutil
+ else
+ which rpm >/dev/null 2>&1
+ if test $? -eq 0 ; then
+ datad=`rpm --eval "%{_datadir}"`
+ SYSTEMD_DIR=${datad}/ipmiutil
+ else
+ SYSTEMD_DIR=/usr/share/ipmiutil
+ fi
+ fi
+fi
+
+case "$archm" in
+ ia64)
+ IA64_CFLAGS="-D__IA64__"
+ LIB_DIR="/usr/lib64"
+ ;;
+ ppc64)
+ IA64_CFLAGS="-DSTUB_IO"
+ LIB_DIR="/usr/lib64"
+ ;;
+ x86_64)
+ IA64_CFLAGS=""
+ LIB_DIR="/usr/lib64"
+ ;;
+ i386)
+ IA64_CFLAGS=""
+ ;;
+ i586)
+ IA64_CFLAGS=""
+ ;;
+ i686)
+ IA64_CFLAGS=""
+ ;;
+ sun4u)
+ IA64_CFLAGS="-D__SPARC__"
+ ;;
+ *)
+ IA64_CFLAGS="-DSTUB_IO"
+ ;;
+esac
+
+dnl # libdir can be set with --libdir=/usr/lib (default=${exec_prefix}/lib)
+echo $libdir |grep exec_prefix >/dev/null 2>&1
+if test $? -ne 0; then
+ LIB_DIR="$libdir"
+ echo "libdir set to $libdir"
+fi
+
+PKG_DIR=/usr/src/packages
+INS_LIB=""
+SHR_LINK="libipmiutil.so"
+init0=
+if test "x$sysname" = "xSunOS"; then
+ echo "Detected Solaris"
+ os=solaris
+ archp=`uname -p`
+ if test -d "/usr/sfw/lib"; then
+ sfwdir=/usr/sfw
+ else
+ sfwdir=/usr/local
+ fi
+ OS_CFLAGS="-DSOLARIS -I${sfwdir}/include"
+ OS_LFLAGS="-L${sfwdir}/lib -lxnet -lsocket -lnsl -lresolv"
+ OS_DRIVERS="ipmibmc.c ipmilipmi.c"
+ drivers="bmc lipmi"
+ INS_LIB="# "
+ SHR_LINK=""
+else
+ if test "x$sysname" = "xLinux"; then
+ MD2_CFLAGS=""
+ OS_LFLAGS=""
+ OS_DRIVERS="imbapi.c ipmimv.c ipmild.c ipmidir.c"
+ if test $drv_landesk -eq 1; then
+ drivers="open imb landesk direct"
+ else
+ drivers="open imb direct"
+ fi
+ os=linux
+ tmpc=/tmp/tmp.c
+ tmpo=/tmp/tmp.o
+ echo $ECHO_N "checking compile warning flags ... $ECHO_C"
+ cfwarn="-Wno-pointer-sign -Wno-sign-conversion -Wunused-result -Wgnu-designator"
+ echo "int main() { return(1); }" >$tmpc
+ gcc -o $tmpo -c $cfwarn $tmpc >/dev/null 2>&1
+ if test $? -ne 0 ; then
+ cfwarn=
+ echo "skip"
+ else
+ echo "ok, suppress excess warnings"
+ fi
+ rm -f $tmpc $tmpo >/dev/null 2>&1
+ echo $ECHO_N "checking compile fortify flags ... $ECHO_C"
+ cfhard="-fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2"
+ echo "int main() { return(1); }" >$tmpc
+ gcc -o $tmpo -c $cfhard $tmpc >/dev/null 2>&1
+ if test $? -ne 0 ; then
+ cfhard=
+ echo "skip"
+ else
+ echo "ok, add"
+ fi
+ rm -f $tmpc $tmpo >/dev/null 2>&1
+ if test -f "/etc/debian_version"; then
+ echo "Detected Debian Linux"
+ os=debian
+ PKG_DIR=..
+ INS_LIB="# "
+ # use dpkg-buildpackage instead of rpmbuild
+ else
+ which rpm >/dev/null 2>&1
+ if test $? -eq 0; then
+ pkgtop=`rpm --eval "%{_topdir}"`
+ PKG_DIR=$pkgtop
+ fi
+ fi
+ if test -f "/etc/redhat-release"; then
+ echo "Detected Red Hat Linux"
+ os=redhat
+ isredhat=1
+ fi
+ if test -f "/etc/SuSE-release"; then
+ echo "Detected SuSE Linux"
+ os=suse
+ sed -e 's/# POST_INSTALL/if [ ! -f \/etc\/snmp\/snmpd.conf ]; then\n if [ -f \/etc\/ucdsnmpd.conf ]; then\n mkdir -p \/etc\/snmp; ln -s \/etc\/ucdsnmpd.conf \/etc\/snmp\/snmpd.conf\n fi\nif [ -f \/etc\/snmpd.conf ]; then\nmkdir -p \/etc\/snmp; ln -s \/etc\/snmpd.conf \/etc\/snmp\/snmpd.conf\nfi\nfi\n#/' -e 's/make install DEST/make install-strip DEST/' doc/ipmiutil.spec >$tmpspec
+ cp -f $tmpspec doc/ipmiutil.spec
+ fi
+ if test -f "/etc/mvl-release"; then
+ echo "Detected MontaVista Linux"
+ os=montavista
+ init0=/etc/init.d
+ sed -e 's/openssl-devel/openssl-dev\n%ifarch x86_pentium3 x86_pentium4\nAutoReqProv: No\n%endif/' -e 's/%{_mandir}/\/usr\/share\/man/' -e 's/%{_initrddir}/\/etc\/init.d/' -e 's/%{_sysconfdir}/\/etc/' -e 's/# POST_INSTALL/newcrypto=%{_libdir}\/libcrypto.so.4\nif [ ! -f $newcrypto ]; then\n cp -f %{_libdir}\/libcrypto.so.0 $newcrypto\nfi\n#/' -e 's/make install DEST/make install-strip DEST/' doc/ipmiutil.spec >$tmpspec
+ cp -f $tmpspec doc/ipmiutil.spec
+ fi
+ if test -f "/etc/wrs-release" -o -d "$WIND_HOME"; then
+ echo "Detected WindRiver Linux"
+ os=windriver
+ echo "Be sure to set up the WR build environment first"
+ # WR requires extra steps in the spec file.
+ grep "%configure_target" doc/ipmiutil.spec >/dev/null 2>&1
+ if test $? -ne 0; then
+ # WR changes have not been patched in, so make them.
+ sed -e 's/Release: 1%{?dist}/Release: 1_WR/' -e 's/%build/%build\n%configure_target\n%define _config_cache config.cache\n/' -e 's/^make$/make CC="$CC" TARGET_CFLAGS="$CFLAGS" TARGET_LDADD="-L%{_host_cross_lib_dir}" LDFLAGS="$LDFLAGS" CXX="$CXX" CXXFLAGS="$CXXFLAGS" LD="$LD" AS="$AS" AR="$AR" CPP="$CPP" NM="$NM" OBJCOPY="$OPBJCOPY" OBJDUMP="$OPBJDUMP" RANLIB="$RANLIB" STRIP="$STRIP"/' -e 's/%install/%install\n%configure_target\n/' doc/ipmiutil.spec >$tmpspec
+ cp -f $tmpspec doc/ipmiutil.spec
+ fi
+ # WRL libcrypto does not have MD2
+ MD2_CFLAGS="-DSKIP_MD2"
+ init0=/etc/rc.d/init.d
+ fi
+ if test $isredhat -eq 0 ; then
+ # set default start/stop for init scripts
+ sed -i 's/# Default-Start:/# Default-Start: 3 4 5/' $init_scripts
+ sed -i 's/# Default-Stop:/# Default-Stop: 0 1 2 6/' $init_scripts
+ fi
+ if test -f "$LIB_DIR/libcrypto.so"; then
+ strings $LIB_DIR/libcrypto.so | grep EVP_md2 >/dev/null 2>&1
+ if test $? -ne 0; then
+ echo "No MD2 detected in openssl libcrypto.so"
+ MD2_CFLAGS="-DSKIP_MD2"
+ fi
+ else
+ echo "No openssl $LIB_DIR/libcrypto.so detected"
+ MD2_CFLAGS="-DSKIP_MD2"
+ fi
+ OS_CFLAGS="-DLINUX $MD2_CFLAGS -fPIC $cfwarn $cfhard"
+ else
+ # usually "x$sysname" = "xFreeBSD", but allow NetBSD
+ echo $sysname | grep BSD >/dev/null 2>&1
+ if test $? -eq 0; then
+ os=bsd
+ OS_CFLAGS="-DBSD"
+ OS_LFLAGS=""
+ OS_DRIVERS="ipmimv.c ipmidir.c"
+ drivers="open direct"
+ else
+ uname -a | grep -i HP-UX >/dev/null 2>&1
+ hpux=$?
+ if test $hpux -eq 0; then
+ echo "Detected HP-UX"
+ os=hpux
+ MD2_CFLAGS="-DSKIP_MD2"
+ OS_CFLAGS="-DHPUX"
+ OS_LFLAGS=""
+ OS_DRIVERS="ipmimv.c"
+ drivers="open"
+ SHR_LINK=""
+ elif test "x$sysname" = "xDarwin" ; then
+ echo "Detected MacOSX"
+ os=macos
+ MD2_CFLAGS="-DSKIP_MD2"
+ OS_CFLAGS="-DMACOS"
+ OS_LFLAGS=""
+ OS_DRIVERS="ipmimv.c ipmidir.c"
+ drivers="open direct"
+ SHR_LINK=""
+ # optionally check for AppleBMC.kext here?
+ else
+ # not Solaris, Linux, BSD, or HP-UX = error
+ echo "OS $sysname not yet supported"
+ exit 1
+ fi
+ fi
+ fi
+fi
+
+dnl determine where the init.d directory is
+if test "x$init0" = "x" ; then
+ if test "x$os" != "xmacos" ; then
+ which rpmbuild >/dev/null 2>&1
+ if test $? -eq 0 ; then
+ init1=`rpmbuild --showrc |grep " _initrddir" | cut -d'}' -f2`
+ if test "x$init1" != "x" ; then
+ init0=/etc/${init1}
+ fi
+ fi
+ fi
+fi
+if test "x$init0" = "x" ; then
+ if test -d ${etcdir}/rc.d/init.d ; then
+ init0=/etc/rc.d/init.d;
+ else
+ init0=/etc/init.d;
+ fi
+fi
+INIT_DIR=${init0}
+
+AC_SUBST(IA64_CFLAGS)
+AC_SUBST(LANPLUS_CFLAGS)
+AC_SUBST(LANPLUS_LDADD)
+AC_SUBST(LANPLUS_LIB)
+AC_SUBST(LANPLUS_CRYPTO)
+AC_SUBST(LANPLUS_SAM)
+AC_SUBST(LD_SAMX)
+AC_SUBST(GPL_CFLAGS)
+AC_SUBST(OS_CFLAGS)
+AC_SUBST(OS_LFLAGS)
+AC_SUBST(OS_DRIVERS)
+AC_SUBST(PKG_DIR)
+AC_SUBST(INIT_DIR)
+AC_SUBST(LIB_DIR)
+AC_SUBST(INS_LIB)
+AC_SUBST(SUBDIR_S)
+AC_SUBST(CROSS_CFLAGS)
+AC_SUBST(CROSS_LFLAGS)
+AC_SUBST(SYSTEMD_DIR)
+AC_SUBST(SHR_LINK)
+
+AC_OUTPUT(Makefile util/Makefile lib/lanplus/Makefile doc/Makefile scripts/Makefile)
+
+if test "x$sysname" = "xSunOS"; then
+ sed -e 's/^LDFLAGS = /LDFLAGS = -L\/usr\/sfw\/lib -lxnet -lsocket -lnsl /' -e 's/-DLINUX/-DSOLARIS -I\/usr\/sfw\/include/' util/Makefile >/tmp/make
+ # -e 's/ipmidir.c/ipmibmc.c/'
+ cp -f /tmp/make util/Makefile
+fi
+
+AC_MSG_RESULT([])
+AC_MSG_RESULT([ipmiutil $VERSION])
+AC_MSG_RESULT([ OS : $os])
+AC_MSG_RESULT([ ARCH : $archm])
+AC_MSG_RESULT([ DRIVERS : $drivers lan $drv_lanplus])
+AC_MSG_RESULT([])
+
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..36a5f39
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,272 @@
+ipmiutil (2.9.3-1) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Mon, 02 Dec 2013 22:39:56 -0500
+
+ipmiutil (2.9.3-2) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Mon, 02 Dec 2013 22:39:26 -0500
+
+ipmiutil (2.9.2-2) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Fri, 18 Oct 2013 04:11:06 -0400
+
+ipmiutil (2.9.2-1) unstable; urgency=low
+
+ * Initial official Debian release (Closes: #650323)
+ * Updated debian/copyright to DEP-5 format, and included more detail
+ * See also ChangeLog file in source
+
+ -- Andy Cress <arcress@users.sourceforge.net> Fri, 14 Jun 2013 12:08:08 -0400
+
+ipmiutil (2.9.1+nmu1) UNRELEASED; urgency=low
+
+ * updated rules to use dh syntax and debhelper 9 (up from 4); many lintian
+ cleanups as a result
+ * added dh-autoreconf as a build dependency; can now stop using beforeconf.sh
+ * updated control file with additional information and standards-version
+ * --enable-gpl is now used in rules; enables MD2 hash for IPMI LAN
+ * daily cronjob is no longer installed via postinst script
+ * prerm script added, properly deletes /var/lib/ipmiutil on purge
+
+ -- Alex Waite <Alexqw85@gmail.com> Fri, 14 Jun 2013 17:21:15 +0200
+
+ipmiutil (2.9.1) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Fri, 12 Apr 2013 07:21:54 -0400
+
+ipmiutil (2.9.0) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Thu, 04 Apr 2013 21:14:03 -0400
+
+ipmiutil (2.9.0) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Thu, 04 Apr 2013 21:12:25 -0400
+
+ipmiutil (2.9.0) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Thu, 04 Apr 2013 21:09:44 -0400
+
+ipmiutil (2.9.0) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Thu, 04 Apr 2013 21:06:46 -0400
+
+ipmiutil (2.9.0) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Thu, 04 Apr 2013 21:00:16 -0400
+
+ipmiutil (2.9.0) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Thu, 04 Apr 2013 20:58:37 -0400
+
+ipmiutil (2.8.9) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Sun, 31 Mar 2013 18:51:35 -0400
+
+ipmiutil (2.8.9) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Sun, 31 Mar 2013 18:51:07 -0400
+
+ipmiutil (2.8.9) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Sun, 31 Mar 2013 18:50:35 -0400
+
+ipmiutil (2.8.9) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Sun, 31 Mar 2013 18:49:23 -0400
+
+ipmiutil (2.8.9) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Sun, 31 Mar 2013 18:46:31 -0400
+
+ipmiutil (2.8.8) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Thu, 17 Jan 2013 06:06:40 -0500
+
+ipmiutil (2.8.7) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Tue, 11 Dec 2012 16:17:16 -0500
+
+ipmiutil (2.8.6) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Thu, 30 Aug 2012 11:57:52 -0400
+
+ipmiutil (2.8.5) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Wed, 13 Jun 2012 12:16:30 -0400
+
+ipmiutil (2.8.5) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Wed, 13 Jun 2012 12:15:57 -0400
+
+ipmiutil (2.8.5) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Wed, 13 Jun 2012 11:39:40 -0400
+
+ipmiutil (2.8.4) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Thu, 03 May 2012 11:03:55 -0400
+
+ipmiutil (2.8.4) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Wed, 02 May 2012 15:53:24 -0400
+
+ipmiutil (2.8.3) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Thu, 22 Mar 2012 16:36:45 -0400
+
+ipmiutil (2.8.2) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Mon, 13 Feb 2012 10:12:08 -0500
+
+ipmiutil (2.8.1) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Fri, 13 Jan 2012 10:27:46 -0500
+
+ipmiutil (2.8.0) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Wed, 07 Dec 2011 16:50:02 -0500
+
+ipmiutil (2.8.0) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Wed, 07 Dec 2011 16:49:11 -0500
+
+ipmiutil (2.8.0b) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Fri, 02 Dec 2011 18:37:57 -0500
+
+ipmiutil (2.8.0) UNRELEASED; urgency=low
+
+ * New upstream version, added prerm script
+
+ -- Andy Cress <arcress@users.sourceforge.net> Fri, 28 Oct 2011 16:44:02 -0400
+
+ipmiutil (2.7.9) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Fri, 28 Oct 2011 16:43:35 -0400
+
+ipmiutil (2.8.0) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Wed, 26 Oct 2011 11:01:02 -0400
+
+ipmiutil (2.7.9) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Tue, 20 Sep 2011 08:17:01 -0400
+
+ipmiutil (2.7.9) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Tue, 20 Sep 2011 08:14:05 -0400
+
+ipmiutil (2.7.9) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Thu, 15 Sep 2011 17:13:31 -0400
+
+ipmiutil (2.7.8) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Tue, 19 Jul 2011 12:57:11 -0400
+
+ipmiutil (2.7.7) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Mon, 16 May 2011 16:49:12 -0400
+
+ipmiutil (2.7.6) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Fri, 15 Apr 2011 12:47:17 -0400
+
+ipmiutil (2.7.5) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Fri, 25 Feb 2011 12:43:45 -0500
+
+ipmiutil (2.7.4) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Tue, 11 Jan 2011 13:52:43 -0500
+
+ipmiutil (2.7.3) UNRELEASED; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Fri, 17 Dec 2010 14:30:28 -0500
+
+ipmiutil (2.7.2) UNRELEASED; urgency=low
+
+ * New upstream version.
+ * Patch to allow Debian package builds from svn.
+
+ -- Andy Cress <arcress@users.sourceforge.net> Fri, 29 Oct 2010 16:44:31 -0500
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..b69ef91
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,27 @@
+Source: ipmiutil
+Section: utils
+Priority: optional
+Maintainer: Andy Cress <arcress@users.sourceforge.net>
+Build-Depends: debhelper (>> 9), dh-autoreconf, libssl-dev
+Standards-Version: 3.9.4.0
+Vcs-Svn: svn://svn.code.sf.net/p/ipmiutil/code/trunk
+Vcs-Browser: https://sourceforge.net/p/ipmiutil/code/HEAD/tree/trunk/
+Homepage: http://ipmiutil.sourceforge.net/
+
+Package: ipmiutil
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base
+Suggests: openipmi
+Description: Easy-to-use IPMI server management utilities
+ The ipmiutil package provides easy-to-use utilities to view the SEL,
+ perform an IPMI chassis reset, set up the IPMI LAN and Platform Event Filter
+ entries to allow SNMP alerts, Serial-Over-LAN console, event daemon, and
+ other IPMI tasks.
+ .
+ These can be invoked with the metacommand ipmiutil, or via subcommand
+ shortcuts as well. IPMIUTIL can also write sensor thresholds, FRU asset tags,
+ and has a full IPMI configuration save/restore.
+ An IPMI driver can be provided by either the OpenIPMI driver (/dev/ipmi0)
+ or the Intel IPMI driver (/dev/imb), etc. If used locally and no driver is
+ detected, ipmiutil will use user-space direct I/Os instead.
+
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..1800759
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,129 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: ipmiutil
+Upstream-Contact: Andy Cress <arcress at users.sourceforge.net>
+Source: http://ipmiutil.sourceforge.net
+Comment: This package was debianized by Andy Cress on 2010-10-29,
+ with Debian package updates by Alex Waite on 2013-06-14
+
+Files: *
+Copyright: 2001-2008, Intel Corporation
+ 2009-2012, Kontron America
+ 2013, Andy Cress <arcress at users.sourceforge.net>
+License: BSD-3-clause
+
+Files: lib/lanplus/*
+Copyright: 2003 Sun Microsystems, Inc.
+License: BSD-3-clause
+
+Files: util/itsol.c
+Copyright: 2005 Tyan Computer Corp.
+License: BSD-3-clause
+
+Files: util/iekanalyzer.c
+Copyright: 2007 Kontron Canada, Inc.
+ 2003 Sun Microsystems, Inc.
+License: BSD-3-clause
+
+Files: util/md2.h
+Copyright: 2003 FreeIPMI Core Team
+Comment: Optional to include this file, based on configure options
+License: GPL-2.0
+
+Files: util/AnsiTerm.cpp
+Copyright: 2009 Robert Nelson <robertnelson at users.sourceforge.net>
+License: BSD-2-clause
+
+Files: util/oem_dell.c
+Copyright: 2008, Dell Inc
+License: BSD-3-clause
+
+Files: util/oem_sun.c
+Copyright: 2005 Sun Microsystems, Inc.
+License: BSD-3-clause
+
+Files: util/ifirewall.c
+Copyright: 2010 Kontron America Inc.
+ 2005 International Business Machines, Inc.
+ 2003 Sun Microsystems, Inc.
+License: BSD-3-clause
+
+Files: util/ifwum.c util/ihpm.c
+Copyright: 2004-2006 Kontron Canada, Inc.
+ 2003 Sun Microsystems, Inc.
+License: BSD-3-clause
+
+Files: util/md5.c
+Copyright: 1999, 2000, 2002 Aladdin Enterprises.
+Comment: Aladdin unrestricted license is compatible with BSD-3-clause
+License: Aladdin
+ 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
+
+License: 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.
+
+License: BSD-2-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.
+ 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.
+
+License: GPL-2.0
+ 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, or (at your option)
+ any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ A copy of the GNU General Public License is available as
+ /usr/share/common-licenses/GPL-2 in the Debian distribution or on
+ the World Wide Web at http://www.gnu.org/copyleft/gpl.html. You can
+ also obtain it by writing to the Free Software Foundation, Inc.,
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/debian/dirs b/debian/dirs
new file mode 100644
index 0000000..d398c09
--- /dev/null
+++ b/debian/dirs
@@ -0,0 +1,2 @@
+etc/init.d
+etc/cron.daily
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..55bc0a6
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,2 @@
+README
+AUTHORS
diff --git a/debian/files b/debian/files
new file mode 100644
index 0000000..793f54c
--- /dev/null
+++ b/debian/files
@@ -0,0 +1 @@
+ipmiutil_2.9.1_amd64.deb utils optional
diff --git a/debian/ipmiutil.cron.daily b/debian/ipmiutil.cron.daily
new file mode 120000
index 0000000..9241b18
--- /dev/null
+++ b/debian/ipmiutil.cron.daily
@@ -0,0 +1 @@
+../scripts/checksel \ No newline at end of file
diff --git a/debian/ipmiutil.lintian-overrides b/debian/ipmiutil.lintian-overrides
new file mode 100644
index 0000000..5667e46
--- /dev/null
+++ b/debian/ipmiutil.lintian-overrides
@@ -0,0 +1,4 @@
+# The only GPL code in ipmiutil is md2.h, which is excluded
+# by default, so ignore unsafe link with openssl warning
+ipmiutil: possible-gpl-code-linked-with-openssl
+
diff --git a/debian/ipmiutil.substvars b/debian/ipmiutil.substvars
new file mode 100644
index 0000000..275a91d
--- /dev/null
+++ b/debian/ipmiutil.substvars
@@ -0,0 +1,2 @@
+shlibs:Depends=libc6 (>= 2.15), libssl1.0.0 (>= 1.0.0)
+misc:Depends=
diff --git a/debian/postinst b/debian/postinst
new file mode 100755
index 0000000..399957f
--- /dev/null
+++ b/debian/postinst
@@ -0,0 +1,41 @@
+#!/bin/sh
+# Debian postinstall script
+#
+# see: dh_installdeb(1)
+set -e
+case "$1" in
+ configure)
+ sbindir=/usr/bin
+ vardir=/var/lib/ipmiutil
+ sensorout=$vardir/sensor_out.txt
+
+ mkdir -p $vardir
+
+ # Run some ipmiutil command to see if any IPMI interface works.
+ IPMIcmd=true
+ $sbindir/ipmiutil sel -v >/dev/null 2>&1 || IPMIcmd=false
+
+ # If IPMIcmd is still true, then the IPMI command was successful, and IPMI is enabled locally.
+ if $IPMIcmd ; then
+ # Capture a snapshot of IPMI sensor data once now for later reuse.
+ if [ ! -f $sensorout ]; then
+ $sbindir/ipmiutil sensor -q >$sensorout
+ fi
+ fi
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/prerm b/debian/prerm
new file mode 100755
index 0000000..e66d2d9
--- /dev/null
+++ b/debian/prerm
@@ -0,0 +1,26 @@
+#!/bin/sh
+# Debian prerm script
+#
+set -e
+
+case "$1" in
+ purge)
+ if [ -d /var/lib/ipmiutil/ ]
+ then
+ rm -Rf /var/lib/ipmiutil/
+ fi
+ ;;
+ remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
+ ;;
+ *)
+ echo "postrm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..49191d6
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,23 @@
+#!/usr/bin/make -f
+%:
+ dh $@ --with autoreconf
+
+PKD = $(abspath $(dir $(MAKEFILE_LIST)))
+PKG = $(word 2,$(shell dpkg-parsechangelog -l$(PKD)/changelog | grep ^Source))
+VER ?= $(shell dpkg-parsechangelog -l$(PKD)/changelog | perl -ne 'print $$1 if m{^Version:\s+(?:\d+:)?(\d.*)(?:\-\d+.*)};')
+
+.PHONY: get-orig-source
+## http://wiki.debian.org/onlyjob/get-orig-source
+get-orig-source: $(info I: $(PKG)_$(VER))
+ @echo "# Downloading..."
+ uscan --noconf --verbose --rename --destdir=$(CURDIR) --check-dirname-level=0 --force-download --download-version $(VER) $(PKD)
+
+override_dh_auto_configure:
+ dh_auto_configure -- --enable-gpl
+
+# work around bug #670796
+override_dh_autoreconf:
+ dh_autoreconf --exclude=mkinstalldirs
+
+override_dh_installchangelogs:
+ dh_installchangelogs ChangeLog
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..f1d1c3c
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,2 @@
+version=3
+http://sf.net/ipmiutil/ipmiutil-(.+)\.tar\.gz
diff --git a/depcomp b/depcomp
new file mode 100755
index 0000000..04701da
--- /dev/null
+++ b/depcomp
@@ -0,0 +1,530 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2005-07-09.11
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+# 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, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+ '')
+ echo "$0: No command. Try \`$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+ depmode Dependency tracking mode.
+ source Source file read by `PROGRAMS ARGS'.
+ object Object file output by `PROGRAMS ARGS'.
+ DEPDIR directory where to store dependencies.
+ depfile Dependency file to output.
+ tmpdepfile Temporary file to use when outputing dependencies.
+ libtool Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "depcomp $scriptversion"
+ exit $?
+ ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+ echo "depcomp: Variables source, object and depmode must be set" 1>&2
+ exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+ sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags. We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write. Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+ # HP compiler uses -M and no extra arg.
+ gccflag=-M
+ depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+ # This is just like dashmstdout with a different argument.
+ dashmflag=-xM
+ depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want. Yay! Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff. Hmm.
+ "$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ mv "$tmpdepfile" "$depfile"
+ ;;
+
+gcc)
+## There are various ways to get dependency output from gcc. Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+## up in a subdir. Having to rename by hand is ugly.
+## (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+## -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+## than renaming).
+ if test -z "$gccflag"; then
+ gccflag=-MD,
+ fi
+ "$@" -Wp,"$gccflag$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+ sed -e 's/^[^:]*: / /' \
+ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header). We avoid this by adding
+## dummy dependencies for each header file. Too bad gcc doesn't do
+## this for us directly.
+ tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'. On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+sgi)
+ if test "$libtool" = yes; then
+ "$@" "-Wp,-MDupdate,$tmpdepfile"
+ else
+ "$@" -MDupdate "$tmpdepfile"
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+
+ if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
+ echo "$object : \\" > "$depfile"
+
+ # Clip off the initial element (the dependent). Don't try to be
+ # clever and replace this with sed code, as IRIX sed won't handle
+ # lines with more than a fixed number of characters (4096 in
+ # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
+ # the IRIX cc adds comments like `#:fec' to the end of the
+ # dependency line.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+ tr '
+' ' ' >> $depfile
+ echo >> $depfile
+
+ # The second pass generates a dummy entry for each header file.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> $depfile
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+aix)
+ # The C for AIX Compiler uses -M and outputs the dependencies
+ # in a .u file. In older versions, this file always lives in the
+ # current directory. Also, the AIX compiler puts `$object:' at the
+ # start of each line; $object doesn't have directory information.
+ # Version 6 uses the directory in both cases.
+ stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
+ tmpdepfile="$stripped.u"
+ if test "$libtool" = yes; then
+ "$@" -Wc,-M
+ else
+ "$@" -M
+ fi
+ stat=$?
+
+ if test -f "$tmpdepfile"; then :
+ else
+ stripped=`echo "$stripped" | sed 's,^.*/,,'`
+ tmpdepfile="$stripped.u"
+ fi
+
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+
+ if test -f "$tmpdepfile"; then
+ outname="$stripped.o"
+ # Each line is of the form `foo.o: dependent.h'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
+ sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+icc)
+ # Intel's C compiler understands `-MD -MF file'. However on
+ # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+ # ICC 7.0 will fill foo.d with something like
+ # foo.o: sub/foo.c
+ # foo.o: sub/foo.h
+ # which is wrong. We want:
+ # sub/foo.o: sub/foo.c
+ # sub/foo.o: sub/foo.h
+ # sub/foo.c:
+ # sub/foo.h:
+ # ICC 7.1 will output
+ # foo.o: sub/foo.c sub/foo.h
+ # and will wrap long lines using \ :
+ # foo.o: sub/foo.c ... \
+ # sub/foo.h ... \
+ # ...
+
+ "$@" -MD -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ # Each line is of the form `foo.o: dependent.h',
+ # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process this invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+ sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+tru64)
+ # The Tru64 compiler uses -MD to generate dependencies as a side
+ # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+ # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+ # dependencies in `foo.d' instead, so we check for that too.
+ # Subdirectories are respected.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+ if test "$libtool" = yes; then
+ # With Tru64 cc, shared objects can also be used to make a
+ # static library. This mecanism is used in libtool 1.4 series to
+ # handle both shared and static libraries in a single compilation.
+ # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
+ #
+ # With libtool 1.5 this exception was removed, and libtool now
+ # generates 2 separate objects for the 2 libraries. These two
+ # compilations output dependencies in in $dir.libs/$base.o.d and
+ # in $dir$base.o.d. We have to check for both files, because
+ # one of the two compilations can be disabled. We should prefer
+ # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+ # automatically cleaned when .libs/ is deleted, while ignoring
+ # the former would cause a distcleancheck panic.
+ tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
+ tmpdepfile2=$dir$base.o.d # libtool 1.5
+ tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
+ tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
+ "$@" -Wc,-MD
+ else
+ tmpdepfile1=$dir$base.o.d
+ tmpdepfile2=$dir$base.d
+ tmpdepfile3=$dir$base.d
+ tmpdepfile4=$dir$base.d
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+#nosideeffect)
+ # This comment above is used by automake to tell side-effect
+ # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout, regardless of -o.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ test -z "$dashmflag" && dashmflag=-M
+ # Require at least two characters before searching for `:'
+ # in the target name. This is to cope with DOS-style filenames:
+ # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+ "$@" $dashmflag |
+ sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+dashXmstdout)
+ # This case only exists to satisfy depend.m4. It is never actually
+ # run, as this mode is specially recognized in the preamble.
+ exit 1
+ ;;
+
+makedepend)
+ "$@" || exit $?
+ # Remove any Libtool call
+ if test "$libtool" = yes; then
+ while test $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+ # X makedepend
+ shift
+ cleared=no
+ for arg in "$@"; do
+ case $cleared in
+ no)
+ set ""; shift
+ cleared=yes ;;
+ esac
+ case "$arg" in
+ -D*|-I*)
+ set fnord "$@" "$arg"; shift ;;
+ # Strip any option that makedepend may not understand. Remove
+ # the object too, otherwise makedepend will parse it as a source file.
+ -*|$object)
+ ;;
+ *)
+ set fnord "$@" "$arg"; shift ;;
+ esac
+ done
+ obj_suffix="`echo $object | sed 's/^.*\././'`"
+ touch "$tmpdepfile"
+ ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile" "$tmpdepfile".bak
+ ;;
+
+cpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ "$@" -E |
+ sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+ sed '$ s: \\$::' > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ cat < "$tmpdepfile" >> "$depfile"
+ sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvisualcpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ "$@" || exit $?
+ IFS=" "
+ for arg
+ do
+ case "$arg" in
+ "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+ set fnord "$@"
+ shift
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift
+ shift
+ ;;
+ esac
+ done
+ "$@" -E |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
+ echo " " >> "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+none)
+ exec "$@"
+ ;;
+
+*)
+ echo "Unknown depmode $depmode" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..3c9c43a
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,383 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# doc/Makefile. Generated from Makefile.in by configure.
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 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.
+
+
+srcdir = .
+top_srcdir = ..
+
+pkgdatadir = $(datadir)/ipmiutil
+pkglibdir = $(libdir)/ipmiutil
+pkgincludedir = $(includedir)/ipmiutil
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = /usr/bin/install -c
+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 = x86_64-redhat-linux-gnu
+host_triplet = x86_64-redhat-linux-gnu
+subdir = doc
+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 =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = ${SHELL} /usr/dev/ipmiutil-2.9.3/missing --run aclocal-1.9
+AMDEP_FALSE = #
+AMDEP_TRUE =
+AMTAR = ${SHELL} /usr/dev/ipmiutil-2.9.3/missing --run tar
+AR = ar
+AUTOCONF = ${SHELL} /usr/dev/ipmiutil-2.9.3/missing --run autoconf
+AUTOHEADER = ${SHELL} /usr/dev/ipmiutil-2.9.3/missing --run autoheader
+AUTOMAKE = ${SHELL} /usr/dev/ipmiutil-2.9.3/missing --run automake-1.9
+AWK = gawk
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPP = gcc -E
+CPPFLAGS =
+CROSS_CFLAGS =
+CROSS_LFLAGS =
+CXX = g++
+CXXCPP = g++ -E
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO = echo
+ECHO_C =
+ECHO_N = -n
+ECHO_T =
+EGREP = grep -E
+EXEEXT =
+F77 = f95
+FFLAGS = -g -O2
+GPL_CFLAGS =
+IA64_CFLAGS =
+INIT_DIR = /etc//rc.d/init.d
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
+INS_LIB =
+LANDESK_CFLAGS =
+LANDESK_LDADD =
+LANPLUS_CFLAGS = -DHAVE_LANPLUS
+LANPLUS_CRYPTO = -lcrypto
+LANPLUS_LDADD = -L../lib -lipmi_lanplus -L/usr/local/lib -lcrypto
+LANPLUS_LIB = ../lib/libipmi_lanplus.a
+LANPLUS_SAM = yes
+LDFLAGS =
+LD_SAMX = ../lib/libipmi_lanplus.a -lcrypto
+LIBOBJS =
+LIBS =
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LIB_DIR = /usr/lib64
+LN_S = ln -s
+LTLIBOBJS =
+MAKEINFO = ${SHELL} /usr/dev/ipmiutil-2.9.3/missing --run makeinfo
+OBJEXT = o
+OS_CFLAGS = -DLINUX -fPIC -fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2
+OS_DRIVERS = imbapi.c ipmimv.c ipmild.c ipmidir.c
+OS_LFLAGS =
+PACKAGE = ipmiutil
+PACKAGE_BUGREPORT =
+PACKAGE_NAME =
+PACKAGE_STRING =
+PACKAGE_TARNAME =
+PACKAGE_VERSION =
+PATH_SEPARATOR = :
+PKG_DIR = /usr/src/redhat
+RANLIB = ranlib
+SED = /bin/sed
+SET_MAKE =
+SHELL = /bin/sh
+SHR_LINK = libipmiutil.so
+STRIP = strip
+SUBDIR_S = doc scripts lib util
+SYSTEMD_DIR = /usr/share/ipmiutil
+VERSION = 2.9.3
+ac_ct_AR = ar
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+ac_ct_F77 = f95
+ac_ct_RANLIB = ranlib
+ac_ct_STRIP = strip
+am__fastdepCC_FALSE = #
+am__fastdepCC_TRUE =
+am__fastdepCXX_FALSE = #
+am__fastdepCXX_TRUE =
+am__include = include
+am__leading_dot = .
+am__quote =
+am__tar = ${AMTAR} chof - "$$tardir"
+am__untar = ${AMTAR} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-redhat-linux-gnu
+build_alias =
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = redhat
+datadir = ${prefix}/share
+exec_prefix = ${prefix}
+host = x86_64-redhat-linux-gnu
+host_alias =
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = redhat
+includedir = ${prefix}/include
+infodir = ${prefix}/info
+install_sh = /usr/dev/ipmiutil-2.9.3/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localstatedir = ${prefix}/var
+mandir = ${prefix}/share/man
+mkdir_p = mkdir -p --
+oldincludedir = /usr/include
+prefix = /usr
+program_transform_name = s,x,x,
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+sysconfdir = ${prefix}/etc
+target_alias =
+
+#!/bin/sh
+# Makefile to build/install doc files
+#
+MKDIR = sh ../mkinstalldirs
+INSTALL_SH = sh ../install-sh -c
+INSTALL_DATA_SH = ${INSTALL_SH} -m 644
+docdir = ${prefix}/share/doc/ipmiutil-${version}
+etcdir = /etc
+datato = ${DESTDIR}${datadir}/ipmiutil
+cronto = ${DESTDIR}${etcdir}/cron.daily
+manto = ${DESTDIR}${mandir}/man8
+varto = ${DESTDIR}/var/lib/ipmiutil
+all: all-am
+
+.SUFFIXES:
+$(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 \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign doc/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
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$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
+installdirs:
+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:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_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-am: clean-generic clean-libtool mostlyclean-am
+
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-exec install-exec-am \
+ install-info install-info-am install-man install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \
+ uninstall-info-am
+
+
+all:
+
+clean:
+
+clobber:
+
+distclean:
+
+check:
+
+install:
+ $(MKDIR) ${manto}
+ $(MKDIR) ${datato}
+ $(MKDIR) ${varto}
+ ${INSTALL_DATA_SH} isel.8 ${manto}
+ ${INSTALL_DATA_SH} isensor.8 ${manto}
+ ${INSTALL_DATA_SH} ireset.8 ${manto}
+ ${INSTALL_DATA_SH} ialarms.8 ${manto}
+ ${INSTALL_DATA_SH} iwdt.8 ${manto}
+ ${INSTALL_DATA_SH} ifru.8 ${manto}
+ ${INSTALL_DATA_SH} ilan.8 ${manto}
+ ${INSTALL_DATA_SH} iserial.8 ${manto}
+ ${INSTALL_DATA_SH} icmd.8 ${manto}
+ ${INSTALL_DATA_SH} igetevent.8 ${manto}
+ ${INSTALL_DATA_SH} ihealth.8 ${manto}
+ ${INSTALL_DATA_SH} ipmiutil.8 ${manto}
+ ${INSTALL_DATA_SH} isol.8 ${manto}
+ ${INSTALL_DATA_SH} idiscover.8 ${manto}
+ ${INSTALL_DATA_SH} ievents.8 ${manto}
+ ${INSTALL_DATA_SH} iconfig.8 ${manto}
+ ${INSTALL_DATA_SH} ipmi_port.8 ${manto}
+ ${INSTALL_DATA_SH} ipicmg.8 ${manto}
+ ${INSTALL_DATA_SH} ifirewall.8 ${manto}
+ ${INSTALL_DATA_SH} ifwum.8 ${manto}
+ ${INSTALL_DATA_SH} ihpm.8 ${manto}
+ ${INSTALL_DATA_SH} isunoem.8 ${manto}
+ ${INSTALL_DATA_SH} itsol.8 ${manto}
+ ${INSTALL_DATA_SH} iekanalyzer.8 ${manto}
+ ${INSTALL_DATA_SH} idelloem.8 ${manto}
+ ${INSTALL_DATA_SH} idcmi.8 ${manto}
+ ${INSTALL_DATA_SH} ismcoem.8 ${manto}
+ ${INSTALL_DATA_SH} bmclanpet.mib ${datato}
+ cd ${manto}; gzip -f *.8
+# 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:
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..832b0d1
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,61 @@
+#!/bin/sh
+# Makefile to build/install doc files
+#
+MKDIR = sh ../mkinstalldirs
+INSTALL_SH = sh ../install-sh -c
+INSTALL_DATA_SH = ${INSTALL_SH} -m 644
+prefix = /usr
+
+datadir = ${prefix}/share
+mandir = ${prefix}/share/man
+docdir = ${prefix}/share/doc/ipmiutil-${version}
+etcdir = /etc
+datato = ${DESTDIR}${datadir}/ipmiutil
+cronto = ${DESTDIR}${etcdir}/cron.daily
+manto = ${DESTDIR}${mandir}/man8
+varto = ${DESTDIR}/var/lib/ipmiutil
+
+all:
+
+clean:
+
+clobber:
+
+distclean:
+
+check:
+
+install:
+ $(MKDIR) ${manto}
+ $(MKDIR) ${datato}
+ $(MKDIR) ${varto}
+ ${INSTALL_DATA_SH} isel.8 ${manto}
+ ${INSTALL_DATA_SH} isensor.8 ${manto}
+ ${INSTALL_DATA_SH} ireset.8 ${manto}
+ ${INSTALL_DATA_SH} ialarms.8 ${manto}
+ ${INSTALL_DATA_SH} iwdt.8 ${manto}
+ ${INSTALL_DATA_SH} ifru.8 ${manto}
+ ${INSTALL_DATA_SH} ilan.8 ${manto}
+ ${INSTALL_DATA_SH} iserial.8 ${manto}
+ ${INSTALL_DATA_SH} icmd.8 ${manto}
+ ${INSTALL_DATA_SH} igetevent.8 ${manto}
+ ${INSTALL_DATA_SH} ihealth.8 ${manto}
+ ${INSTALL_DATA_SH} ipmiutil.8 ${manto}
+ ${INSTALL_DATA_SH} isol.8 ${manto}
+ ${INSTALL_DATA_SH} idiscover.8 ${manto}
+ ${INSTALL_DATA_SH} ievents.8 ${manto}
+ ${INSTALL_DATA_SH} iconfig.8 ${manto}
+ ${INSTALL_DATA_SH} ipmi_port.8 ${manto}
+ ${INSTALL_DATA_SH} ipicmg.8 ${manto}
+ ${INSTALL_DATA_SH} ifirewall.8 ${manto}
+ ${INSTALL_DATA_SH} ifwum.8 ${manto}
+ ${INSTALL_DATA_SH} ihpm.8 ${manto}
+ ${INSTALL_DATA_SH} isunoem.8 ${manto}
+ ${INSTALL_DATA_SH} itsol.8 ${manto}
+ ${INSTALL_DATA_SH} iekanalyzer.8 ${manto}
+ ${INSTALL_DATA_SH} idelloem.8 ${manto}
+ ${INSTALL_DATA_SH} idcmi.8 ${manto}
+ ${INSTALL_DATA_SH} ismcoem.8 ${manto}
+ ${INSTALL_DATA_SH} bmclanpet.mib ${datato}
+ cd ${manto}; gzip -f *.8
+
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644
index 0000000..a6825ce
--- /dev/null
+++ b/doc/Makefile.in
@@ -0,0 +1,383 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 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@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+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@
+subdir = doc
+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 =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+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@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GPL_CFLAGS = @GPL_CFLAGS@
+IA64_CFLAGS = @IA64_CFLAGS@
+INIT_DIR = @INIT_DIR@
+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@
+LDFLAGS = @LDFLAGS@
+LD_SAMX = @LD_SAMX@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_DIR = @LIB_DIR@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+OS_CFLAGS = @OS_CFLAGS@
+OS_DRIVERS = @OS_DRIVERS@
+OS_LFLAGS = @OS_LFLAGS@
+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@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHR_LINK = @SHR_LINK@
+STRIP = @STRIP@
+SUBDIR_S = @SUBDIR_S@
+SYSTEMD_DIR = @SYSTEMD_DIR@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+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@
+datadir = ${prefix}/share
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = ${prefix}/share/man
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = /usr
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+
+#!/bin/sh
+# Makefile to build/install doc files
+#
+MKDIR = sh ../mkinstalldirs
+INSTALL_SH = sh ../install-sh -c
+INSTALL_DATA_SH = ${INSTALL_SH} -m 644
+docdir = ${prefix}/share/doc/ipmiutil-${version}
+etcdir = /etc
+datato = ${DESTDIR}${datadir}/ipmiutil
+cronto = ${DESTDIR}${etcdir}/cron.daily
+manto = ${DESTDIR}${mandir}/man8
+varto = ${DESTDIR}/var/lib/ipmiutil
+all: all-am
+
+.SUFFIXES:
+$(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 \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign doc/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
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$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
+installdirs:
+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:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_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-am: clean-generic clean-libtool mostlyclean-am
+
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-exec install-exec-am \
+ install-info install-info-am install-man install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \
+ uninstall-info-am
+
+
+all:
+
+clean:
+
+clobber:
+
+distclean:
+
+check:
+
+install:
+ $(MKDIR) ${manto}
+ $(MKDIR) ${datato}
+ $(MKDIR) ${varto}
+ ${INSTALL_DATA_SH} isel.8 ${manto}
+ ${INSTALL_DATA_SH} isensor.8 ${manto}
+ ${INSTALL_DATA_SH} ireset.8 ${manto}
+ ${INSTALL_DATA_SH} ialarms.8 ${manto}
+ ${INSTALL_DATA_SH} iwdt.8 ${manto}
+ ${INSTALL_DATA_SH} ifru.8 ${manto}
+ ${INSTALL_DATA_SH} ilan.8 ${manto}
+ ${INSTALL_DATA_SH} iserial.8 ${manto}
+ ${INSTALL_DATA_SH} icmd.8 ${manto}
+ ${INSTALL_DATA_SH} igetevent.8 ${manto}
+ ${INSTALL_DATA_SH} ihealth.8 ${manto}
+ ${INSTALL_DATA_SH} ipmiutil.8 ${manto}
+ ${INSTALL_DATA_SH} isol.8 ${manto}
+ ${INSTALL_DATA_SH} idiscover.8 ${manto}
+ ${INSTALL_DATA_SH} ievents.8 ${manto}
+ ${INSTALL_DATA_SH} iconfig.8 ${manto}
+ ${INSTALL_DATA_SH} ipmi_port.8 ${manto}
+ ${INSTALL_DATA_SH} ipicmg.8 ${manto}
+ ${INSTALL_DATA_SH} ifirewall.8 ${manto}
+ ${INSTALL_DATA_SH} ifwum.8 ${manto}
+ ${INSTALL_DATA_SH} ihpm.8 ${manto}
+ ${INSTALL_DATA_SH} isunoem.8 ${manto}
+ ${INSTALL_DATA_SH} itsol.8 ${manto}
+ ${INSTALL_DATA_SH} iekanalyzer.8 ${manto}
+ ${INSTALL_DATA_SH} idelloem.8 ${manto}
+ ${INSTALL_DATA_SH} idcmi.8 ${manto}
+ ${INSTALL_DATA_SH} ismcoem.8 ${manto}
+ ${INSTALL_DATA_SH} bmclanpet.mib ${datato}
+ cd ${manto}; gzip -f *.8
+# 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:
diff --git a/doc/UserGuide b/doc/UserGuide
new file mode 100644
index 0000000..d1b1090
--- /dev/null
+++ b/doc/UserGuide
@@ -0,0 +1,6497 @@
+
+ IPMIUTIL USER GUIDE
+ VERSION 2.9.3
+ An easy-to-use IPMI server management utility
+
+
+------------------------
+ CONTENTS
+------------------------
+1.0 Overview
+ 1.1 Features
+2.0 Dependencies
+ 2.1 Configuration
+ 2.2 References
+3.0 Utility Man Pages
+ 3.1 IPMIUTIL (ipmiutil)
+ 3.2 IALARMS (ipmiutil alarms)
+ 3.3 ICMD (ipmiutil cmd)
+ 3.4 ICONFIG (ipmiutil config)
+ 3.5 IDISCOVER (ipmiutil discover)
+ 3.6 IEVENTS (ipmiutil events)
+ 3.7 IFRU (ipmiutil fru)
+ 3.8 IGETEVENT (ipmiutil getevt)
+ 3.9 IHEALTH (ipmiutil health)
+ 3.10 ILAN (ipmiutil lan)
+ 3.11 IRESET (ipmiutil reset)
+ 3.12 ISEL (ipmiutil sel)
+ 3.13 ISENSOR (ipmiutil sensor)
+ 3.14 ISERIAL (ipmiutil serial)
+ 3.15 ISOL (ipmiutil sol)
+ 3.16 IWDT (ipmiutil wdt)
+ 3.17 IFRUSET (ifruset)
+ 3.18 IPMI_PORT (ipmi_port)
+ 3.19 IPICMG (ipmiutil picmg)
+ 3.20 IFIREWALL (ipmiutil ifirewall)
+ 3.21 IFWUM (ipmiutil fwum)
+ 3.22 IHPM (ipmiutil hpm)
+ 3.23 ISUNOEM (ipmiutil sunoem)
+ 3.24 IEKANALYZER (ipmiutil ekanalyzer, deprecated)
+ 3.25 ITSOL (ipmiutil tsol)
+ 3.26 IDELLOEM (ipmiutil delloem)
+ 3.27 IDCMI (ipmiutil dcmi)
+ 3.28 ISMCOEM (ipmiutil smcoem)
+ 3.29 ISELTIME (iseltime)
+4.0 Use Cases
+ 4.1 Usage of IPMI utilities for sensor thresholds
+ 4.2 Usage to configure a system for IPMI LAN
+ 4.3 Usage of IPMI utilities for Automated IPMI LAN configuration
+ 4.4 Usage of IPMI utilities to Set Watchdog timer
+ 4.5 Usage of kernel panic handler code
+ 4.6 Interpreting BMC LAN SNMP Traps from Platform Events
+ 4.7 Interpreting newer PECI sensors for CPU Thermal Margin
+ 4.8 How to configure a system for IPMI Serial-Over-LAN Console
+ 4.9 Using ipmiutil Library APIs for custom programs
+ 4.10 How to configure a system for SNMP Traps via IPMI PEF rules
+5.0 IPMI Utilities on Windows
+ 5.1 Windows Install Instructions
+ 5.2 Windows Build Instructions
+ 5.3 Windows Command Usage
+6.0 Sample output
+7.0 Problems
+ 7.1 Error Return Codes
+ 7.2 IPMI Completion Codes
+8.0 Building IPMI Utilities
+ 8.1 Building ipmiutil on Linux
+ 8.2 Building ipmiutil on Windows
+ 8.3 Building ipmiutil on Solaris
+ 8.4 Building ipmiutil on FreeBSD
+ 8.5 Building ipmiutil on ARM (Android)
+9.0 IPMIUtil Library APIs
+10.0 Related Information
+ 9.1 History
+ 9.2 Links
+
+
+
+------------------------
+1.0 OVERVIEW
+------------------------
+
+The IPMI Specification provides a standard way to do both simple and complex
+server management functions. Everything from remote reset/power-off to sending
+an SNMP alert from a sensor event even if the OS is down. Being able to
+perform these tasks in Baseboard Management Controller (BMC) firmware allows
+OS-independent management. What many integrators need, however, is a set of
+utilities and/or sample code to perform these functions within their
+enterprise management subsystem without a learning curve.
+
+The IPMI Management Utilities project provides a series of utilities that
+perform common IPMI server management functions, such as viewing the firmware
+log, or configuring the BMC LAN & PEF features.
+The utilities are designed for end-users, so that they should not require
+intimate knowledge of how to build IPMI commands. Each of the utilities detects or reasonably assigns default values so that a working configuration can be
+easily obtained. More detailed options allow changes to these default values.
+These utilities can be used separately, or merged with a larger server
+management subsystem. The source license is BSD and ipmiutil compiles under
+Linux (Makefile) and Windows (buildwin.cmd). There are also corresponding
+SA Forum HPI standard utilities that run with two different HPI
+implementations, including OpenHPI. These were the basis of the current
+openhpi/clients.
+
+This project includes both IPMI utilities and a kernel patch for
+panic handler enhancements. See the project web site for binaries
+and documentation at http://ipmiutil.sourceforge.net.
+
+The ipmiutil IPMI utilities below allow the user to access the firmware
+System Event Log and configure the Platform Event Filter table for the new
+'OS Critical Stop' records, as well as other common IPMI system management
+functions.
+
+ipmiutil - a meta-command to invoke all of the below as sub-commands
+ievents - a standalone utility to interpret IPMI and PET event data
+isel - show/set the firmware System Event Log records
+isensor - show Sensor Data Records, sensor readings, and thresholds
+ireset - cause the BMC to hard reset or power down the system
+ilan - show and configure the BMC LAN port and Platform Event Filter
+ table to allow BMC LAN alerts from firmware events and
+ OS Critical Stop messages,
+iserial - show and configure the BMC Serial port for various modes,
+ such as Terminal Mode.
+ifru - show the FRU chassis, board, and product inventory data,
+ and optionally write a FRU asset tag.
+ialarms - show and set front panel alarms (LEDs and relays)
+iwdt - show and set watchdog timer parameters
+igetevent - receive any IPMI events and display them
+ihealth - check and report the basic health of the IPMI BMC
+iconfig - list/save/restore the BMC configuration parameters
+icmd - send specific IPMI commands to the BMC,
+ mainly for testing and debug purposes.
+idiscover - discover the available IPMI LAN nodes on a subnet
+isol - start/stop an IPMI Serial-Over-LAN Console session
+ipicmg - show/set the IPMI PICMG parameters
+ifirewall - show/set the IPMI firmware firewall configuration
+iekanalyzer - run FRU-EKeying analyzer on FRU files
+ifwum - OEM firmware update manager extensions
+ihpm - HPM firmware update manager extensions
+isunoem - Sun OEM functions
+idelloem - Dell OEM functions
+itsol - Tyan SOL console start/stop session
+idcmi - get/set DCMI parameters, if supporting the DCMI spec
+
+Other supporting files:
+checksel = cron script using ipmiutil sel to check the SEL, write new
+ events to the OS system log, and clear the SEL if nearly full.
+ipmi_port = daemon to bind the RMCP port and sleep to prevent
+ Linux portmap from stealing the RMCP port
+ipmi_port.sh = init script to reserve the RMCP port from portmap,
+ this also restores saved sensor thresholds, if any.
+ipmiutil_wdt = init script to restart watchdog timer every 60 sec via cron
+ipmiutil_asy = init script runs 'ipmiutil getevt -a' for remote shutdown
+ipmiutil_evt = init script runs 'ipmiutil getevt -s' for monitoring events
+evt.sh = sample script which can be invoked by ipmiutil_evt
+ipmi_if.sh = script using dmidecode to determine the IPMI Interface Type
+bmclanpet.mib = SNMP MIB for BMC LAN Platform Event Traps
+test/* = scripts and utilities used in testing ipmiutil/panicsel
+kern/* = kernel patches for panic handling
+
+The kernel panic handler patch (kern/bmcpanic.patch) adds additional
+features to the Linux Panic Handler so that more information can be
+saved and passed along if a Linux panic condition occurs.
+bmc_panic features:
+
+ 1. Write an OS Critical Stop event to firmware System Event Log (SEL)
+ This is in bmcpanic.patch, in OpenIPMI and in Intel IMB.
+ 2. Send SNMP trap via BMC LAN Alerting mechanism
+ Accomplished by configuring the BMC with 'ipmiutil lan'.
+ 3. Turn on the Critical Alarm LED on the Telco Alarms Panel
+ This is in bmcpanic.patch, but not in OpenIPMI due to
+ platform-specific issues with the alarms panel.
+
+The kernel portion of this, except item 3, is now included in the OpenIPMI
+project with the CONFIG_IPMI_PANIC_EVENT option, and the OpenIPMI
+driver has merged into Linux kernel 2.4.21 and beyond.
+The latest version of the OpenIPMI driver can be obtained from
+http://openipmi.sourceforge.net.
+This patch is also included in the Intel IMB IPMI driver v28 and greater,
+for any Linux kernel. This Intel IMB IPMI driver can be obtained from
+http://downloadcenter.intel.com/Product_Search.aspx?Prod_nm=imbsrc or
+a copy is cached on http://ipmiutil.sf.net also.
+
+
+------------------------
+1.1 FEATURES
+------------------------
+
+These are the key strengths, user features and functions that are
+supported by ipmiutil.
+
+Key Strengths = supports any IPMI server platforms,
+ top-down user-friendly IPMI functions,
+ detection, portability,
+ incorporates fixes and new features quickly
+Target Market = Administrators, Developers, and OEMs
+OS Support = Linux, Windows, Solaris, and FreeBSD
+ (supports Windows natively for remote or local interface)
+License = BSD
+Drivers = For Linux: openipmi, imb, valinux ipmikcs, lan, lanplus,
+ landesk, and driverless direct KCS & SSIF
+ For Windows: Intel IMB and Microsoft IPMI drivers
+ For Solaris: bmc
+ For FreeBSD: openipmi, driverless KCS or SSIF
+LEDs = Show/set ATCA LEDs, set identify LED, Intel Telco Alarm LEDs
+health = show overall health and product information
+discovery = find all IPMI LAN servers on a given subnet
+fru = Display all FRU and SPD inventory data, also
+ Set some FRU product fields (asset tag, serial number)
+sensor = Show SDRs and sensor readings, also set sensor thresholds
+getevent = Receive any IPMI events and decode them,
+ The IPMI event monitoring service is automated in Linux via
+ the ipmiutil_evt init script.
+reset = IPMI local and remote reset/power-control,
+ IPMI boot device selection.
+remote IPMI = Perform an OS shutdown/restart request via IPMI LAN,
+soft-shutdown using ipmiutil getevt -a and invoking ipmiutil reset -o.
+ This async bridge service is automated in Linux via the
+ ipmiutil_asy init script.
+cmd = Execute raw IPMI commands locally or remotely
+lan = Show/set IPMI LAN and PEF configuration parameters,
+ adds more PEF rules, or can add a custom PEF rule
+serial = Show/set IPMI serial configuration parameters
+sel = Show decoded System Event Log records, clear SEL,
+ see the checksel cron script to automate SEL management.
+sol console = Start/stop an SOL console session
+watchdog = Show, set, and reset the IPMI watchdog timer and its actions,
+ The watchdog timer service can be automated in Linux via the
+ ipmiutil_wdt init script.
+save/restore = save and restore all BMC configuration parameters
+ievents = Standalone app to decode IPMI or PET event data,
+ especially useful at the management station for interpreting
+ IPMI PET SNMP traps. See also SNMP PET MIB (bmclanpet.mib).
+picmg = Support IPMI PICMG functions
+firewall = Support IPMI firmware firewall functions
+
+Through various services, ipmiutil allows automatic management of common
+IPMI tasks:
+ipmi_port = Automatically prevent Linux port mapper from stealing
+ the RMCP port 623 used by IPMI LAN firmware.
+checksel = a cron script to daily write new SEL records to syslog, and
+ clear the SEL if nearly full.
+ipmiutil_asy = A Linux init script using the ipmiutil getevt -a service to
+ enable receiving soft-shutdown requests from ipmiutil reset -o
+ipmiutil_wdt = A Linux init script to reset the watchdog timer every 60 sec.
+ipmiutil_evt = A Linux init script using the ipmiutil getevt -s service to
+ monitor IPMI events, log them, and optionally run a script.
+
+
+
+------------------------
+2.0 DEPENDENCIES
+------------------------
+
+The IPMI Utilities will run on Linux, Windows Solaris, or FreeBSD, and should
+be portable to other OSs, if an IPMI driver for that OS can be obtained.
+
+The IPMI Utilities and Panic Handler Enhancements currently work with
+platforms that support the IPMI standard. If the platform does not
+support IPMI, these changes are inert. The Service Availability Forum
+has developed a Hardware Platform Interface (HPI) specification that
+can be used to group IPMI and other system management interfaces
+together. A set of comparable HPI utilities is included in the
+ipmiutil project source as hpiutil/*.
+
+The Panic Handler kernel enhancements (via kern/bmcpanic.patch) are now
+included in the Intel IMB driver v28 and later, and in the OpenIPMI driver
+via the CONFIG_IPMI_PANIC_EVENT and CONFIG_IPMI_PANIC_STRING parameters in
+the kernel config file (/usr/src/linux/.config) with kernels 2.4.21 or greater.
+
+If run locally, the ipmiutil utilities must be run as
+superuser/Administrator and an IPMI driver must be used.
+
+For Linux, these IPMI drivers are supported:
+ . the MontaVista OpenIPMI driver (/dev/ipmi0),
+ . the Intel IMB IPMI driver (/dev/imb, via 'ipmidrvr' or 'ipmi_imb'),
+ . the valinux IPMI Driver (/dev/ipmikcs),
+ . the LANDesk ldipmi daemon,
+ . or direct user-space I/Os to the IPMI KCS or SSIF/SMBus interfaces,
+ if no other driver is detected.
+
+For Windows, these drivers are supported:
+ . the Intel IMB IPMI driver (imbdrv.sys) for any Windows Server OS,
+ . the Microsoft IPMI driver (ipmidrv.sys) for Win2003R2 or Win2008.
+
+For Solaris, these drivers are supported:
+ . the Sun bmc driver (/dev/bmc) for Solaris 10 and greater
+
+For FreeBSD, these drivers are supported:
+ . the FreeBSD 7.x OpenIPMI driver port (kldload ipmi, /dev/ipmi0)
+ . direct user-space I/Os to the IPMI KCS or SSIF/SMBus interfaces
+
+Each of the IPMI management utilities will detect which IPMI driver
+is present, and in Linux, if none are found, it will attempt to use direct
+KCS or SSIF I/Os to communicate with the IPMI BMC.
+
+If using the IPMI LAN interface, neither the local or remote system requires
+any IPMI driver, but the remote target system must have had IPMI LAN enabled,
+(e.g. via ipmiutil lan) which is done locally on the target system.
+Note that the IPMI LAN session password is sent with either MD5 or MD2
+encryption by default.
+
+See http://openipmi.sourceforge.net for the OpenIPMI driver.
+See http://downloadcenter.intel.com/Product_Search.aspx?Prod_nm=imbsrc for Intel IMB driver
+See http://cvs.sf.net/cgi-bin/viewcvs.cgi/ipmitools/ipmitools/kernel/kcs/patches/2.4.x/ for the valinux driver.
+See http://www.landesk.com/ or the CD supplied with your server for LANDesk.
+
+List of companies that have adopted IPMI (over 198):
+ http://www.intel.com/design/servers/ipmi/adopterlist.htm
+
+Example IPMI Server Platforms tested with ipmiutil, by BMC manufacturer:
+ Intel RackMount Servers (various, both 32-bit and 64-bit)
+ Intel ATCA (MPCMM0001 and MPBL00xx)
+ Kontron CRMS servers and KTC5520
+ Dell PowerEdge 18xx, 19xx, 2800
+ SuperMicro with AOC-IPMI20 (by LMC)
+ SuperMicro with AOC-SIMSO (by Peppercon)
+ Sun (product id 0x4701)
+ Tyan (product id 0x14e9)
+ NSC (product id 0x4311, National SemiConductor)
+ NEC (product id 0x024b)
+ Tatung TS-2552 (product id 0x09f8)
+ AMI IPMI MegaRAC
+
+
+------------------------
+2.1 CONFIGURATION
+------------------------
+
+To find the base address of the IPMI KCS interface, or to find the IPMI
+SSIF/SMBus slave address, you can use the 'dmidecode' utility provided
+with most Linux distributions. See also http://www.nongnu.org/dmidecode.
+The ipmi_if.sh script can determine the IPMI Interface Type, and the
+resulting /usr/share/ipmiutil/ipmi_if.txt file can be edited if needed.
+The ipmiutil binary uses the same mechanism to detect the IPMI KCS or
+SSIF interface parameters by default if no driver is loaded.
+
+For some IPMI systems, a minimum firmware version may be needed to
+support the BMC LAN/PEF feature. On an Intel TSRLT2 system, for instance,
+these are the minimum levels:
+ BMC Firmware ver 54 or greater
+Systems with IPMI versions prior to 1.5 do not support BMC LAN or PEF features
+
+By default, the ipmiutil IPMI utilities rpm does not set the panic timeout.
+If a different kernel panic timeout is desired, add the kernel parameter
+"panic=10" in grub.conf/lilo.conf, or do "echo 10 >/proc/sys/kernel/panic"
+in one of the /etc/init.d scripts to set it to 10 seconds, for instance.
+
+The ipmiutil lan (ilan) utility can be used to configure the BMC LAN
+Alerting while the OS is running. It has additional PEF rules and LAN
+parameter detection logic beyond what most other utilities provide.
+
+The ipmiutil serial (iserial) utility is intended to configure the EMP
+serial port on the server for shared access between BMC/IPMI functions
+and BIOS Console Redirection. Some older platforms only support only Basic
+Mode for BMC/IPMI functions. Basic Mode requires a remote client application
+to utilize it (Windows ISC Console/DPC applet, or a special modified Linux
+telnet). There are many platforms which implement Terminal Mode via IPMI v1.5
+Appendix E to make remote management with character commands available
+on the serial port without a special remote client application.
+
+Notes about BMC Users:
+Most IPMI 1.5 systems support at least 3 users, numbered 1,2,3, where
+user 1 is the default and has a null username. Users 2 and 3 are
+alternate users whose usernames can be set. For ipmiutil, these are
+currently implemented by default as follows:
+user 1: used by default for BMC LAN and Serial (ilan & iserial)
+user 2: set for BMC LAN if ipmiutil lan -u is specified
+user 3: set for BMC Serial/EMP if ipmiutil serial -u is specified
+Also note that the -q option can be used to set different users by number.
+
+Note that the checksel script will be copied to /etc/cron.daily when
+the Linux ipmiutil rpm is installed, so that ipmiutil sel will automatically
+save SEL records to syslog and clear the SEL if it gets nearly full.
+If you do not want this to happen automatically, remove the checksel
+script from the /etc/cron.daily directory.
+
+In order for the ipmiutil sel -w function to work cleanly on a Windows system,
+the showselmsg.dll should be copied to %SystemRoot%\system32, and the
+showsel.reg should be run to set up the corresponding EventLog service
+registry values. See install.cmd to perform these functions.
+
+The BSD License in the COPYING file applies to all source files
+herein, except for
+ * util/md5.c (Aladdin unrestricted license, compatible with BSD)
+ * util/md2.h (GPL)
+ * util/ipmi_ioctls.h (GPL)
+While the BSD License allows code reuse in both open and non-open
+applications, the md2.h and ipmi_ioctls.h files would have to be removed
+if used in a non-open application. The default ipmiutil build omits GPL code.
+There is a ALLOW_GPL compile flag for this that is disabled by default, but
+can be enabled for open-source by running "./configure --enable-gpl".
+
+See the INSTALL file for build instructions for various configurations.
+
+
+------------------------
+2.2 REFERENCES
+------------------------
+
+The IPMI 1.5 spec, Table 36-3 defines the sensor types for SEL records,
+as used by ipmiutil sel.
+The IPMI 1.5 spec, Table 15-2 defines the Platform Event Filter table
+entries, as used by ipmiutil lan.
+The IPMI 1.5 spec, Table 19-4 defines the LAN Configuration Parameters,
+as used by ipmiutil lan.
+The IPMI 2.0 spec, Section 15 defines the Serial-Over-LAN functionality.
+
+The enterprises.3183 SNMP traps come from the BMC firmware, and are defined in
+bmclan*.mib files in the ipmiutil project. Details about the format of these
+Platform Event Traps are available in section 12.2 through 12.5 of the ISM
+(Intel Server Management) 5.x Technical Product Specification at
+http://www.intel.com/support/motherboards/server/isc/sb/cs-008024.htm
+
+The enterprises.343 SNMP traps come from ISM or SNMPSA and are defined in
+basebrd*.mib or mapbase*.mib files on the platform CD.
+The enterprises.412 SNMP traps come from ISM/DMTF, defined in dmtf*.mib files
+on the platform CD.
+
+
+------------------------
+3.0 UTILITY MAN PAGES
+------------------------
+
+
+--------------------------------------
+3.1 IPMIUTIL (ipmiutil)
+
+IPMIUTIL(8) IPMIUTIL(8)
+
+NAME
+ ipmiutil - a meta-command to invoke various IPMI functions.
+
+SYNOPSIS
+ ipmiutil <command> [-x -NUPREFJTVY] [other command options]
+
+DESCRIPTION
+ This utility performs various IPMI functions. Each of the individual
+ commands in the ipmiutil project can be invoked via this meta-command.
+ The <command> is one of the following:
+ alarms show/set the front panel alarm LEDs and relays
+ leds show/set the front panel alarm LEDs and relays
+ cmd send a specified raw IPMI command to the BMC
+ config list/save/restore BMC configuration parameters
+ dcmi get/set DCMI parameters
+ discover discover all IPMI servers on this LAN
+ ekanalyzer run FRU-EKeying analyzer on FRU files (deprecated, see fru)
+ events decode IPMI events and display them
+ firewall show/set firmware firewall functions
+ fru show decoded FRU inventory data, write asset tag
+ fwum OEM firmware update manager extensions
+ getevt get IPMI events and display them, event daemon
+ getevent get IPMI events and display them, event daemon
+ health check and show the basic health of the IPMI BMC
+ hpm HPM firmware update manager extensions
+ lan show/set IPMI LAN parameters and PEF table
+ picmg show/set picmg extended functions
+ reset cause the BMC to reset or power down the system
+ sel show/clear firmware System Event Log records
+ sensor show Sensor Data Records, readings, thresholds
+ serial show/set IPMI Serial & Terminal Mode parameters
+ sol start/stop an SOL console session
+ smcoem SuperMicro OEM functions
+ sunoem Sun OEM functions
+ delloem Dell OEM functions
+ tsol Tyan SOL console start/stop session
+ wdt show/set/reset the watchdog timer
+ For help on each command (e.g. ’sel’), enter:
+ ipmiutil sel -?
+ For man pages on each command, its man page is named "i<command>", or
+ refer to SEE ALSO below.
+
+ This utility can use either the /dev/ipmi0 driver from OpenIPMI, the
+ /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+ direct user-space IOs, or the IPMI LAN interface if -N is used.
+
+
+OPTIONS
+ Command options are described in the man page for each command. Below
+ are a few of the common options.
+
+ -x Causes extra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+EXAMPLES
+ ipmiutil sel
+ Shows the IPMI System Event Log entries.
+
+ ipmiutil wdt
+ Shows the watchdog timer values.
+
+
+
+SEE ALSO
+ ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifirewall(8)
+ ifru(8) ifruset(8) ifwum(8) igetevent(8) ihealth(8) ihpm(8) ilan(8)
+ ipicmg(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) isunoem(8)
+ iwdt(8) ipmiutil(8) ipmi_port(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.2 IALARMS (ipmiutil alarms)
+
+IALARMS(8) IALARMS(8)
+
+
+
+NAME
+ ipmiutil_alarms - display and set alarm indicators
+
+SYNOPSIS
+ ipmiutil alarms [-abcdimnoprx -N node -U user -P/-R pswd -EFJTVY]
+
+
+DESCRIPTION
+ ipmiutil alarms is a program that uses IPMI commands to display and set
+ alarm indicators, which are usually LEDs on the system chassis front
+ panel. This utility can use either the /dev/ipmi0 driver from
+ OpenIPMI, the /dev/imb driver from Intel, the /dev/ipmikcs driver from
+ valinux, direct user-space IOs, or the IPMI LAN interface if -N. Note
+ that a LAN user must have Administrative privileges to read or write
+ the alarm LEDs.
+
+ Note that this utility may not be the only logic setting alarm states.
+ The BMC firmware, system management software, or cluster fault manager
+ may also want to set alarm states. Intel provides a Telco Alarms Man-
+ ager API which presents a consolidated interface for all alarm manage-
+ ment applications.
+
+
+OPTIONS
+ Command line options are described below.
+
+ -r Read-only. Show the alarms status, but do not set any states.
+ This is also the default mode if no parameters are specified.
+
+ -iN Sets the Chassis Identify feature, which can be an LED or some
+ other alarm. If N=0, turn off the Chassis ID, otherwise turn
+ the ID on for N seconds. N=255 will turn on the ID indefi-
+ nitely, if it is IPMI 2.0.
+
+ -aN Sets Disk A Fault LED. If N=0, turn it off. If N=1, turn it
+ on. Used only for TIGPT1U platform.
+
+ -bN Sets Disk B Fault LED. If N=0, turn it off. If N=1, turn it
+ on. Used only for TIGPT1U platform.
+
+ -dXN Sets Disk X Fault LED, where X=0-6. If N=0, turn it off. If
+ N=1, turn it on. Used only for NSC2U platform.
+
+ -cN Sets the Critical Alarm. If N=0, turn it off. If N=1, turn it
+ on.
+
+ -mN Sets the Major Alarm. If N=0, turn it off. If N=1, turn it on.
+
+ -nN Sets the Minor Alarm. If N=0, turn it off. If N=1, turn it on.
+
+ -pN Sets the Power Alarm. If N=0, turn it off. If N=1, turn it on.
+ 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. Refer
+ to the system Technical Product Specification for System Faults.
+
+ -o Sets all alarms off, including the Chassis ID.
+
+ -x Causes extra debug messages to be displayed.
+
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use this IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5,
+ 4=Straight Password, 5=OEM.
+
+ -V Use this IPMI LAN privilege level. 1=Callback level, 2=User
+ level, 3=Operator level, 4=Administrator level (default), 5=OEM
+ level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+
+SEE ALSO
+ ipmiutil(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifru(8)
+ igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.3 ICMD (ipmiutil cmd)
+
+ICMD(8) ICMD(8)
+
+
+
+NAME
+ ipmiutil_cmd - a tool to send specific IPMI commands via the command
+ line.
+
+
+SYNOPSIS
+ ipmiutil cmd [-qsx -NUPREFJTVY] bus rsSa netFn/lun cmd [data bytes]
+
+
+DESCRIPTION
+ This ipmiutil cmd tool sends specific IPMI commands to the firmware.
+ The commands are composed as hex values on the command line. This tool
+ was written to allow in-band use to match the DOS CMDTOOL.EXE or IPMI-
+ TOOL.EXE program which is distributed with many Intel servers. Certain
+ scripts or pre-written commands may have been supplied for the DOS tool
+ that can now be used while the system is running Linux or Windows.
+
+ This utility can use either the /dev/ipmi0 driver from OpenIPMI, the
+ /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+ direct user-space IOs, or the IPMI LAN interface if -N.
+
+ This tool should only be used if you are familiar with the IPMI 1.5
+ specification, or you have specific pre-written commands to send.
+
+
+
+OPTIONS
+ Command line options are described below.
+
+ -q Quiet mode. Show only minimal header information.
+
+ -s Skips the GetDeviceID command
+
+ -x Causes extra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+PARAMETERS
+ The following parameters are used by icmd. Each is represented as a
+ two-digit hex byte. The parameters have no default values.
+
+
+ bus This byte contains the bus number for this command, usually 00.
+
+
+ rsSa This is the resource slave address, usually 0x20 for the BMC.
+
+
+ netFn/lun
+ This byte combines the net Function and Lun. The 2 low-order
+ bits are the Lun and the 6 high-order bits are the net Function.
+ This representation is consistent with the DOS CMDTOOL/IPMITOOL.
+
+
+ cmd This byte contains the IPMI command.
+
+
+ [data bytes]
+ This is a sequence of zero to 16 bytes that represent data bytes
+ specific to this command.
+
+
+EXAMPLES
+ icmd 00 20 18 01
+ Sends the GetDevice ID command to the BMC.
+
+ icmd 00 20 28 43 00 00 ff ff 00 ff
+ Sends a Get SEL entry command for the last entry in the firmware log.
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) idiscover(8) ievents(8) ifru(8)
+ igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.4 ICONFIG (ipmiutil config)
+
+ICONFIG(8) ICONFIG(8)
+
+
+
+NAME
+ ipmiutil_config - list, save, and restore BMC configuration parameters
+
+SYNOPSIS
+ ipmiutil config [-lpxLNUPREFJTVY] [-r file] [-s file]
+
+
+DESCRIPTION
+ ipmiutil config is a program that uses an IPMI driver to send IPMI com-
+ mands which list, save and restore BMC configuration parameters for
+ LAN, Serial, PEF, SOL, User, Channel. This combines the functionality
+ of ipmiutil lan (ilan) and ipmiutil serial (iserial). Note that some
+ of the LAN parameters cannot be restored remotely over the IPMI LAN,
+ changing the configuration that is in use. This utility can use either
+ the /dev/ipmi0 driver from OpenIPMI, the /dev/imb driver from Intel,
+ the /dev/ipmikcs driver from valinux, direct user-space IOs, or the
+ IPMI LAN interface if -N.
+
+
+OPTIONS
+ Command line options are described below.
+
+
+ -l Lists BMC configuration parameters with a keyword, index, and
+ its hex values. This is the default behavior if no options are
+ specified.
+
+ -r config_file
+ Restores BMC configuration from config_file, which was produced
+ with -s below.
+
+ -s config_file
+ Saves BMC configuration to config_file. This file could be
+ edited, in certain cases, such as to vary the BMC IP address
+ (LanParam 3), or to use the UserPassword records. Note that
+ lines beginning with ’#’ are comments and are ignored. For
+ editing UserPassword records, convert your text value to hex
+ format; for example "echo ’mypassword’ |od -t x1", and leave off
+ the trailing 0a.
+
+ -x Causes extra debug messages to be displayed.
+
+ -p password_to_set
+ This specifies the firmware password to set for BMC LAN access
+ for all users during the restore. If not specified, the pass-
+ word configuration will not be changed, unless a valid UserPass-
+ word record is present in the file to be restored. Note that
+ user passwords are write-only via standard IPMI commands.
+
+ -L lan_ch_num
+ This specifies the IPMI LAN channel number used for BMC LAN.
+ This varies by platform, and can be found in the platform tech-
+ nical specifications. By default, bmcconfig scans all IPMI
+ channels to find a LAN channel for BMC LAN.
+
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) icmd(8) idiscover(8) ievents(8) ifru(8)
+ igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.5 IDISCOVER (ipmiutil discover)
+
+IDISCOVER(8) IDISCOVER(8)
+
+
+
+NAME
+ ipmiutil_discover - discover IPMI LAN-enabled nodes
+
+SYNOPSIS
+ idiscover [-abegisx]
+
+
+DESCRIPTION
+ idiscover is a program that uses IPMI LAN commands to discover any
+ nodes on the LAN that are available, by probing the RMCP port (623.)
+ on those nodes. This utility uses IPMI LAN, so no IPMI drivers are
+ needed. There are three methods that can be used:
+ -a = broadcast RMCP ping method (default)
+ -g = GetChannelAuthCap command method
+ else = specific RMCP ping method
+
+ A beginning IP address can be specified with -b for broadcast and spe-
+ cific methods. An ending IP can be specified for non-broadcast methods.
+
+
+OPTIONS
+ Command line options are described below.
+
+ -a All nodes, use the broadcast ping method. This is the default
+ if no options are specified. This will detect the first enabled
+ ethernet interface, and defaults to the broadcast address
+ x.x.x.255 (where x.x.x.x is IP address) unless -b is used to
+ specify otherwise.
+
+ -b <ip>
+ Beginning IP address, required, unless using broadcast with
+ defaults. This could be a specific IP address, or a broadcast
+ address, ending in 255, if the broadcast method (-a) is used.
+
+ -e <ip>
+ Endign IP address of the range. Not used for broadcast method.
+ If this is not specified, a range of one IP address matching the
+ beginning IP is assumed.
+
+ -g Use the GetChannelAuthenticationCapabilities command method over
+ IPMI LAN instead of the RMCP ping. Not compatible with broad-
+ cast. This may be useful if the vendor BMC does not support
+ RMCP ping for some reason.
+
+ -i eth0
+ The interface name to use when sending the probes. The default
+ is to detect the first enabled ethernet interface (e.g. eth0).
+
+ -m shows MAC address. Uses the broadcast ping method, but uses a
+ raw socket so that the MAC address can be displayed. This
+ detects the first enabled ethernet interface, and defaults to
+ the broadcast address 255.255.255.255 like -a. Using -m with
+ raw sockets requires root privilege.
+
+ -r N Repeat the ping N times to each node. Default is to send 1 ping
+ per node.
+
+ -x Causes extra debug messages to be displayed.
+
+
+
+EXAMPLES
+ idiscover -a -b 192.168.1.255
+ Sends a broadcast RMCP ping to discover IPMI LAN nodes on the specified
+ subnet.
+
+ idiscover -b 192.168.1.100 -e 192.168.1.254
+ Sends RMCP pings to a range of IP addresses.
+
+ idiscover -g -b 192.168.1.100 -e 192.168.1.254
+ Sends GetChannelAuthCap commands to a range of IP addresses.
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) ievents(8) ifru(8)
+ igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.6 IEVENTS (ipmiutil events)
+
+IEVENTS(8) IEVENTS(8)
+
+
+
+NAME
+ ievents - decode IPMI and PET event data
+
+SYNOPSIS
+ ievents [-bfhnprsx] 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10
+
+
+DESCRIPTION
+ ievents is a standalone utility delivered with ipmiutil, used to inter-
+ pret raw hex data from IPMI events or from IPMI PET SNMP trap varbind
+ data. This utility uses the same interpretation logic as is used by
+ "ipmiutil sel" (showsel) and "ipmiutil getevt" (getevents).
+
+ The data bytes in the input are always assumed to be in hex form.
+
+ This could be useful if a utility other than "ipmiutil sel" were used
+ to obtain IPMI SEL records or events and interpretation is needed.
+
+ This would also be needed at an enterprise management station to inter-
+ pret the PET SNMP trap hex data into human-readable form, see option
+ -p.
+
+
+OPTIONS
+ -b bin_file
+ Interpret a file containing raw binary/hex SEL data dumped in
+ binary form, such as that produced by "ipmitool sel writeraw
+ bin_file". Each set of 16 bytes in the file will be interpreted
+ as an IPMI event. (same as -h)
+
+
+ -f sel_file
+ Interpret a file containing raw ascii text SEL data captured
+ with ipmiutil sel -r, or some other similar utility. Each line
+ in the file should be in this form, with no leading spaces:
+ 04 00 02 76 a9 4a 47 20 00 04 10 09 6f 42 0f ff
+ If this option is not specified, the default is to use the 16
+ bytes taken from the command-line arguments. (same as -r)
+
+
+ -h bin_file
+ Interpret a file containing raw binary/hex SEL data dumped in
+ binary form, such as that produced by "ipmitool sel writeraw
+ bin_file". Each set of 16 bytes in the file will be interpreted
+ as an IPMI event. (same as -b)
+
+
+ -n This option generates a New IPMI platform event, using 9 bytes
+ of input. The input bytes are the same as the last 9 bytes of
+ an IPMI event.
+
+
+ -p Decode as PET event bytes, where the input is 34 PET hex data
+ bytes, skipping the first 8 of the 47-byte PET data. The
+ default without -p assumes that the input is a 16-byte IPMI
+ event.
+
+
+ -r sel_file
+ Interpret a file containing raw ascii text SEL data captured
+ with ipmiutil sel -r, or some other similar utility. (same as
+ -f)
+
+
+ -s sensor_file
+ Sensor file with the output of "ipmiutil sensor", used to get
+ the PET sensor_type from the sensor_num. The default is
+ /usr/share/ipmiutil/sensor_out.txt as generated during the
+ ipmiutil package installation. This is only needed with PET
+ interpretation (-p).
+
+
+ -x show eXtra debug messages
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ifru(8)
+ igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.7 IFRU (ipmiutil fru)
+
+IFRU(8) IFRU(8)
+
+
+
+NAME
+ ipmiutil_fru - show Field Replacable Unit configuration data
+
+SYNOPSIS
+ ipmiutil fru [-abcdeikmsvx -N node -U user -P/-R pswd -EFJTVY]
+
+
+DESCRIPTION
+ ipmiutil fru is a program that uses IPMI commands to show FRU configu-
+ ration data and optionally write an asset tag string into the FRU data.
+ Setting the asset tag is a function that can be used to uniquely iden-
+ tify the unit, even if the storage devices are removed or changed.
+ This utility can use either the /dev/ipmi0 driver from OpenIPMI, the
+ /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+ direct user-space IOs, or the IPMI LAN interface if -N.
+
+
+OPTIONS
+ Command line options are described below.
+
+ -a asset_string
+ This option specifies an asset tag string to be written to the
+ baseboard FRU Product area. The asset tag length is limited by
+ the existing FRU Product data, but is usually allowed up to 16
+ characters. The default is to not modify this FRU field.
+
+ -b Only show the Baseboard FRU data. The default behavior is to
+ also scan for any SDR FRU data or DIMM SPD data referenced by
+ the SDRs.
+
+ -c Show FRU output in a canonical format, with a default delimiter
+ of '|'.
+
+ -d file
+ Dump binary FRU data to the specified file.
+
+ -e Show Every FRU output in a bladed chassis, including those under
+ child MCs. The default is to show FRUs referred to by just the
+ target MC.
+
+ -i 00 This option specifies a specific FRU ID to show. The input
+ value should be in hex (0b, 1a, etc.), as shown from the sensor
+ SDR output. By default, all FRU IDs that are specified in the
+ FRU locator SDRs are shown.
+
+ -k <setsn | setmfgdate | nextboot>
+ These Kontron OEM functions set FRU data based on existing data
+ stored elsewhere. The setsn option sets the FRU Board and Prod-
+ uct serial number, and the setmfgdate option sets the FRU Board
+ Mfg DateTime. The nextboot option specifies the boot device for
+ the next boot: BIOS, FDD, HDD, CDROM, or network. These options
+ are only supported on Kontron ATCA boards which have this func-
+ tionality.
+
+ -m 002000
+ Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00). This
+ could be used for PICMG or ATCA blade systems. The trailing
+ character, if present, indicates SMI addressing if ’s’, or IPMB
+ addressing if ’i’ or not present.
+
+ -s serial_num
+ This option specifies a serial number string to be written to
+ the baseboard FRU Product area. The serial number can be any
+ string up to 16 characters. The default is to not modify this
+ FRU field.
+
+ -v prod_ver
+ This option specifies a product version number string to be
+ written to the baseboard FRU Product area. The version number
+ can be any string up to 16 characters. The default is to not
+ modify this FRU field.
+
+ -x Causes eXtra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8)
+ igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.8 IGETEVENT (ipmiutil getevt)
+
+IGETEVENT(8) IGETEVENT(8)
+
+
+
+NAME
+ ipmiutil_getevt - wait for IPMI events
+
+SYNOPSIS
+ ipmiutil getevt [-abosx -t secs -N node -U user -P/-R pswd -EFJTVY]
+
+
+DESCRIPTION
+ ipmiutil getevt is a program that uses IPMI commands to wait for IPMI
+ events sent from the BMC firmware. These events are also sent to the
+ IPMI System Event Log (SEL). This utility can use either the
+ /dev/ipmi0 driver from OpenIPMI, the /dev/imb driver from Intel, the
+ /dev/ipmikcs driver from valinux, direct user-space IOs, or the IPMI
+ LAN interface if -N.
+
+ 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. 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:
+ 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.
+ This is the only method supported over IPMI LAN, i.e. with -N.
+
+ The ReadEventMessageBuffer method:
+ 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 simul-
+ taneously, 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.
+
+ The OpenIPMI custom method:
+ 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 if the OpenIPMI
+ driver is detected, and no other method is specified.
+
+ The Async Event method:
+ This only gets certain Asynchronous requests from the BMC to an SMS OS
+ service, like a remote OS shutdown, and get_software_id. This method
+ is disabled by default and only turned on if the getevent -a option is
+ specified. This method is only supported via the Intel IMB and
+ OpenIPMI driver interfaces. There is an init script provided with
+ ipmiutil to automate the task of starting this async event daemon.
+ # chkconfig --add ipmiutil_asy (skip this if no chkconfig)
+ # /etc/init.d/ipmiutil_asy start
+ This listens for IPMI LAN requests for soft-shutdown, and logs the out-
+ put to /var/log/ipmiutil_asy.log
+
+
+OPTIONS
+ Command line options are described below.
+
+
+ -a Use the Async request method, which receives SMS OS requests
+ from the BMC using the IMB or OpenIPMI driver interface. This
+ services remote SMS bridge agent requests, like remote OS shut-
+ down and get software_id.
+
+ -b Run in Background as a daemon. If this option is specified,
+ normal output will be redirected to /var/log/ipmiu-
+ til_getevt.log. The default is to run in foreground.
+
+ -c Show output in a canonical format, with a delimiter of '|'.
+
+ -e N Wait for a specific event sensor type N. The parameter can be
+ in hex (0x23) or decimal (35). The default is 0xFF which means
+ wait for any event.
+
+ -r F Run script file F when an event occurs. The filename can
+ include a full path. The script will be passed the event
+ description as a parameter. A sample evt.sh script is included
+ with the ipmiutil package.
+
+ -o Only run one pass to wait for the first event. Default is to
+ loop for multiple events for the timeout period.
+
+ -s Use the SEL method to get events. This polls the SEL once a
+ second for new events. The last SEL record read is saved in
+ /usr/share/ipmiutil/evt.idx. Otherwise, the default is to use
+ the ReadEventMessageBuffer method to get new events.
+
+ -t N Set the timeout period to N seconds. Default is 120 seconds. A
+ timeout of 0 means an infinite period.
+
+ -x Causes extra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8)
+ ifru(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.9 IHEALTH (ipmiutil health)
+
+IHEALTH(8) IHEALTH(8)
+
+
+
+NAME
+ ipmiutil_health- show IPMI health
+
+SYNOPSIS
+ ipmiutil health [-ifhglmnopqsx -N node -U user -P/-R pswd -EFJTVY]
+
+
+DESCRIPTION
+ ipmiutil health is a program that uses IPMI commands to show the health
+ of the BMC. This utility can use either the /dev/ipmi0 driver from
+ OpenIPMI, the /dev/imb driver from Intel, the /dev/ipmikcs driver from
+ valinux, direct user-space IOs, or the IPMI LAN interface if -N.
+
+
+OPTIONS
+ Command line options are described below.
+
+
+ -c Show canonical, delimited output.
+
+ -f Show the FRUSDR version also.
+
+ -g Show the IPMI GUID of this system. The GUID is a read-only
+ unique identifier.
+
+ -h Check the health of the HotSwap Controller also.
+
+ -l Show the IPMI LAN channel statistics also.
+
+ -m 002000
+ Target a specific MC (e.g. bus 00, sa 20, lun 00). This could
+ be used for PICMG or ATCA blade systems. The trailing charac-
+ ter, if present, indicates SMI addressing if ’s’, or IPMB
+ addressing if ’i’ or not present.
+
+ -n string
+ Set the System Name to this string in the IPMI System Informa-
+ tion.
+
+ -o string
+ Set the Primary Operating System to this string in the IPMI Sys-
+ tem Information.
+
+ -p 1 Set the chassis Power restore policy, governing the desired
+ behavior when power was lost and is restored. Values: 0 = stay
+ off, 1 = last state, 2 = always on.
+
+ -q string
+ Set the Secondary Operating System to this string in the IPMI
+ System Information.
+
+ -s Show the IPMI Session information also.
+
+ -x Causes extra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8)
+ ifru(8) igetevent(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.10 ILAN (ipmiutil lan)
+
+ILAN(8) ILAN(8)
+
+
+
+NAME
+ ipmiutil_lan - show and configure BMC LAN parameters and set up a PEF
+ entry to send BMC LAN Alerts for OS Critical Stop log events
+
+SYNOPSIS
+ ipmiutil lan [-abcdefghijklmnopq#rstuvwxyzBDQK -i eth1 ]
+ [-I ipadr -M macadr -S subnet -B baud_sol ]
+ [-G gwyip -H gwymac -L lan_channel_num ]
+ [-A alertip -X alertmac -C community ]
+ [-u user_to_set -p password_to_set ]
+ [-N nodename -U username -Fimb ]
+ [-P/-R rmt_node_pswd -EFJTVY ]
+
+
+DESCRIPTION
+ ipmiutil lan shows or sets all of the IPMI LAN Parameters to enable
+ remote LAN sessions or BMC LAN Alerts. The IP address and MAC address
+ of the local system, the default gateway, and the alert destination can
+ be defaulted to those specified in Linux, or can be overridden by user
+ parameters. It also creates a new Platform Event Filter table entry
+ for an OS Critical Stop (0x20) SEL firmware log event, so that it will
+ be enabled to send a BMC LAN Alert. This utility will skip the PEF
+ records if the system does not support IPMI 1.5 or greater. This util-
+ ity can use either the /dev/ipmi0 driver from OpenIPMI, the /dev/imb
+ driver from Intel, the /dev/ipmikcs driver from valinux, direct user-
+ space IOs, or the IPMI LAN interface if -N.
+
+
+OPTIONS
+ Command line options are described below. Note that without options,
+ ipmiutil lan behaves as if option -r were used. To configure IPMI LAN
+ & PEF, use option -e.
+
+
+ -a alertnum
+ Specify which PEF alert number is to be used. Default is 1.
+ This would only be used if extra PEF alert destinations had been
+ set.
+
+ -b authmask
+ Specify a certain authtype mask in hex to use when configuring
+ this channel. The default mask is 0x16, so to include authtype
+ None (bit 0), it would require entering ’-b 17’.
+
+ -c Show Canonical output, which shows only interpreted text and
+ streamlines the parameters shown, using a common delimiter.
+
+ -d This option disables the IPMI LAN and PEF parameters, so as not
+ to allow BMC LAN connections or alerts. This option also sets
+ the IP address to zeros.
+
+ -e This option enables the BMC LAN configuration and PEF event
+ alerts. The utility will attempt to obtain the default BMC LAN
+ parameters from the OS automatically, or they can be specified
+ with command options below.
+
+ -f Set the ARP control parameter to 1 = gratuituous ARPs, 2 = ARP
+ responses, or 3 = both grat ARP and ARP responses. The default
+ is 1.
+
+ -g This specifies the secondary gateway IP address to use for the
+ BMC LAN. The default is to omit this parameter and only use the
+ default gateway. See also -G.
+
+ -h Set the IPMI VLAN ID to this value. Setting to a value >=4096
+ disables the VLAN ID. The default behavior is not to set this
+ parameter.
+
+ -i ethif
+ By default, the eth0 interface is used to find IP and MAC
+ addresses. Sometimes, however, the first ethernet port on the
+ baseboard may be represented by Linux as eth1 or eth2 instead.
+ If so, use this option to indicate the correct ethernet inter-
+ face to use. By default, ipmiutil lan will scan up to 32 eth
+ interfaces for the onboard one that BMC LAN uses.
+
+ -j This sets a custom PEF rule as the last PEF entry. The input is
+ a series of 10 hex bytes, forming the PEF entry. For example,
+ this sample PEF entry would perform a power down action if the
+ Baseboard Temp reached its threshold.
+ "ipmiutil lan -e -j020110ffff013001950a"
+
+ -k This causes ipmiutil lan to also insert two rules to send alerts
+ for transition-to-OK events, including Power Redundancy OK and
+ Temperature OK.
+
+ -l This option enables the BMC LAN configuration, but not PEF
+ events. The utility will attempt to obtain the default BMC LAN
+ parameters from the OS automatically, or they can be specified
+ with command options below.
+
+ -n num By default, the new PEF entry for OS Critical Stop is inserted
+ at offset 12 into the table. This can be changed to insert it
+ at an offset > 12 if another entry already exists at offset 12.
+
+ -o Disable Only SOL. This could be used after the IPMI LAN was
+ configured, to disable Serial-Over-LAN console access but still
+ allow other IPMI LAN access.
+
+ -p password_to_set
+ This specifies the firmware password to set for BMC LAN access.
+ If not specified, the user and password configuration will not
+ be changed.
+
+ -q Specify an alternate user number for the LAN username from the
+ -u option. This is normally user number 2, 3, or 4, where 2 is
+ the default. The maximum number of users is 15. Same as -#
+ below.
+
+ -# Specify an alternate user number for the LAN username from the
+ -u option. Same as -q above.
+
+ -r This option just reads the configuration without writing any BMC
+ LAN parameters or writing any new entries to the PEF table.
+
+ -s This option will also display some of the Serial parameters.
+
+ -t Test if the BMC LAN has already been configured. Returns 0 if
+ so.
+
+ -u username_to_set
+ This specifies the firmware username to set for BMC LAN access.
+ If a username is specified, user 3 will be set. If not speci-
+ fied, the default user 1 will be used.
+
+ -v priv
+ Set a specific access priVilege for this user, where priv can
+ be: 1=Callback, 2=User, 3=Operator, 4=Admin, 5=OEM, 15=NoAccess
+ The default if not specified or specified in error, is to use
+ 4=Admin.
+
+ -w N Set the Gratuitous ARP Interval to N seconds. This has no
+ effect if the firmware does not support Grat-ARP, as shown in
+ Lan Param 10. If not set, the interval remains at the firmware
+ default.
+
+ -x Causes extra debug messages to be displayed.
+
+ -y N Set the OEM LAN Failover parameter to N. Values for N with
+ Intel Romley/S2600 baseboards: 1 = enable, 0 = disable. Val-
+ ues for N with SuperMicro baseboards: 2 = failover, 1 = lan1 , 0
+ = dedicated.
+
+ -z Also show the IPMI LAN Statistics
+
+ -A alert_ip_addr
+ This specifies the SNMP Alert Destination IP address to use for
+ the BMC LAN. By default, this utility will attempt to obtain
+ this from the /etc/snmp/snmpd.conf file, via the trapsink param-
+ eter. The alert destination will see the BMC LAN traps with the
+ enterprises.3183.1.1 OID. If no alert IP address is specified
+ in either snmpd.conf or this parameter, or if that IP address
+ does not respond, the other SNMP parameters for BMC LAN will be
+ skipped.
+
+ -B baud_sol
+ This specifies the Baud rate for SerialOverLan. The possible
+ values are: 9600, 19.2k, 38.4k, 57.6k, and 115.2k. The default
+ is 19.2k.
+
+ -C snmp_community
+ This specifies the SNMP Community name to use for BMC LAN
+ Alerts. The default community string is "public". This parame-
+ ter is ignored if there is no Alert IP address.
+
+ -D This causes the local IP address to be determined by DHCP
+ instead of a static IP address.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -G gwy_ip_addr
+ This specifies the default gateway IP address to use for the BMC
+ LAN. The default is to automatically obtain this from the Linux
+ route table.
+
+ -H gwy_mac_addr
+ This specifies the default gateway MAC address to use for the
+ BMC LAN. The format can be either 11:22:33:44:55:66 or
+ 11-22-33-44-55-66. The default is to try to automatically
+ obtain this by sending an arp request from an OS LAN eth inter-
+ face: the default one, or as specified by -i.
+
+ -K hostname
+ This specifies the IPMI hostname to set, for Kontron servers
+ only. This enables the firmware to properly map the IP address
+ to a hostname, especially with the web interface. The default
+ is not to set this parameter, and use IP address only.
+
+ -I ip_addr
+ This specifies the local IP address to use for the BMC LAN on
+ eth0. The default is to automatically obtain this from the
+ Linux ifconfig.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -L lan_ch_num
+ This specifies the IPMI LAN channel number used for BMC LAN.
+ This varies by platform, and can be found in the platform tech-
+ nical specifications. For instance, Intel platforms usually use
+ channels 1 & 2 for onboard NICs, and channel 3 for optional RMM
+ NICs. By default, ipmiutil lan scans all IPMI channels to find
+ the first LAN channel for BMC LAN. To just list all IPMI chan-
+ nels to see what is available, use the string ’list’ instead of
+ a LAN channel number. This will list the channels and exit.
+
+ -M mac_addr
+ This specifies the local MAC address to use for the BMC LAN on
+ eth0. The format can be either 11:22:33:44:55:66 or
+ 11-22-33-44-55-66. The default is to automatically obtain this
+ from the Linux ifconfig.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -P rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password. Same as -R below.
+
+ -Q Set the IPMI VLAN Priority. The default priority is 0.
+
+ -R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password. Same as -P above.
+
+ -S subnet
+ This specifies the local subnet mask to use for the BMC LAN on
+ eth0. The default is to automatically obtain this from the
+ Linux ifconfig.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -X alert_mac_addr
+ This specifies the SNMP Alert Destinations’s MAC address to use
+ for the BMC LAN. The format can be either 11:22:33:44:55:66 or
+ 11-22-33-44-55-66. The default is to attempt to obtain this
+ from the Linux arp cache. This parameter is ignored if there is
+ no Alert IP address.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+EXAMPLES
+ To read existing settings:
+ ipmiutil lan -r
+
+ To enable IPMI LAN with default settings detected, assuming shared
+ MAC/IP:
+ ipmiutil lan -e
+
+ To set up IPMI LAN for a unique IP address and set PEF SNMP Alerts:
+ ipmiutil lan -e -I 192.168.1.1 -A 192.168.1.10
+
+ To set the IPMI LAN password for the default user:
+ ipmiutil lan -e -p mypassword
+
+ To disable access to the IPMI LAN channel:
+ ipmiutil lan -d
+
+
+SAMPLE PEF TABLE
+ These 11 PEF table entries are configured from the factory for various
+ Intel Sahalee BMC systems, and will be applied as the defaults for a
+ system with an empty PEF table:
+ PEF(01): 01 Temperature Sensor event - enabled for alert
+ 01 c0 01 01 00 ff ff 01 ff 01 95 0a 00 00 00 00 00 00 00 00 00
+ PEF(02): 02 Voltage Sensor event - enabled for alert
+ 02 c0 01 01 00 ff ff 02 ff 01 95 0a 00 00 00 00 00 00 00 00 00
+ PEF(03): 04 Fan Failure event - enabled for alert
+ 03 c0 01 01 00 ff ff 04 ff 01 95 0a 00 00 00 00 00 00 00 00 00
+ PEF(04): 05 Chassis Intrusion event - enabled for alert
+ 04 c0 01 01 00 ff ff 05 05 6f 01 00 00 00 00 00 00 00 00 00 00
+ PEF(05): 08 Power Supply Fault event - enabled for alert
+ 05 c0 01 01 00 ff ff 08 ff 6f 06 00 00 00 00 00 00 00 00 00 00
+ PEF(06): 0c Memory ECC Error event - enabled for alert
+ 06 c0 01 01 00 ff ff 0c 08 6f 02 00 00 00 00 00 00 00 00 00 00
+ PEF(07): 0f FRB Failure event - enabled for alert
+ 07 c0 01 01 00 ff ff 0f 06 6f 01 00 00 00 00 00 00 00 00 00 00
+ PEF(08): 07 BIOS POST Error event - enabled for alert
+ 08 c0 01 01 00 ff ff 07 ff 6f 1c 00 00 00 00 00 00 00 00 00 00
+ PEF(09): 13 Fatal NMI event - enabled for alert
+ 09 c0 01 01 00 ff ff 13 ff 6f 3e 03 00 00 00 00 00 00 00 00 00
+ PEF(10): 23 Watchdog Timer Reset event - enabled for alert
+ 0a c0 01 01 00 ff ff 23 03 6f 0e 00 00 00 00 00 00 00 00 00 00
+ PEF(11): 12 System Restart event - enabled for alert
+ 0b c0 01 01 00 ff ff 12 ff 6f 02 00 00 00 00 00 00 00 00 00 00
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8)
+ ifru(8) igetevent(8) ihealth(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.11 IRESET (ipmiutil reset)
+
+IRESET(8) IRESET(8)
+
+
+
+NAME
+ ipmiutil_reset - perform a hardware reset on the system
+
+SYNOPSIS
+ ipmiutil reset [-bcdDefhijmnoprsuwxy -N node -U user -P/-R pswd
+ -EFJTVY]
+
+
+DESCRIPTION
+ ipmiutil reset is a program that uses IPMI commands to perform a hard-
+ ware reset of the chassis, or boot to a specific device. This utility
+ can use either the /dev/ipmi0 driver from OpenIPMI, the /dev/imb driver
+ from Intel, the /dev/ipmikcs driver from valinux, direct user-space
+ IOs, or the IPMI LAN interface if -N.
+
+
+OPTIONS
+ Command line options are described below.
+
+ -c Power Cycle the system chassis
+
+ -d Power Down the system chassis
+
+ -n Send NMI to the system
+
+ -u Power Up the system chassis
+
+ -r Hard Reset the system chassis
+
+ -D Do a soft shutdown of the OS, and then power down. Note that
+ remote soft shutdown (-D -N) for Intel S5000 baseboard requires
+ ipmiutil getevt -a running on the target server.
+
+ -o Do a soft shutdown of the OS, and then reset. Note that remote
+ soft shutdown (-o -N) for Intel S5000 baseboard requires ipmiu-
+ til getevt -a running on the target server.
+
+ -k Do a cold reset to restart the BMC firmware.
+
+ -m 002000s
+ Perform these function for a specific MC (e.g. bus 00, sa 20,
+ lun 00). The trailing character, if present, indicates SMI
+ addressing if ’s’, or IPMB addressing if ’i’ or not present.
+
+ -b Do a hard reset and reboot to the BIOS Setup menu, for this
+ reboot only.
+
+ -e Do a hard reset to EFI, if IPMI EFI boot is enabled, for this
+ reboot only.
+
+ -f Do a hard reset to Floppy/Removable, for this reboot only.
+
+ -h Do a hard reset to a Hard Disk, for this reboot only.
+
+ -i Set the boot Initiator mailbox string, usually for PXE use. The
+ string must be less than 78 characters.
+
+ -j Set the IANA number used for the boot Initiator mailbox string.
+
+ -p Do a hard reset and network boot to PXE server, for this reboot
+ only.
+
+ -s Do a hard reset and reboot to the Service/Diagnostic Partition,
+ for this reboot only. Reboots to the default if no service par-
+ tition is configured.
+
+ -v Do a hard reset to DVD/CDROM Media, for this reboot only.
+
+ -w Wait for BMC ready after a reset before exiting the utility.
+
+ -x Causes extra debug messages to be displayed.
+
+ -y Yes, try to persist any boot options used [-befhprsv]. This
+ requires the IPMI firmware to ask the BIOS to change boot order
+ settings, so it may not be supported by all BMC firmware ven-
+ dors.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8)
+ ifru(8) igetevent(8) ihealth(8) ilan(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.12 ISEL (ipmiutil sel)
+
+ISEL(8) ISEL(8)
+
+
+
+NAME
+ ipmiutil_sel - show firmware System Event Log records
+
+SYNOPSIS
+ ipmiutil sel [-abcflswvx -N node -P/-R pswd -U user -EFJTVY]
+
+
+DESCRIPTION
+ ipmiutil sel is a program that uses IPMI commands to to read and dis-
+ play the System Event Log (SEL) which is stored by the BMC firmware.
+ IPMI commands are issued to read each record, and, if specified, incre-
+ mentally write records that have not previously been read into the
+ Linux syslog (/var/log/messages). This utility can use either the
+ /dev/ipmi0 driver from OpenIPMI, the /dev/imb driver from Intel, the
+ /dev/ipmikcs driver from valinux, direct user-space IOs, or the IPMI
+ LAN interface if -N.
+
+
+OPTIONS
+ Command line options are described below.
+
+
+ -a string
+ Add a SEL record with a string of up to 13 characters. Longer
+ strings will be truncated. Note that this should be used spar-
+ ingly, but would be useful for changes made to the hardware or
+ firmware environment, like "Fan replaced" or "flash FW2.1".
+
+
+ -b bin_file
+ Interpret a file containing raw binary/hex SEL data dumped in
+ binary form, such as that produced by "ipmitool sel writeraw
+ bin_file". Each set of 16 bytes in the file will be interpreted
+ as an IPMI event.
+
+
+ -c Show output in a canonical format, with a default delimiter of
+ '|'. (same as -n).
+
+
+ -d Deletes/Clears the SEL of all records. If the SEL becomes full
+ (free space = 0), it no longer accepts new records, so the SEL
+ should be cleared periodically (use checksel cron script).
+
+
+ -e Show Extended sensor descriptions for events if run locally.
+ This option will attempt to get the full sensor description from
+ /var/lib/ipmiutil/sensor_out.txt, and also use its SDR to decode
+ any raw threshold values in the event, if present.
+
+
+ -f sel_file
+ Interpret a file containing raw ascii text SEL data captured
+ with ipmiutil sel -r, or some other similar utility. Each line
+ in the file should be in this form, with no leading spaces:
+ 04 00 02 76 a9 4a 47 20 00 04 10 09 6f 42 0f ff
+ Lines not in this format will be ignored.
+
+
+ -l N Show last N SEL records, in reverse order (newest first). For
+ some BMC implementations, this may not show all N records speci-
+ fied.
+
+ -n Show output in a nominal/canonical format, with a default delim-
+ iter of '|'. (same as -c).
+
+ -r Show the 16 raw hex bytes for each SEL entry. The default is to
+ display interpreted entries, and include relevant hex event
+ bytes.
+
+ -p By default, all SEL records are displayed. This option causes
+ only the Panic events with sensor_type = 0x20 (OS Critical Stop)
+ to be displayed.
+
+ -s N Show only SEL events with severity N or greater. Severity
+ 0=INF, 1=MIN, 2=MAJ, 3=CRT. The default is to show all SEL
+ events.
+
+ -u Show the SEL time as UTC and also get the SEL Time UTC offset if
+ that command is supported. The default is to convert the SEL
+ Time to local time.
+
+ -v Only show the version information. This shows: the ipmiutil
+ sel utility version, the BMC version, the IPMI version, the SEL
+ version, and the amount of free space in the SEL.
+
+ -w This option writes SEL records to the Linux syslog
+ (/var/log/messages) or Windows Application Log. It only writes
+ SEL records that have timestamps newer than the last record
+ written to syslog. It saves the last timestamp in an index file
+ named /usr/share/ipmiutil/sel.idx (.\sel.idx in Windows).
+
+ -x Causes extra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8)
+ ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.13 ISENSOR (ipmiutil sensor)
+
+ISENSOR(8) ISENSOR(8)
+
+
+
+NAME
+ ipmiutil_sensor - show Sensor Data Records
+
+SYNOPSIS
+ ipmiutil sensor [-abcdefgmpqrstuvwx -i id -n snum -h tval -l tval
+ -NUPREFJTVY]
+
+
+DESCRIPTION
+ ipmiutil sensor is a program that uses IPMI commands to show and decode
+ Sensor Data Records and current sensor readings for all sensors in the
+ system. This utility can use either the /dev/ipmi0 driver from
+ OpenIPMI, the /dev/imb driver from Intel, the /dev/ipmikcs driver from
+ valinux, direct user-space IOs, or the IPMI LAN interface if -N.
+
+ Note that this utility by default only displays Sensor Data Records
+ reported by from the Baseboard Management Controller. To show sensors
+ for other controllers, see options -b and -m below.
+
+
+OPTIONS
+ Command line options are described below.
+
+ -a snum
+ ReArms the sensor number for events
+
+ -b Shows SDRs for Bladed (PICMG or ATCA) systems by traversing the
+ child MCs (same as -e).
+
+ -c Show sensor list in a simpler/Canonical format without uninter-
+ preted binary values. Only the user-friendly interpreted sensor
+ information is shown. (same as -s).
+
+ -d <file>
+ Dump the SDRs to a specified binary file.
+
+ -e Show Every SDR in a bladed system by traversing the child MCs
+ (same as -b).
+
+ -f <file>
+ Restore the SDRs from the specified binary File. This is nor-
+ mally only done with the initial factory provisioning.
+
+ -g sens_type
+ Shows only those SDRs matching the given sensor type group. The
+ sens_type string can be "fan", "temp", "voltage", or any string
+ or substring matching those in the IPMI 2.0 Table 42-3 for Sen-
+ sor Types. Multiple types can be listed, separated by a comma
+ (,) but no spaces.
+
+ -h tval
+ Highest threshold value to set for the specified sensor. This
+ tval can be in decimal, or of the form 0x1a, to match the raw
+ reading value shown by sensor following the " = ". The value
+ passed is set as the non-critical threshold value, with the more
+ critical ones set by the utility as incrementally lower. This
+ simplifies the interface and ensures that the threshold values
+ do not get out of order. This requires specifying the sensor
+ number via -n.
+
+ -i ID Show or set only the sensor Index corresponding to ID, where ID
+ is the hex ID of the SDR as shown in the sensor output under
+ "_ID_". The ID argument can be one hex number (e.g. 0x0e or
+ 0e), or a range of hex numbers (e.g. 0e-1a or 1a,2a or
+ 0x0e-0x2a). This is useful to repeatedly view just a few sensor
+ readings for changes, or to set just one sensor quickly without
+ reading all of the SDRs.
+
+ -l tval
+ Lowest threshold value to set for the specified sensor. This
+ tval can be in decimal, or of the form 0x1a, to match the raw
+ reading value shown by sensor following the " = ". The value
+ passed is set as the non-critical threshold value, with the more
+ critical ones set by the utility as incrementally higher. This
+ simplifies the interface and ensures that the threshold values
+ do not get out of order. This requires specifying the sensor
+ number via -n.
+
+ -m 002000s
+ Show SDRs for a specific MC (e.g. bus 00, sa 20, lun 00). This
+ could be used for PICMG or ATCA blade systems. The trailing
+ character, if present, indicates SMI addressing if ’s’, or IPMB
+ addressing if ’i’ or not present.
+
+ -n snum
+ Number of the sensor to set. This num can be in decimal, or of
+ the form 0x1a, to match the value shown by sensor following the
+ "snum" tag. This is required if setting hi/lo thresholds via
+ -h/-l.
+
+ -o Output the memory DIMM information from SMBIOS, including size.
+ Not available if using IPMI LAN via -N. Sample output:
+ Memory Device (0,0): DIMM_A1 : size=2048MB
+ Memory Device (0,1): DIMM_A2 : not present
+
+ -p Persist the threshold being set (as specified via -l or -h).
+ This writes a "sensor -i" script line to the file
+ /usr/share/ipmiutil/thresholds.sh, which can then be executed at
+ each reboot by starting the /etc/init.d/ipmi_port service for
+ the desired runlevels. For Windows, the filename is thresh-
+ olds.cmd.
+
+ -q Show any thresholds for each sensor in short format with ’:’
+ delimiters, useful as an example for setting thresholds with
+ ’-u’.
+
+ -r Show Raw SDR bytes also.
+
+ -s Show sensor list in a simpler/canonical format without uninter-
+ preted binary values. Only the user-friendly interpreted sensor
+ information is shown. (same as -c).
+
+ -t Show any Thresholds for each sensor also, in text format.
+
+ -u Set unique threshold values. The values are specified in a
+ string of threshold values. It can be in raw hex characters or
+ in float values. All 6 possible thresholds must be specified,
+ but only the ones that are valid for this sensor will be
+ applied. These values are validated for ordering. For example:
+ -u 6:5:4:60:65:69 (float) or
+ -u 0x0605043c4145 (raw hex)
+ would mean 0x06=noncrit_lo, 0x05=crit_lo, 0x04=nonrec_lo,
+ 0x3c=noncrit_hi, 0x41=crit_hi, 0x45=nonrec_hi.
+
+ -v Show Verbose output, including volatile thresholds, SDR thresh-
+ olds, max/min, hysteresis, and BMC_TAM decoding.
+
+ -w Wrap the threshold data onto the same line as the sensor. This
+ may be convenient for scripting.
+
+ -x Causes eXtra debug messages to be displayed.
+
+ -L n Loop n times. This is useful along with -i. Default is one
+ loop.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+EXAMPLES
+ ipmiutil sensor sample output is below.
+ ipmiutil ver 2.21
+ sensor: version 2.21
+ -- BMC version 0.17, IPMI version 2.0
+ _ID_ SDR_Type_xx ET Own Typ S_Num Sens_Description Hex & Interp Read-
+ ing
+ 000b SDR Full 01 01 20 a 01 snum 30 Baseboard Temp = 2e OK 46.00
+ degrees C
+ 000e SDR Full 01 01 20 m 04 snum 50 Fan 1A = 6f OK 7659.00
+ RPM
+ 0042 SDR Comp 02 6f 20 a 21 snum e0 DIMM 1A = 00 c0 04 00
+ Present
+ 004e SDR FRU 11 1b dev: 20 03 80 00 0a 01 Pwr Supply 1 FRU
+ 0050 SDR IPMB 12 1b dev: 20 00 bf 07 01 Basbrd Mgmt Ctlr
+ 0051 SDR OEM c0 09 Intel: 02 02 00 01 70 71
+ 0065 SDR OEM c0 11 Intel: SDR Package 17
+ [...]
+
+ Output Columns:
+ _ID_: This is an SDR ID or index number, in hex. This may vary from
+ chassis to chassis.
+ SDR_Type_xx: This shows the SDR Type and its hex representation. Some
+ SDR types have a custom display. The OEM SDRs only show the OEM vendor
+ by IANA number and then usually the data is listed in hex.
+ ET: For Full or Comp SDRs, this shows the Event Type. For other SDRs,
+ this shows the size of the SDR entry in hex (Sz).
+ Own: This is the hex slave address of the SDR Owner, usually 20 if BMC.
+ a/m: This indicates whether this sensor is either automatically or man-
+ ually rearmed, respectively.
+ Typ: This is the Sensor Type as defined in Table 42-3 of the IPMI 2.0
+ spec. (01 = Temperature, 02 = Voltage, 03 = Current, 04 = Fan, etc.)
+ S_Num: This is the sensor number in hex. This remains consistent
+ across baseboards of the same type. The output can be parsed with the
+ "snum" delimiter to extract this value.
+ Sens_Description: This is the text description of this SDR, which is
+ stored within the SDR on the BMC.
+ Hex & Interp Reading: This is the raw hex value returned by GetSensor-
+ Reading, and its interpreted meaning.
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8)
+ ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.14 ISERIAL (ipmiutil serial)
+
+ISERIAL(8) ISERIAL(8)
+
+
+
+NAME
+ ipmiutil_serial - configure a system for Serial/EMP management func-
+ tions, such as Terminal Mode, and optionally share the port with the
+ Serial Console.
+
+SYNOPSIS
+ ipmiutil serial [-bcdeflq#rsvxB -m0 -m1 -n ser_chan -u user -p passwd
+ -NUPREFJTVY]
+
+
+DESCRIPTION
+ ipmiutil serial is a program that uses an IPMI driver to send IPMI com-
+ mands which configure a system to enable EMP/serial Terminal Mode man-
+ agement functions within the firmware, so that an administrator can use
+ command-line character commands via the serial port to power cycle the
+ system and perform other functions, even if the system is not running
+ an OS. This level of access needs to be protected by a username/pass-
+ word login, which can be specified with this utility. This utility can
+ use either the /dev/ipmi0 driver from OpenIPMI, the /dev/imb driver
+ from Intel, the /dev/ipmikcs driver from valinux, direct user-space
+ IOs, or the IPMI LAN interface if -N.
+
+
+OPTIONS
+ Command line options are described below.
+
+ -b Set up and enable the Serial Port EMP parameters for Basic Mode
+ management functions. This does not set a username or password.
+
+ -c Configure and enable the Serial Port EMP parameters for Terminal
+ Mode management functions, shared with BIOS Console Redirection.
+ Setting a new username and password for serial access via -u and
+ -p is recommended for security.
+
+ -d Disable the serial port access for IPMI commands. The serial
+ port is then only available for BIOS console and OS functions.
+ A side-effect of this option is that it sets the default user
+ (1) back to admin access.
+
+ -e Enable EMP Terminal Mode without shared BIOS console. The
+ serial port is then only available for EMP Terminal Mode func-
+ tions.
+
+ -f Specifies the Flow Control for the Serial EMP. 0 means no flow
+ control, and 1 means RTS/CTS flow control (default). This must
+ match the BIOS Serial Console setting.
+
+ -l Show LAN Parameters. This option reads and displays the LAN
+ Parameter configuration also.
+
+ -m0 Switch the Serial Port MUX to Baseboard/BIOS Console operation.
+ Set no other configuration parameters.
+
+ -m1 Switch the Serial Port MUX to Terminal Mode management. Set no
+ other configuration parameters.
+
+ -n ser_chan
+ Sets the IPMI channel number to use for the EMP serial channel
+ (often 4). Note that the IPMI channels for LAN, Serial, etc.
+ are numbered differently on each platform type. The default is
+ to detect the first available IPMI serial channel.
+
+ -# Same as -q below.
+
+ -q Specify an alternate user number for the EMP Username from the
+ -u option. This is normally user number 2, 3, or 4, where 3 is
+ the default. The maximum number of users is 15.
+
+ -r Read Only. This option just reads the Serial Parameter configu-
+ ration without writing any values.
+
+ -s Set up and enable the Serial Port EMP parameters for Shared
+ operation between Basic Mode management functions and Baseboard
+ (BIOS) Remote Console. This option switches the Serial Port MUX
+ to Baseboard Console operation.
+
+ -t Configure and enable the Serial Port EMP parameters for Terminal
+ Mode management functions, shared with BIOS Console Redirection.
+ Same as -c, but easier to remember.
+
+ -u username
+ This specifies a username for the EMP Terminal Mode login. It
+ can be any string, up to 15 characters. If -u is not used, the
+ default user 1 (null) will be assumed. The username, if speci-
+ fied, will be set for user 3, unless option -q is specified.
+
+ -p password
+ This specifies a password for the EMP Terminal Mode login. It
+ can be any string, up to 15 characters. A null password is used
+ if none is specified. This password applies to user 3 if -u is
+ used, to user 1 otherwise.
+
+ -v priv
+ Set a specific access priVilege for this user, where priv can
+ be: 1=Callback, 2=User, 3=Operator, 4=Admin, 5=OEM, 15=NoAccess
+ The default if not specified or specified in error, is to use
+ 4=Admin.
+
+ -x Causes extra debug messages to be displayed.
+
+ -B Set the Baud rate of the serial port to one of the following:
+ 9600, 19,2K, 38.4K, 57.6K, or 115.2K. The default is 19.2K bps.
+
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+EXAMPLES
+ ipmiutil serial -t (or -c)
+ Enables Terminal Mode management functions, shared with BIOS
+ Serial Console redirection. The user can switch between serial
+ console operations and IPMI Terminal Mode commands by typing ESC
+ ’)’ and ESC ’Q’.
+
+
+ ipmiutil serial -s
+ Enables Basic Mode management functions shared with BIOS Serial
+ Console redirection. The user can switch between serial console
+ operations and IPMI Basic Mode management programs on the same
+ serial port.
+
+
+ ipmiutil serial -d
+ Disables the serial port management functions. This would be
+ used if only the BIOS Serial Console were used and no BMC serial
+ management functions.
+
+
+ How to login to a Terminal Mode console:
+ ESC ( (switch to Terminal mode)
+ [SYS PWD -N ] (login for default user, null psw)
+ [SYS PWD -U ROOT -N PASSWORD] (syntax example for user 3)
+ [SYS 000157 ACTIVATE] (activate advanced commands)
+ [SYS HEALTH QUERY]
+ [SYS HELP]
+ [SYS PWD] (logoff)
+ ESC Q (switch to BIOS console)
+ See IPMI 1.5 Spec, Appendix E, and Intel TIGPR2U TPS for more informa-
+ tion.
+
+
+DEPENDENCIES
+ The ipmiutil serial utility is intended to configure the EMP serial
+ port on the server for shared access between BMC/IPMI functions and
+ BIOS Console Redirection. Some platforms only support only Basic Mode
+ for BMC/IPMI functions. Basic Mode requires a remote client applica-
+ tion to utilize it (Windows ISC Console/DPC, or a special modified
+ Linux telnet). There are some platforms which implement Terminal Mode
+ via IPMI v1.5 Appendix E to make remote management with character com-
+ mands available on the serial port without a special remote client
+ application.
+
+ For example, Intel TSRLT2 systems would use "ipmiutil serial -s" for
+ Basic Mode shared functions, but Intel TIGPR2U systems could use
+ "ipmiutil serial -c" to configure Terminal Mode functions. On your
+ system, run "ipmiutil serial -r" to check whether Serial Param(29):
+ "Terminal Mode Config" is supported. If not, configure Basic Mode via
+ "ipmiutil serial -s".
+
+
+
+PLATFORM SERIAL PORT CONFIGURATION EXAMPLES
+ First, enter BIOS Setup for Serial Console Redirection parameters:
+ (these vary by platform)
+ Console Redirection = Serial Port B
+ ACPI Redirection = Disabled
+ Baud Rate = 115.2K
+ Flow Control = CTS/RTS
+ Terminal Type = VT100
+ Legacy Redirection = Enabled
+ Note that the Baud Rate can vary, but it must match in all locations
+ where it is used (BIOS, IPMI, and Linux).
+ For some non-Intel platforms, the serial console would be COM1 instead
+ of COM2, but should be enabled in BIOS.
+ From Linux, run "ipmiutil serial -c" for Terminal Mode shared configu-
+ ration.
+ Or, on older Intel TSRLT2 platforms: From Linux, run "ipmiutil serial
+ -s" for Basic Mode Shared configuration.
+
+
+LINUX CONFIGURATION FOR SERIAL CONSOLE
+ If using lilo, in /etc/lilo.conf, add
+ append="console=ttyS1,19200n8 console=tty0"
+ (and comment out the "message=" line because it includes graphics)
+ Note that the append line can be placed in the global section and
+ removed from each kernel section if there are no other differences.
+
+
+ Or, if using grub, edit /boot/grub/grub.conf as follows:
+ #Omit the splashimage or gfxmenu
+ # splashimage=(hd0,0)/grub/splash.xpm.gz
+ #The serial and terminal lines are not usually needed
+ # serial --unit=1 --speed=19200 --word=8 --parity=no --stop=1
+ # terminal --timeout=10 serial console
+ #Add the console=ttyS* parameter to the kernel line
+ kernel (hd0,0) /vmlinuz root=/dev/sda2 console=ttyS1,19200n8
+
+
+ Add this line to /etc/initab, if ttyS1 is not already there:
+ co:2345:respawn:/sbin/agetty ttyS1 19200 vt100
+
+ Add this line to /etc/securetty, if ttyS1 is not already there:
+ ttyS1
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8)
+ ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.15 ISOL (ipmiutil sol)
+
+ISOL(8) ISOL(8)
+
+
+
+NAME
+ ipmiutil_sol - an IPMI Serial-Over-LAN Console application
+
+
+SYNOPSIS
+ ipmiutil sol [-acdeilorsvwxz -NUPREFJTVY]
+
+
+DESCRIPTION
+ This utility starts an IPMI Serial-Over-LAN console session. A Serial-
+ over-LAN console allows the client to see and modify functions before
+ the OS boots, such as BIOS setup, grub, etc. This utility uses either
+ the IPMI LAN 1.5 or 2.0 SOL interface. The 1.5 SOL interface is spe-
+ cific to Intel BMCs, while any IPMI 2.0 BMC should support 2.0 SOL.
+ The target system/node must first have these parameters configured
+ before SOL sessions can be started:
+ - [BIOS] serial console redirection parameters,
+ - [IPMI] lan and SOL parameters (see ipmiutil lan or ilan), and
+ - [OS] For Linux, edit grub.conf, inittab, and securetty parameters.
+ Be sure that the baud rate matches in all of the above places. See the
+ ipmiutil UserGuide section 4.8 for details.
+
+
+OPTIONS
+ -a Activate the SOL Console session, and enter console mode. Use
+ the escape sequence (’~.’) to exit the session.
+
+ -c ’^’ Set the escape Character to ’^’, or another ANSI character.
+ This changes the default two-character escape sequence (’~.’) to
+ the specified single escape character, which will end the SOL
+ session.
+
+ -d Deactivate the SOL Console session. Use this if the previous
+ session was aborted abnormally and starting a new session gives
+ an error.
+
+ -e Turn Encryption off in negotiation when activating a session.
+ By default, encryption is on for Serial-Over-LAN console ses-
+ sions.
+
+ -l Use Legacy BIOS mapping for Enter key (CR+LF) instead of just
+ LF. This is needed for BIOS Setup menus and DOS, but causes an
+ extra LF to occur in Linux. So, only use this option if doing
+ BIOS or DOS changes. This should be seldom be needed since now
+ the default is to automatically detect these menus with colored
+ backgrounds and change the mapping.
+
+ -i input_file
+ Use this file as an input script. The input_file will be read
+ after the session is established. This can be used to automate
+ certain tasks. The input_file is read one line at a time. If
+ the input_file does not have an escape character (~) to end the
+ session, then the input is returned to the keyboard when the
+ file ends.
+
+ -o output_file
+ Use a Trace log. The output_file is created and all SOL screen
+ output is written to the file, including VT100 escape sequences.
+ If the output_file exists, the output is appended to it. This
+ can be used to log what the user has done in an SOL session.
+
+ -r Use Raw terminal I/O instead of custom VT100 to ANSI translation
+ (in Windows). Use this option if the server is configured in
+ BIOS and BMC for ANSI and the utility is being invoked from Win-
+ dows.
+
+ -s NNN For a slow link with high latency, this adds a delay of NNN
+ microseconds between sending and receiving SOL packets. The
+ default is 100 microseconds.
+
+ -w (Windows only) Do not use the Windows Console buffer, but use
+ Windows stdio instead. This does not handle cursor positioning
+ correctly in some cases, however.
+
+ -v log_file
+ Causes debug messages to be displayed to the specified debug
+ log_file. The default log_file is isoldbg.log in the current
+ directory.
+
+ -x Causes debug messages to be displayed to the debug log file.
+
+ -z Causes more verbose debug messages to be displayed to the debug
+ log file.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any supported
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+EXAMPLES
+ ipmiutil sol -a -N nodename -U username -P password
+ Starts an SOL console session to the nodename. Detect the lan proto-
+ col.
+
+ ipmiutil sol -a -N nodename -U username -P password -Flan2
+ Starts an SOL console session to the nodename. Force lan protocol to
+ 2.0.
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8)
+ ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8)
+ iserial(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.16 IWDT (ipmiutil wdt)
+
+IWDT(8) IWDT(8)
+
+
+
+NAME
+ ipmiutil_wdt- display and set WatchDog Timer parameters
+
+SYNOPSIS
+ ipmiutil wdt [-acdelrtx -N node -P/-R pswd -U user -EFJTVY]
+
+
+DESCRIPTION
+ ipmiutil wdt is a program that uses IPMI commands to display and set
+ WatchDog Timer parameters.
+
+ This utility can use either any available IPMI driver, or direct user-
+ space IOs, or the IPMI LAN interface if -N.
+
+ This utility is an example of how to access the IPMI watchdog parame-
+ ters directly, which allows changing the timer configuration.
+
+ There is an init script provided with ipmiutil to automate the task of
+ managing the watchdog timer in user-space.
+ # chkconfig --add ipmiutil_wdt (skip this if no chkconfig)
+ # /etc/init.d/ipmiutil_wdt start
+ This sets the watchdog timer to reset the system if the wdt is not
+ restarted within 90 seconds. It creates an /etc/cron.d/wdt file to
+ restart wdt every 60 seconds. See also ipmiutil UserGuide section 4.4
+ for more information.
+
+
+OPTIONS
+ Command line options are described below.
+
+ -a N Set watchdog event Action to N. Values: 0 = No action, 1 = Hard
+ Reset(default), 2 = Power down, 3 = Power cycle.
+
+ -c Show watchdog output in a canonical format, with a default
+ delimiter of '|'.
+
+ -d Disables the watchdog timer.
+
+ -e Enables the watchdog timer. The timer is not actually started,
+ however, until the timer is reset. The pre-timeout action is
+ not enabled.
+
+ -l Set the watchdog dontLog bit to not log watchdog events in the
+ SEL.
+
+ -p N Set watchdog Pretimeout event action to N. Values: 0 = No
+ action(default), 1 = SMI, 2 = NMI, 3 = Messaging Interrupt. If
+ this is set to an action other than 0, the pretimeout will also
+ be set to 90% of the timeout. However, if the timeout is less
+ than 20 seconds, the pretimeout will not be enabled.
+
+ -q S Set watchdog pretimeout value to S seconds, rather than 90% of
+ the timeout as in -p. The pretimeout value must be >= 5 and at
+ least 5 seconds less than the timeout value.
+
+ -r Resets the watchdog timer. This should be done every N seconds
+ if the timer is running to prevent the watchdog action (usually
+ a system reset) from occurring.
+
+ -tN Set the watchdog Timeout to N seconds. The default is 120 sec-
+ onds (2 minutes).
+
+ -x Causes extra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+
+SEE ALSO
+ ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifirewall(8)
+ ifru(8) ifruset(8) ifwum(8) igetevent(8) ihealth(8) ihpm(8) ilan(8)
+ ipicmg(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) isunoem(8)
+ iwdt(8) ipmiutil(8) ipmi_port(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.17 IFRUSET (ifruset)
+
+IFRUSET(8) IFRUSET(8)
+
+
+
+NAME
+ ifruset - show/set Field Replacable Unit configuration data
+
+SYNOPSIS
+ ifruset [-bcimx -unpvsafo -N node -U user -P/-R pswd -EFJTVY]
+
+
+DESCRIPTION
+ ifruset is a program that uses IPMI commands to show FRU configuration
+ data and optionally write any Product area fields into the FRU data.
+ Setting the FRU Product area fields is a function that might be done by
+ a manufacturer or system integrator. This utility can use either the
+ /dev/ipmi0 driver from OpenIPMI, the /dev/imb driver from Intel, the
+ /dev/ipmikcs driver from valinux, direct user-space IOs, or the IPMI
+ LAN interface if -N.
+
+ This program is not built or installed by default. Integrators who
+ wish to use it should build ipmiutil from source, then do ’cd util;
+ make ifruset’.
+
+
+OPTIONS
+ Command line options are described below.
+
+ -u manuf
+ This option specifies a product manufacturer string to be writ-
+ ten to the baseboard FRU Product area field 0. This field can
+ be any string up to 20 characters. The default is to not modify
+ this FRU field.
+
+ -n name
+ This option specifies a product name string to be written to the
+ baseboard FRU Product area field 1. This field can be any
+ string up to 20 characters. The default is to not modify this
+ FRU field.
+
+ -p partnum
+ This option specifies a product part number string to be written
+ to the baseboard FRU Product area field 2. This field can be
+ any string up to 20 characters. The default is to not modify
+ this FRU field.
+
+ -v prod_ver
+ This option specifies a product version number string to be
+ written to the baseboard FRU Product area field 3. The version
+ number can be any string up to 20 characters. The default is to
+ not modify this FRU field.
+
+ -s serial_num
+ This option specifies a serial number string to be written to
+ the baseboard FRU Product area field 4. The serial number can
+ be any string up to 20 characters. The default is to not modify
+ this FRU field.
+
+ -a asset_string
+ This option specifies an asset tag string to be written to the
+ baseboard FRU Product area field 5. The asset tag length is
+ limited by the existing FRU Product data, but is usually allowed
+ up to 20 characters. The default is to not modify this FRU
+ field.
+
+ -f fruid
+ This option specifies a product FRU file ID string to be written
+ to the baseboard FRU Product area field 6. This field can be
+ any string up to 20 characters.
+
+ -o oem This option specifies a product OEM field string to be written
+ to the baseboard FRU Product area field 7. This field can be
+ any string up to 20 characters.
+
+
+ -b Only show the Baseboard FRU data. The default behavior is to
+ also scan for any SDR FRU data or DIMM SPD data referenced by
+ the SDRs.
+
+ -c Show FRU output in a canonical format, with a default delimiter
+ of '|'.
+
+ -i 00 This option specifies a specific FRU ID to show. The input
+ value should be in hex (0b, 1a, etc.), as shown from the sensor
+ SDR output. By default, all FRU IDs that are specified in the
+ FRU locator SDRs are shown.
+
+ -m 002000
+ Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00). This
+ could be used for PICMG or ATCA blade systems. The trailing
+ character, if present, indicates SMI addressing if ’s’, or IPMB
+ addressing if ’i’ or not present.
+
+ -x Causes eXtra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8)
+ igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.18 IPMI_PORT (ipmi_port)
+
+IPMI_PORT(8) IPMI_PORT(8)
+
+
+
+NAME
+ ipmi_port - a daemon to bind RMCP port 623 to prevent portmap from
+ using it
+
+
+SYNOPSIS
+ ipmi_port [-bx]
+
+
+DESCRIPTION
+ This ipmi_port service starts and binds port 623, then sleeps forever,
+ so that the portmap service will not try to reuse port 623, which it
+ otherwise might try to do. Since the IPMI firmware snoops the NIC
+ channel and grabs any traffic destined for RMCP port 623, any applica-
+ tion in the OS which tried to use port 623 would fail.
+
+
+OPTIONS
+ Command line options are described below.
+
+ -b Background mode. Convert to a daemon and run in background.
+ Without specifying this option, ipmi_port will run in fore-
+ ground.
+
+ -x Causes eXtra debug messages to be displayed.
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) idiscover(8) ievents(8) ifru(8)
+ igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.19 IPICMG (ipmiutil picmg)
+
+IPICMG(8) IPICMG(8)
+
+
+
+NAME
+ ipmiutil_picmg - send specific PICMG extended IPMI commands
+
+
+SYNOPSIS
+ ipmiutil picmg [-mixNUPREFJTVY] parameters
+
+
+DESCRIPTION
+ This ipmiutil picmg subcommand sends specific PICMG/ATCA extended IPMI
+ commands to the firmware.
+
+ This utility can use either the /dev/ipmi0 driver from OpenIPMI, the
+ /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+ direct user-space IOs, or the IPMI LAN interface if -N.
+
+
+OPTIONS
+ Command line options are described below.
+
+ -i 00 This option specifies a specific FRU ID to show. The input
+ value should be in hex (0b, 1a, etc.), as shown from the sensor
+ SDR output. The default FRU ID is zero (0).
+
+ -m 002000
+ Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00). This
+ could be used for PICMG or ATCA blade systems. The trailing
+ character, if present, indicates SMI addressing if ’s’, or IPMB
+ addressing if ’i’ or not present.
+
+ -x Causes extra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+PARAMETERS
+ picmg parameters
+
+
+ properties
+ Get PICMG properties may be used to obtain and print
+ Extension major version information, PICMG identifier,
+ FRU Device ID and Max FRU Device ID.
+
+
+ addrinfo
+
+ Get address information. This command may return infor-
+ mation on the Hardware address, IPMB-0 Address, FRU ID,
+ Site/Entity ID, and Site/Entity Type.
+
+ frucontrol fru id options
+
+ Set various control options:
+
+ 0x00 - Cold Reset
+
+ 0x01 - Warm Reset
+
+ 0x02 - Graceful Reboot
+
+ 0x03 - Issue Diagnostic Interrupt
+
+ 0x04 - Quiesce [AMC only]
+
+ 0x05-0xFF - Cold Reset
+
+ activate fru id
+
+ Activate the specified FRU.
+
+ deactivate fru id
+
+ Deactivate the specified FRU.
+
+ policy get fru id
+
+ Get FRU activation policy.
+
+ policy set fru id lockmask lock
+
+ Set FRU activation policy. lockmask is 1 or 0 to indi-
+ cate action on the deactivation or activation locked bit
+ respectively. lock is 1 or 0 to set/clear locked bit.
+
+ portstate set|getall|getgranted|getdenied parameters
+
+ Get or set various port states. See usage for parameter
+ details.
+
+
+
+
+EXAMPLES
+ ipmiutil picmg properties
+ Gets PICMG properties from the default target address (slave address
+ 0x20).
+
+ ipmiutil picmg -N 192.168.1.1 -U root -P pswd addrinfo
+ Gets PICMG Address Information from the specified IP address.
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) idiscover(8) ievents(8) ifru(8)
+ igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.20 IFIREWALL (ipmiutil firewall)
+
+IFIREWALL(8) IFIREWALL(8)
+
+
+
+NAME
+ ipmiutil_firewall - configure the IPMI firmware firewall functions
+
+
+SYNOPSIS
+ ipmiutil firewall [-mxNUPREFJTVY] parameters
+
+
+DESCRIPTION
+ This ipmiutil firewall command supports the IPMI Firmware Firewall
+ capability. It may be used to add or remove security-based restric-
+ tions on certain commands/command sub-functions or to list the current
+ firmware firewall restrictions set on any commands. For each firmware
+ firewall command listed below, parameters may be included to cause the
+ command to be executed with increasing granularity on a specific LUN,
+ for a specific NetFn, for a specific IPMI Command, and finally for a
+ specific command’s sub-function. See Appendix H in the IPMI 2.0 Speci-
+ fication for a listing of any sub-function numbers that may be associ-
+ ated with a particular command.
+
+ This utility can use either the /dev/ipmi0 driver from OpenIPMI, the
+ /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+ direct user-space IOs, or the IPMI LAN interface if -N.
+
+
+OPTIONS
+ Command line options are described below.
+
+ -m 002000
+ Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00). This
+ could be used for PICMG or ATCA blade systems. The trailing
+ character, if present, indicates SMI addressing if ’s’, or IPMB
+ addressing if ’i’ or not present.
+
+ -x Causes extra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+PARAMETERS
+ Parameter syntax and dependencies are as follows:
+
+ firewall [channel H] [lun L [ netfn N [command C [subfn S]]]]
+
+ Note that if "netfn N" is specified, then "lun L" must also be speci-
+ fied; if "command C" is specified, then "netfn N" (and therefore "lun
+ L") must also be specified, and so forth.
+
+ "channel H" is an optional and standalone parameter. If not specified,
+ the requested operation will be performed on the current channel. Note
+ that command support may vary from channel to channel.
+
+ Firmware firewall commands:
+
+ info [(Parms as described above)]
+
+ List firmware firewall information for the specified LUN,
+ NetFn, and Command (if supplied) on the current or speci-
+ fied channel. Listed information includes the support,
+ configurable, and enabled bits for the specified command
+ or commands.
+
+ Some usage examples:
+
+ info [channel H] [lun L]
+
+ This command will list firmware firewall informa-
+ tion for all NetFns for the specified LUN on
+ either the current or the specified channel.
+
+ info [channel H] [lun L [ netfn N ]
+
+ This command will print out all command informa-
+ tion for a single LUN/NetFn pair.
+
+ info [channel H] [lun L [ netfn N [command C] ]]
+
+ This prints out detailed, human-readable informa-
+ tion showing the support, configurable, and
+ enabled bits for the specified command on the
+ specified LUN/NetFn pair. Information will be
+ printed about each of the command subfunctions.
+
+ info [channel H] [lun L [ netfn N [command C [subfn S]]]]
+
+ Print out information for a specific sub-func-
+ tion.
+
+ enable [(Parms as described above)]
+
+ This command is used to enable commands for a given
+ NetFn/LUN combination on the specified channel.
+
+ disable [(Parms as described above)] [force]
+
+ This command is used to disable commands for a given
+ NetFn/LUN combination on the specified channel. Great
+ care should be taken if using the "force" option so as
+ not to disable the "Set Command Enables" command.
+
+ reset [(Parms as described above)]
+
+ This command may be used to reset the firmware firewall
+ back to a state where all commands and command sub-func-
+ tions are enabled.
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) idiscover(8) ievents(8) ifru(8)
+ igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.21 IFWUM (ipmiutil fwum)
+
+IFWUM(8) IFWUM(8)
+
+
+
+NAME
+ ipmiutil_fwum - Update IPMC using Kontron OEM Firmware Update Manager
+
+
+SYNOPSIS
+ ipmiutil fwum [-mixNUPREFJTVY] parameters
+
+
+DESCRIPTION
+ This ipmiutil fwum subcommand updates IPMC firmware using Kontron OEM
+ Firmware Update Manager.
+
+ This utility can use either the /dev/ipmi0 driver from OpenIPMI, the
+ /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+ direct user-space IOs, or the IPMI LAN interface if -N.
+
+
+OPTIONS
+ Command line options are described below.
+
+ -i 00 This option specifies a specific FRU ID to show. The input
+ value should be in hex (0b, 1a, etc.), as shown from the sensor
+ SDR output. The default FRU ID is zero (0).
+
+ -m 002000
+ Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00). This
+ could be used for PICMG or ATCA blade systems. The trailing
+ character, if present, indicates SMI addressing if ’s’, or IPMB
+ addressing if ’i’ or not present.
+
+ -x Causes extra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+PARAMETERS
+ fwum parameters
+
+
+ info
+ Show information about current firmware.
+
+
+ status
+ Show status of each firmware bank present in the hard-
+ ware.
+
+
+ download filename
+ Download the specified firmware image.
+
+
+ upgrade [filename]
+ Install firmware upgrade. If the filename is specified,
+ the file is downloaded first, otherwise the last firmware
+ downloaded is used.
+
+
+ rollback
+ Ask IPMC to rollback to previous version.
+
+
+ tracelog
+ Show the firmware upgrade log.
+
+
+
+EXAMPLES
+ ipmiutil fwum info
+ Gets Firmware information
+
+ ipmiutil fwum -N 192.168.1.1 -U root -P pswd download firmware.img
+ Downloads the firmware version contained in firmware.img over IPMI LAN.
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) idiscover(8) ievents(8) ifru(8)
+ igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.22 IHPM (ipmiutil hpm)
+
+IHPM(8) IHPM(8)
+
+
+
+NAME
+ ipmiutil_hpm - PICMG HPM.1 Upgrade Agent
+
+
+SYNOPSIS
+ ipmiutil hpm [-mxNUPREFJTVY] parameters
+
+
+DESCRIPTION
+ This ipmiutil hpm subcommand updates HPM components using PICMG HPM.1
+ file
+
+ This utility can use either the /dev/ipmi0 driver from OpenIPMI, the
+ /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+ direct user-space IOs, or the IPMI LAN interface if -N.
+
+
+OPTIONS
+ Command line options are described below.
+
+ -m 002000
+ Target a specific MC (e.g. bus 00, sa 20, lun 00). This could
+ be used for PICMG or ATCA blade systems. The trailing charac-
+ ter, if present, indicates SMI addressing if ’s’, or IPMB
+ addressing if ’i’ or not present.
+
+ -x Causes extra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+PARAMETERS
+ hpm parameters
+
+
+ check
+ Check the target information.
+
+
+ check filename
+ Display both the existing target version and image ver-
+ sion on the screen.
+
+
+ download filename
+ Download specified firmware.
+
+
+ upgrade filename [all] [component x] [activate]
+ Upgrade the firmware using a valid HPM.1 image file. If
+ no option is specified, the firmware versions are checked
+ first and the firmware is upgraded only if they are dif-
+ ferent.
+
+
+ all
+ Upgrade all components even if the firmware ver-
+ sions are the same (use this only after using
+ "check" command).
+
+
+ component x
+ Upgrade only given component from the given file.
+ component 0 - BOOT
+ component 1 - RTK
+
+
+ activate
+ Activate new firmware right away.
+
+
+
+ activate
+ Activate the newly uploaded firmware.
+
+
+ targetcap
+ Get the target upgrade capabilities.
+
+
+ compprop id opt
+ Get the specified component properties. Valid component
+ id: 0-7. Opt can be one of following:
+ 0 - General properties
+ 1 - Current firmware version
+ 2 - Description string
+ 3 - Rollback firmware version
+ 4 - Deferred firmware version
+
+
+ abort
+ Abort the on-going firmware upgrade.
+
+
+ upgstatus
+ Show status of the last long duration command.
+
+
+ rollback
+ Perform manual rollback on the IPM Controller firmware.
+
+
+ rollbackstatus
+ Show the rollback status.
+
+
+ selftestresult
+ Query the self test results.
+
+
+
+EXAMPLES
+ ipmiutil hpm targetcap
+ Gets HPM target capabilities
+
+ ipmiutil hpm -N 192.168.1.1 -U root -P pswd download firmware.img
+ Downloads the HPM firmware version contained in firmware.img over IPMI
+ LAN.
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) idiscover(8) ievents(8) ifru(8)
+ igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.23 ISUNOEM (ipmiutil sunoem)
+
+ISUNOEM(8) ISUNOEM(8)
+
+
+
+NAME
+ ipmiutil_sunoem - OEM commands for Sun servers
+
+SYNOPSIS
+ ipmiutil sunoem [-mx -NPRUEFJTVY] commands
+
+
+DESCRIPTION
+ ipmiutil sunoem commands is a program that uses Sun OEM IPMI commands
+ to perform platform-specific functions.
+
+
+OPTIONS
+ -m 002000
+ Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00). This
+ could be used for PICMG or ATCA blade systems. The trailing
+ character, if present, indicates SMI addressing if ’s’, or IPMB
+ addressing if ’i’ or not present.
+
+ -x Causes extra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+COMMANDS
+ led
+
+ These commands provide a way to get and set the status of LEDs
+ on a Sun Microsystems server. Use ’sdr list generic’ to get a
+ list of devices that are controllable LEDs. The ledtype parame-
+ ter is optional and not necessary to provide on the command line
+ unless it is required by hardware.
+
+ get sensorid [ledtype]
+
+ Get status of a particular LED described by a Generic
+ Device Locator record in the SDR. A sensorid of all will
+ get the status of all available LEDS.
+
+ set sensorid ledmode [ledtype]
+
+ Set status of a particular LED described by a Generic
+ Device Locator record in the SDR. A sensorid of all will
+ set the status of all available LEDS to the specified
+ ledmode and ledtype.
+
+ LED Mode is required for set operations:
+ OFF Off
+ ON Steady On
+ STANDBY 100ms on 2900ms off blink rate
+ SLOW 1HZ blink rate
+ FAST 4HZ blink rate
+
+ LED Type is optional:
+ OK2RM Ok to Remove
+ SERVICE Service Required
+ ACT Activity
+ LOCATE Locate
+
+
+ fan speed 0-100
+
+ Set system fan speed (PWM duty cycle).
+
+ sshkey
+
+ set userid keyfile
+
+ This command will allow you to specify an SSH key
+ to use for a particular user on the Service Pro-
+ cessor. This key will be used for CLI logins to
+ the SP and not for IPMI sessions. View available
+ users and their userids with the ’user list’ com-
+ mand.
+
+ del userid
+
+ This command will delete the SSH key for a speci-
+ fied userid.
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8)
+ ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8)
+ iserial(8) isol(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.24 IEKANALYZER (ipmiutil ekanalyzer)
+
+IEKANALYZER(8) IEKANALYZER(8)
+
+
+
+NAME
+ ipmiutil_ekanalyzer - run FRU-Ekeying analyzer with FRU files
+
+SYNOPSIS
+ ipmiutil ekanalyzer [-mx -NPRUEFJTVY] commands (deprecated, see ifru
+ instead)
+
+
+DESCRIPTION
+ ipmiutil ekanalyzer is a program that analyzes FRU Ekeying information
+ from files saved from PICMG IPMI systems.
+
+ ekanalyzer command xx=filename1 xx=filename2 [rc=filename3]
+ NOTE: This command can support a maximum of 8 files per command line
+
+
+ filename1
+ binary file that stores FRU data of a Carrier or an AMC module
+
+
+ filename2
+ binary file that stores FRU data of an AMC module. These binary
+ files can be generated from this command:
+ ipmiutil fru -i id -d filename
+
+
+ filename3
+ configuration file used for configuring On-Carrier Device ID or
+ OEM GUID. This file is optional.
+
+
+ xx indicates the type of the file. It can take the following value:
+ oc : On-Carrier device
+ a1 : AMC slot A1
+ a2 : AMC slot A2
+ a3 : AMC slot A3
+ a4 : AMC slot A4
+ b1 : AMC slot B1
+ b2 : AMC slot B2
+ b3 : AMC slot B3
+ b4 : AMC slot B4
+ sm : Shelf Manager
+
+
+
+OPTIONS
+ -m 002000
+ Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00). This
+ could be used for PICMG or ATCA blade systems. The trailing
+ character, if present, indicates SMI addressing if ’s’, or IPMB
+ addressing if ’i’ or not present.
+
+ -x Causes extra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+COMMANDS
+The available commands for ekanalyzer are:
+
+
+print [carrier | power | all]
+
+ carrier (default) oc=filename1 oc=filename2 ...
+
+ Display point to point physical connectivity between carriers
+ and AMC modules.
+ Example:
+ # ipmiutil ekanalyzer print carrier oc=fru oc=carrierfru
+ From Carrier file: fru
+ Number of AMC bays supported by Carrier: 2
+ AMC slot B1 topology:
+ Port 0 =====> On Carrier Device ID 0, Port 16
+ Port 1 =====> On Carrier Device ID 0, Port 12
+ Port 2 =====> AMC slot B2, Port 2
+ AMC slot B2 topology:
+ Port 0 =====> On Carrier Device ID 0, Port 3
+ Port 2 =====> AMC slot B1, Port 2
+ *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+ From Carrier file: carrierfru
+ On Carrier Device ID 0 topology:
+ Port 0 =====> AMC slot B1, Port 4
+ Port 1 =====> AMC slot B1, Port 5
+ Port 2 =====> AMC slot B2, Port 6
+ Port 3 =====> AMC slot B2, Port 7
+ AMC slot B1 topology:
+ Port 0 =====> AMC slot B2, Port 0
+ AMC slot B1 topology:
+ Port 1 =====> AMC slot B2, Port 1
+ Number of AMC bays supported by Carrier: 2
+
+
+ power xx=filename1 xx=filename2 ...
+
+ Display power supply information between carrier and AMC
+ modules.
+
+ all xx=filename xx=filename ...
+
+ Display both physical connectivity and power supply of each car-
+ rier and AMC modules.
+
+
+frushow xx=filename
+ Convert a binary FRU file into human readable text format. Use -v
+ option to get more display information.
+
+
+summary [match | unmatch | all]
+
+ match (default) xx=filename xx=filename ...
+ Display only matched results of Ekeying match between an On-Car-
+ rier device and an AMC module or between 2 AMC modules. Example:
+ # ipmiutil ekanalyzer summary match oc=fru b1=amcB1 a2=amcA2
+ On-Carrier Device vs AMC slot B1
+ AMC slot B1 port 0 ==> On-Carrier Device 0 port 16
+ Matching Result
+ - From On-Carrier Device ID 0
+ -Channel ID 11 || Lane 0: enable
+ -Link Type: AMC.2 Ethernet
+ -Link Type extension: 1000BASE-BX (SerDES Gigabit) Ethernet
+ link
+ -Link Group ID: 0 || Link Asym. Match: exact match
+ - To AMC slot B1
+ -Channel ID 0 || Lane 0: enable
+ -Link Type: AMC.2 Ethernet
+ -Link Type extension: 1000BASE-BX (SerDES Gigabit) Ethernet
+ link
+ -Link Group ID: 0 || Link Asym. Match: exact match
+ *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+ AMC slot B1 port 1 ==> On-Carrier Device 0 port 12
+ Matching Result
+ - From On-Carrier Device ID 0
+ -Channel ID 6 || Lane 0: enable
+ -Link Type: AMC.2 Ethernet
+ -Link Type extension: 1000BASE-BX (SerDES Gigabit) Ethernet
+ link
+ -Link Group ID: 0 || Link Asym. Match: exact match
+ - To AMC slot B1
+ -Channel ID 1 || Lane 0: enable
+ -Link Type: AMC.2 Ethernet
+ -Link Type extension: 1000BASE-BX (SerDES Gigabit) Ethernet
+ link
+ -Link Group ID: 0 || Link Asym. Match: exact match
+ *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+ On-Carrier Device vs AMC slot A2
+ AMC slot A2 port 0 ==> On-Carrier Device 0 port 3
+ Matching Result
+ - From On-Carrier Device ID 0
+ -Channel ID 9 || Lane 0: enable
+ -Link Type: AMC.2 Ethernet
+ -Link Type extension: 1000BASE-BX (SerDES Gigabit) Ethernet
+ link
+ -Link Group ID: 0 || Link Asym. Match: exact match
+ - To AMC slot A2
+ -Channel ID 0 || Lane 0: enable
+ -Link Type: AMC.2 Ethernet
+ -Link Type extension: 1000BASE-BX (SerDES Gigabit) Ethernet
+ link
+ -Link Group ID: 0 || Link Asym. Match: exact match
+ *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+ AMC slot B1 vs AMC slot A2
+ AMC slot A2 port 2 ==> AMC slot B1 port 2
+ Matching Result
+ - From AMC slot B1
+ -Channel ID 2 || Lane 0: enable
+ -Link Type: AMC.3 Storage
+ -Link Type extension: Serial Attached SCSI (SAS/SATA)
+ -Link Group ID: 0 || Link Asym. Match: FC or SAS interface
+ {exact match}
+ - To AMC slot A2
+ -Channel ID 2 || Lane 0: enable
+ -Link Type: AMC.3 Storage
+ -Link Type extension: Serial Attached SCSI (SAS/SATA)
+ -Link Group ID: 0 || Link Asym. Match: FC or SAS interface
+ {exact match}
+ *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+
+ unmatch xx=filename xx=filename ...
+
+ Display the unmatched results of Ekeying match between an On-
+ Carrier device and an AMC module or between 2 AMC modules
+
+ all xx=filename xx=filename ...
+
+ Display both matched result and unmatched results of Ekeying
+ match between two cards or two modules.
+
+
+SEE ALSO
+ ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifirewall(8)
+ ifru(8) ifruset(8) ifwum(8) igetevent(8) ihealth(8) ihpm(8) ilan(8)
+ ipicmg(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) isunoem(8)
+ iwdt(8) ipmiutil(8) ipmi_port(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.25 ITSOL (ipmiutil tsol)
+
+ITSOL(8) ITSOL(8)
+
+
+
+NAME
+ ipmiutil_tsol - Tyan IPMIv1.5 Serial-Over-LAN Console application
+
+
+SYNOPSIS
+ ipmiutil tsol [recvip] [port=NUM] [ro|rw] [rows=NUM] [cols=NUM] [alt-
+ term]
+
+
+DESCRIPTION
+ This command allows Serial-over-LAN sessions to be established with
+ Tyan IPMIv1.5 SMDC such as the M3289 or M3290. The default command run
+ with no arguments will establish default SOL session back to local IP
+ address. Optional arguments may be supplied in any order.
+
+
+OPTIONS
+ <recv ipaddr>
+ Send receiver IP address to SMDC which it will use to send
+ serial traffic to. By default this detects the local IP
+ address and establishes two-way session. Format of ipaddr is
+ XX.XX.XX.XX
+
+
+ port Configure UDP port to receive serial traffic on. By default
+ this is 6230.
+
+
+ ro|rw Confiure SOL session as read-only or read-write. Sessions
+ are read-write by default.
+
+
+ rows Set terminal rows [default: rows=24]
+
+
+ cols Set terminal columns [default: cols=80]
+
+
+ altterm
+ Alternate terminal setup [default is off]
+
+
+
+EXAMPLES
+ ipmiutil tsol 192.168.1.1
+ Starts a Tyan SOL console session to the IP address.
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8)
+ ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8)
+ iserial(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.26 IDELLOEM (ipmiutil delloem)
+
+IDELLOEM(8) IDELLOEM(8)
+
+
+
+NAME
+ ipmiutil_delloem - OEM commands for Dell servers
+
+SYNOPSIS
+ ipmiutil delloem [-mx -NPRUEFJTVY] commands
+
+
+DESCRIPTION
+ ipmiutil delloem commands is a program that uses Dell OEM IPMI commands
+ to perform platform-specific functions.
+
+
+OPTIONS
+ -m 002000
+ Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00). This
+ could be used for PICMG or ATCA blade systems. The trailing
+ character, if present, indicates SMI addressing if ’s’, or IPMB
+ addressing if ’i’ or not present.
+
+ -x Causes extra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+COMMANDS
+ mac list
+ Lists the MAC address of LOMs
+
+
+ mac get <NIC number>
+ Shows the MAC address of specified LOM. 0-7 System LOM, 8-
+ DRAC/iDRAC.
+
+
+ lan set <Mode>
+ Sets the NIC Selection Mode (dedicated, shared,
+ shared with failover lom2, shared with Failover all
+ loms).
+
+
+ lan get
+ Returns the current NIC Selection Mode (dedicated, shared,
+ shared with failover lom2, shared with Failover all loms).
+
+
+ lan get active
+ Returns the current active NIC (dedicated, LOM1, LOM2, LOM3,
+ LOM4).
+
+
+ powermonitor
+ Shows power tracking statistics
+
+
+ powermonitor clear cumulativepower
+ Reset cumulative power reading
+
+
+ powermonitor clear peakpower
+ Reset peak power reading
+
+
+ powermonitor powerconsumption
+ Displays power consumption in <watt|btuphr>
+
+
+ powermonitor powerconsumptionhistory <watt|btuphr>
+ Displays power consumption history
+
+
+ powermonitor getpowerbudget
+ Displays power cap in <watt|btuphr>
+
+
+ powermonitor setpowerbudget <val> <watt|btuphr|percent>
+ Allows user to set the power cap in <watt|BTU/hr|percentage>
+
+
+ powermonitor enablepowercap
+ To enable set power cap
+
+
+ powermonitor disablepowercap
+ To disable set power cap
+
+
+ windbg start
+ Starts the windbg session (Cold Reset & SOL Activation)
+
+
+ windbg end
+ Ends the windbg session (SOL Deactivation)
+
+
+ vFlash info Card
+ Shows Extended SD Card information
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8)
+ ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8)
+ iserial(8) isol(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.27 IDCMI (ipmiutil dcmi)
+
+IDCMI(8) IDCMI(8)
+
+
+
+NAME
+ ipmiutil_dcmi - handle DCMI functions
+
+
+SYNOPSIS
+ ipmiutil dcmi [-admsx -NUPREFTVY] <function>
+
+
+DESCRIPTION
+ This ipmiutil dcmi subcommand handles DCMI command functions according
+ to the DCMI specification.
+
+ This utility can use either the /dev/ipmi0 driver from OpenIPMI, the
+ /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+ direct user-space IOs, or the IPMI LAN interface if -N.
+
+
+OPTIONS
+ Command line options are described below.
+
+ -a string
+ Set the DCMI Asset Tag to this string.
+
+ -d string
+ Set the DCMI MC ID to this string.
+
+ -m 002000
+ Target a specific MC (e.g. bus 00, sa 20, lun 00). This could
+ be used for PICMG or ATCA blade systems. The trailing charac-
+ ter, if present, indicates SMI addressing if ’s’, or IPMB
+ addressing if ’i’ or not present.
+
+ -s When getting info, also get the DCMI sensor information.
+
+ -x Causes extra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+FUNCTIONS
+ info Get DCMI Capabilities, MC ID, and Asset Tag. This is the default
+ function if no function was specified.
+
+
+ power Get DCMI Power reading and DCMI Power limit, if supported in the
+ DCMI capabilties.
+
+ power set_limit
+ Set Power limit
+
+ power set_action <action>
+ Set Power limit exception action (where action = no_action |
+ power_off | log_sel)
+
+ power set_correction
+ Set Power limit correction time (in ms)
+
+ power set_sample
+ Set Power limit sampling period (in sec)
+
+ power activate
+ Activate Power limit
+
+ power deactivate
+ Deactivate Power limit
+
+
+
+ thermal
+ Get/Set DCMI Thermal parameters. This requires DCMI 1.5 sup-
+ port.
+
+
+ config Get/Set DCMI Configuration parameters. This requires DCMI 1.5
+ support.
+
+
+ help Show the help (usage) message
+
+
+EXAMPLES
+ ipmiutil dcmi info -s
+ Gets DCMI information, plus DCMI sensor information
+
+ ipmiutil dcmi -N 192.168.1.1 -U root -P pswd
+ Gets DCMI information over IPMI LAN.
+
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) idiscover(8) ievents(8) ifru(8)
+ igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8)
+ isol(8) iwdt(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.28 ISMCOEM (ipmiutil smcoem)
+
+ISMCOEM(8) ISMCOEM(8)
+
+
+
+NAME
+ ipmiutil_smcoem - OEM commands for SuperMicro servers
+
+SYNOPSIS
+ ipmiutil smcoem [-mx -NPRUEFJTVY] commands
+
+
+DESCRIPTION
+ ipmiutil smcoem is a function that uses SuperMicro OEM IPMI commands to
+ perform platform-specific functions.
+
+
+OPTIONS
+ -m 002000
+ Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00). This
+ could be used for PICMG or ATCA blade systems. The trailing
+ character, if present, indicates SMI addressing if ’s’, or IPMB
+ addressing if ’i’ or not present.
+
+ -x Causes extra debug messages to be displayed.
+
+ -N nodename
+ Nodename or IP address of the remote target system. If a node-
+ name is specified, IPMI LAN interface is used. Otherwise the
+ local system management interface is used.
+
+ -P/-R rmt_pswd
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -U rmt_user
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 17):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40. Default is 3.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+COMMANDS
+ intrusion
+
+ This command resets any chassis intrusion condition that may
+ have occurred.
+
+
+ bmcstatus [enable|disable]
+ This command gets or sets the BMC service status. Alone, with-
+ out arguments, it gets the BMC status as either enabled or dis-
+ abled. With an argument of either enable or disable, it will
+ also set the BMC status as specified.
+
+
+ firmware
+
+ This command gets the extra firmware version information, if
+ available.
+
+
+
+ lanport [dedicated|lan1|failover]
+ This command gets or sets the IPMI LAN interface port. If set
+ to dedicated, only the dedicated IPMI NIC can be configured for
+ IPMI LAN. If set to lan1, only the first onboard NIC (LAN1) can
+ be configured for IPMI LAN. If set to failover, both the dedi-
+ cated and onboard LAN1 port would be configured for IPMI LAN,
+ with the same IP address.
+
+
+SEE ALSO
+ ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8)
+ ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8)
+ iserial(8) isol(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+--------------------------------------
+3.29 ISELTIME (iseltime)
+
+ISELTIME(8) ISELTIME(8)
+
+
+
+NAME
+ iseltime - synchronize BMC SEL time with OS system time
+
+SYNOPSIS
+ seltime [-sx -NUPRETVF]
+
+
+DESCRIPTION
+ seltime is a program that uses IPMI commands to set the BMC SEL time
+ from the OS system time. The OS system time should be in sync with the
+ BIOS Real-Time-Clock. The OS system time may also be kept from drift-
+ ing via an NTP server. Normally the BIOS will set the BMC time from
+ the RTC during boot, but running this command may be necessary periodi-
+ cally if the system does not reboot for many weeks, for instance. Note
+ that this command should not be run too frequently to avoid BMC timing
+ issues. Once per day should be sufficient.
+
+ Run with no options, this command reads the BMC SEL time without set-
+ ting anything.
+
+ This utility can use either the /dev/ipmi0 openipmi driver, the
+ /dev/imb Intel driver, the /dev/ipmikcs valinux driver, a driverless
+ interface, or IPMI LAN.
+
+
+OPTIONS
+ -s Sets the SEL time (no more than once a day).
+
+ -x Causes eXtra debug messages to be displayed.
+
+
+ -N nodename
+ Nodename of the remote target system. If a nodename is speci-
+ fied, IPMI LAN interface is used. Otherwise the local system
+ management interface is used.
+
+ -P/-R password
+ Remote password for the nodename given. The default is a null
+ password.
+
+ -U username
+ Remote username for the nodename given. The default is a null
+ username.
+
+ -E Use the remote password from Environment variable IPMI_PASSWORD.
+
+ -F drv_t
+ Force the driver type to one of the followng: imb, va, open,
+ gnu, landesk, lan, lan2, lan2i, kcs, smb. Note that lan2i means
+ lan2 with intelplus. The default is to detect any available
+ driver type and use it.
+
+ -J Use the specified LanPlus cipher suite (0 thru 14):
+ 0=none/none/none, 1=sha1/none/none, 2=sha1/sha1/none,
+ 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128, 5=sha1/sha1/xrc4_40,
+ 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+
+ -T Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2,
+ 2=MD5, 4=Straight Password, 5=OEM.
+
+ -V Use a specified IPMI LAN privilege level. 1=Callback level,
+ 2=User level, 3=Operator level, 4=Administrator level (default),
+ 5=OEM level.
+
+ -Y Yes, do prompt the user for the IPMI LAN remote password.
+ Alternatives for the password are -E or -P.
+
+
+
+SEE ALSO
+ ipmiutil(8) isel(8) ievents(8) icmd(8)
+
+
+WARNINGS
+ See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil
+ and any bug fix list.
+
+
+
+--------------------------
+4.0 USE CASES
+--------------------------
+
+----------------------------------------------------------------
+4.1 Usage of IPMI utilities for sensor thresholds
+----------------------------------------------------------------
+
+Get and set the Baseboard Temperature sensor threshold with
+the 'sensor' utility like this:
+# ipmiutil sensor -t
+[...]
+000e SDR Full 01 39 20 sensnum 30 Baseboard Temp = 1d OK 29.00 degrees C
+ hi-crit 65.00 hi-noncr 60.00 lo-noncr 10.00 lo-crit 5.00
+[...]
+Using sensor number 30, index 000e, and the hex raw reading (1d) as a
+baseline from above, we can set the lower threshold above the current
+reading, i.e. 0x1e or 30 C.
+
+# ipmiutil sensor -i 0e -t -n 0x30 -l 30
+sensor: version 1.39
+idx = 0e
+-- BMC version 0.48, IPMI version 1.5
+_ID_ SDR_Type_xx Sz Own Typ S_Num Sens_Description Hex & Interp Reading
+000e SDR Full 01 39 20 sensnum 30 Baseboard Temp = 1d OK 29.00 degrees C
+ hi-crit 65.00 hi-noncr 60.00 lo-noncr 10.00 lo-crit 5.00
+ Setting SDR 000e sensor 30 to lo=1e hi=ff
+GetThreshold[30]: 30 1b 0a 05 00 3c 41 00
+SetThreshold[30]: 30 03 20 1f 1e 00 00 00
+SetSensorThreshold[30] to lo=1e(30.000) hi=ff(0.000), ret = 0
+#
+This sets the lower non-crit to 1e (30 C), and lower crit to 1f (31 C), and
+would cause a sensor threshold event. Note that this utility takes the
+raw threshold value and increments it sequentially for each of the severities.
+Now we should set the lower threshold back to a more normal value of 5 C.
+# ipmiutil sensor -i 0e -t -n 0x30 -l 5
+sensor: version 1.39
+idx = 0e
+-- BMC version 0.48, IPMI version 1.5
+_ID_ SDR_Type_xx Sz Own Typ S_Num Sens_Description Hex & Interp Reading
+000e SDR Full 01 39 20 a 01 snum 30 Baseboard Temp = 1b Crit-lo 27.00 degrees
+C
+ hi-crit 66.00 hi-noncr 60.00 lo-noncr 10.00 lo-crit 5.00
+ Setting SDR 000e sensor 30 to lo=05 hi=ff
+GetThreshold[30]: 30 1b 20 1f 00 3c 42 00
+SetThreshold[30]: 30 03 07 06 05 00 00 00
+SetSensorThreshold[30] to lo=05(5.000) hi=ff(0.000), ret = 0
+#
+The threshold events can be displayed via ipmiutil sel.
+# ipmiutil sel -l4
+4b18 07/17/06 14:33:14 BMC 01 Temperature 30 LoC thresh OK now act=1b thr=06
+4b04 07/17/06 14:33:14 BMC 01 Temperature 30 LoN thresh OK now act=1b thr=07
+4af0 07/17/06 14:26:38 BMC 01 Temperature 30 Lo Crit thresh act=1b thr=1f
+4adc 07/17/06 14:26:38 BMC 01 Temperature 30 Lo Noncrit thresh act=1b thr=20
+#
+
+
+----------------------------------------------------------------
+4.2 How to configure a system for IPMI LAN
+----------------------------------------------------------------
+
+Below is a sample IPMI LAN configuration with IPMI LAN enabled,
+PEF Alerts enabled, and 2 users configured for IPMI LAN.
+
+The key unique LAN parameters that must be configured for basic
+IPMI LAN functionality are: 3,4,5,6,12,13, plus the
+Channel Access Mode and User Access.
+Additional parameters for PEF and SOL are shown below also.
+
+Defaults for required parameters are detected by ipmiutil lan, except
+for the username, password, and the BMC LAN IP if it is not shared.
+The detection uses the OS LAN configuration to find the gateway IP,
+MAC addresses, mask, etc.
+
+# ipmiutil lan -e -u user2 -p password2 [-I 192.168.1.1 ] [-L 3]
+Running "ipmiutil lan -e -u user2 -p password2" would set up all required
+IPMI LAN parameters if the OS and BMC share an IP address. If not,
+the -I parameter should be included to specify the BMC IP.
+You may want to add -G [-H] to specify the gateway IP address [gateway MAC]
+if the OS does not have a NIC on the same subnet.
+To configure an RMM NIC for IPMI LAN, the '-L 3' parameter specifies the
+RMM NIC as IPMI LAN channel 3. Otherwise ipmiutil detects the first
+available IPMI LAN channel and configures it (usually channel 1).
+Note that this also sets up the PEF table for events, but the channel is
+not enabled for PEF events unless an Alert destination is specified,
+either in snmpd.conf or via -A.
+
+Note that the IPMI LAN protocol works only from remote systems.
+The IPMI LAN cannot recognize LAN commands from the local system
+because those requests never really go onto the physical network.
+Use the non-LAN form of a given ipmiutil command (without -N) to run locally.
+
+Below is sample output from a system after being configured for IPMI LAN.
+
+# ipmiutil lan
+ipmiutil ver 2.71
+ilan ver 2.71
+-- BMC version 0.66, IPMI version 2.0
+ilan, GetPefEntry ...
+PEFilter(01): 01 Temperature Sensor event - enabled for alert
+PEFilter(02): 02 Voltage Sensor event - enabled for alert
+PEFilter(03): 04 Fan Failure event - enabled for alert
+PEFilter(04): 05 Chassis Intrusion event - enabled for alert
+PEFilter(05): 08 Power Supply Fault event - enabled for alert
+PEFilter(06): 0c Memory ECC Error event - enabled for alert
+PEFilter(07): 0f BIOS POST Error event - enabled for alert
+PEFilter(08): 07 FRB Failure event - enabled for alert
+PEFilter(09): 13 Fatal NMI event - enabled for alert
+PEFilter(10): 23 Watchdog Timer Reset event - enabled for alert
+PEFilter(11): 12 System Restart event - enabled for alert
+PEFilter(12): 20 OS Critical Stop event - enabled for alert
+PEFilter(13): 09 Power Redundancy Lost event - enabled for alert
+PEFilter(14): 09 Power Unit OK event - enabled for alert
+PEFilter(15): 01 Temperature OK event - enabled for alert
+PEFilter(16): 02 Voltage OK event - enabled for alert
+PEF Control: 01 : PEFenable
+PEF Actions: 2f : Alert PwrDn Reset PwrCyc DiagInt
+PEF Startup Delay: 3c : 60 sec
+PEF Alert Startup Delay: 3c: 60 sec
+PEF Alert Policy[1]: 01 18 11 00 : Chan[1] Dest[1] Enabled
+PEF Alert Policy[2]: 02 00 00 00 : Disabled
+PEF Alert Policy[3]: 03 00 00 00 : Disabled
+PEF Alert Policy[4]: 04 00 00 00 : Disabled
+
+ilan, GetLanEntry for channel 1 ...
+Lan Param(0) Set in progress: 00
+Lan Param(1) Auth type support: 15 : None MD5 Pswd
+Lan Param(2) Auth type enables: 14 14 14 14 00 : MD5 Pswd
+Lan Param(3) IP address: 192 168 1 192
+Lan Param(4) IP addr src: 01 : Static
+Lan Param(5) MAC addr: 00 15 17 8b b4 aa
+Lan Param(6) Subnet mask: 255 255 255 0
+Lan Param(7) IPv4 header: 1e 00 00
+Lan Param(10) BMC grat ARP: 01 : Grat-ARP enabled
+Lan Param(11) grat ARP interval: 04 : 2 sec
+Lan Param(12) Def gateway IP: 192 168 1 200
+Lan Param(13) Def gateway MAC: 00 15 17 8b b4 71
+Lan Param(14) Sec gateway IP: 0 0 0 0
+Lan Param(15) Sec gateway MAC: 00 00 00 00 00 00
+Lan Param(16) Community string: public
+Lan Param(17) Num dest: 04
+Lan Param(18) Dest type: 01 00 01 00 00
+Lan Param(18) Dest type: 02 00 00 00 00
+Lan Param(18) Dest type: 03 00 00 00 00
+Lan Param(18) Dest type: 04 00 00 00 00
+Lan Param(19) Dest address: 01 00 00 [192 168 1 161] 00 07 e9 06 15 31
+Lan Param(19) Dest address: 02 00 00 [0 0 0 0] 00 00 00 00 00 00
+Lan Param(19) Dest address: 03 00 00 [0 0 0 0] 00 00 00 00 00 00
+Lan Param(19) Dest address: 04 00 00 [0 0 0 0] 00 00 00 00 00 00
+Lan Param(192) DHCP Server IP: 0 0 0 0
+Lan Param(193) DHCP MAC Address: 00 00 00 00 00 00
+Lan Param(194) DHCP Enable: 00
+Channel(1=lan) Access Mode: 02 04 : Always Avail, PEF Alerts Enabled
+ilan, GetSOL for channel 1 ...
+SOL Enable: 01 : enabled
+SOL Auth: 82 : User
+SOL Accum Interval: 04 32 : 20 msec
+SOL Retry Interval: 06 14 : 200 msec
+SOL nvol Baud Rate: 0a : 115.2k
+SOL vol Baud Rate: 00 : nobaud
+SOL Payload Support(1): 03 00 15 00 00 00 00 00
+SOL Payload Access(1,1): 02 00 00 00 : enabled
+SOL Payload Access(1,2): 02 00 00 00 : enabled
+SOL Payload Access(1,3): 00 00 00 00 : disabled
+SOL Payload Access(1,4): 00 00 00 00 : disabled
+Users: showing 4 of max 15 users (2 enabled)
+User Access(chan1,user1): 0f 02 01 14 : IPMI, Admin ()
+User Access(chan1,user2): 0f 02 01 14 : IPMI, Admin (root)
+User Access(chan1,user3): 0f 02 01 0f : No access (admin)
+User Access(chan1,user4): 0f 02 01 0f : No access ()
+ipmiutil lan, completed successfully
+
+
+----------------------------------------------------------------
+4.3 Usage of IPMI utilities for Automatic IPMI LAN configuration
+----------------------------------------------------------------
+
+Suppose there are a number of IPMI servers that need to have their
+BMC LAN interface configured. Shell access to the servers
+(via ssh or similar) is assumed.
+
+BMC LAN, Simple case, password is not changed:
+[ssh connection]
+# ipmiutil lan -e
+[ssh exit]
+
+BMC LAN, Complex case, assuming that a password needs to be set and
+that the session text (or script) must encrypt the password.
+So, using the gnupg.org utilities with public/private keys
+would look something like this:
+[ Set up list (or db) of encrypted passwords & key by nodename.
+ Note that the list and keyfile could reside locally, building
+ the ssh script syntax, so that only the encrypted password is
+ exposed remotely. ]
+[ssh connection]
+# gpg --import mykey.file
+# mynode=`uname -n`
+# my_enc_psw=`grep $mynode mylist.file |cut -f2`
+# ipmiutil lan -e -p `gpg --decrypt $my_enc_psw`
+[ssh exit]
+
+----------------------------------------------------------------
+4.4 Usage of IPMI Utilities to Set Watchdog timer
+----------------------------------------------------------------
+
+Watchdog timer coverage over the phases of boot and OS operation:
+ Power-on to end-of-POST = BIOS FRB2
+ end-of-POST to OS Running = BIOS OS Boot Timeout
+ OS User-space operation = SMS Timeout via "ipmiutil wdt"
+Each of these phases uses the same watchdog timer mechanism but initializes
+the timer with different values.
+
+For user-space watchdog control, use "ipmiutil wdt" to read, set, and reset the
+IPMI watchdog timer. There is an init script provided with ipmiutil to
+automate this task.
+# chkconfig --add ipmiutil_wdt (skip this if no chkconfig)
+# /etc/rc.d/init.d/ipmiutil_wdt start
+This sets the watchdog timer to reset the system if the wdt is not
+restarted within 90 seconds. It creates an /etc/cron.d/wdt file to
+restart wdt every 60 seconds.
+This user-space approach is desirable if you wish the watchdog to expire for
+such conditions as out-of-memory or out-of-processes, since the cron job will
+start a short process for each invocation. Note that this also does not require additional services or modules to be running all the time.
+
+Note that the device-independent way to start/stop watchdog timers in
+Linux is to use the /dev/watchdog interface via the OpenIPMI driver.
+
+For kernel-space watchdog management, you could build a custom kernel with
+embedded watchdog support by changing the CONFIG_IPMI_* driver parameters
+to =y in the Linux .config (including CONFIG_IPMI_WATCHDOG) and building the
+kernel. Then edit grub.conf to start the watchdog with the kernel parameter
+"ipmi_watchdog_start_now=1".
+
+
+----------------------------------------------------------------
+4.5 Usage of kernel panic handler code (now CONFIG_IPMI_PANIC_EVENT):
+----------------------------------------------------------------
+
+If a Linux panic occurs, the bmc_panic module will automatically save
+the date/time of the panic, and minimal information about the panic.
+This information will also be sent via SNMP to the remote management console,
+and (if bmcpanic.patch) the Alarms panel LED will be turned on.
+If lkcd is also configured, a full crash-dump of the panic will be saved
+for later analysis.
+After this, the system will automatically reboot.
+This provides instant notification to the administrator, and significantly
+improved post-mortem diagnosis.
+
+Without these features, the administrator may never have any indication that
+the system had crashed, and no way to know how to diagnose and fix the problem.
+
+To enable this, set CONFIG_IPMI_PANIC_EVENT=y and CONFIG_IPMI_PANIC_STRING=y
+in the kernel .config file.
+
+You can also run ipmiutil lan to enable sending an SNMP trap for a kernel
+panic as an "OS Critical Stop" event.
+
+Make sure that the panic timeout is not zero (infinite), by using
+echo "5" > /proc/sys/kernel/panic
+or by adding 'append="panic=5"' to the lilo or grub configuration.
+
+After a panic occurs, you can then use ipmiutil sel to view the firmware
+SEL for that event. It should look something like this:
+# ipmiutil sel
+[...]
+2d04 07/21/04 07:54:22 SMI 20 OS Critical Stop 46 (Fat) 6f [a1 61 74]
+2d18 OEM Event 20 00 Fatal excep
+2d2c OEM Event 20 01 tion
+[...]
+
+
+
+----------------------------------------------------------------
+4.6 Interpreting BMC LAN SNMP Traps from Platform Events.
+----------------------------------------------------------------
+
+There are MIB files provided for BMC LAN SNMP traps with this project.
+They are installed into /usr/share/ipmiutil/bmclan*.mib, and sym-linked
+into /usr/share/snmp/mibs/.
+The Platform Event Traps (enterprises.3183) are defined in bmclanpet.mib.
+The Alert-on-LAN traps (enterprises.3183) are defined in bmclanaol.mib.
+
+Note that Plaform Event Traps also have a 46-byte binary variable bindings
+field included with the trap.
+See Section 12.5 and 12.6 from the Intel ISM 5.x TPS for background.
+
+Actual PET Trap Data from a System Restart Event trap:
+
+snmputil: trap generic=6 specific=1208065
+ from -> 10.243.42.197
+Variable = .iso.org.dod.internet.private.enterprises.3183.1.1.1
+Value = String <0xa4><0x12><0x00><0x5f><0x62><0xa1><0xd5><0x11><0x00><0x80><0x60><0xff><0x94><0x47><0x03><0x00><0x21><0x19><0x0c><0x7f><0x3b><0x12><0xff><0xff><0x20><0x20><0x00><0x01><0x83><0x00><0x00><0x01><0xff><0xff><0x00><0x00><0x00><0x00><0x00><0x19><0x00><0x00><0x01><0x57><0x00><0x0c><0xc1>
+
+Byte Mapping
+Bytes of the trap variable binding data are mapped.
+An extra byte of data is at the end (47).
+
+Byte Data Meaning
+1 0xa4 System GUID (16 bytes)
+2 0x12
+3 0x00
+4 0x5f
+5 0x62
+6 0xa1
+7 0xd5
+8 0x11
+9 0x00
+10 0x80
+11 0x60
+12 0xff
+13 0x94
+14 0x47
+15 0x03
+16 0x00
+17 0x21 Sequence Number/Cookie (2 bytes)
+18 0x19
+19 0x0c Local Timestamp (4 bytes)
+20 0x7f
+21 0x3b
+22 0x12
+23 0xff UTC Offset (2 bytes)
+24 0xff
+25 0x20 Trap Source Type
+26 0x20 Event Source Type
+27 0x00 Event Severity
+28 0x01 Sensor Device
+29 0x83 Sensor Number
+30 0x00 Entity
+31 0x00 Entity Instance
+32 0x01 Event Data (8 bytes max, 3 bytes used)
+33 0xff
+34 0xff
+35 0x00
+36 0x00
+37 0x00
+38 0x00
+39 0x00
+40 0x19 filler byte
+41 0x00 Manufacturer ID (4 bytes, 000157=Intel)
+42 0x00
+43 0x01
+44 0x57
+45 0x00 Product ID (2 bytes)
+46 0x0c
+47 0xc1 extra byte
+
+Also, there is an optional "Extended Platform Event Trap" format defined
+for IPMI which breaks up the 46-byte binary varbind into separate
+varbinds for easier parsing.
+
+See section 4.10 for how to use ipmiutil to perform the configuration and interpretation of IPMI PET traps. For example, the above trap would be interpreted as follows:
+ # events -p 00 80 60 ff 94 47 03 00 21 19 0c 7f 3b 12 ff ff 20 20 00 01 83 00 00 01 ff ff 00 00 00 00 00 19 00 00 01 57 00 0c c1
+events version 2.34
+0019 08/23/04 11:13:06 BMC 12 System Event #83 OEM System Boot 6f [01 ff ff]
+
+
+
+----------------------------------------------------------------
+4.7 Interpreting newer PECI sensors for CPU Thermal Margin
+----------------------------------------------------------------
+
+The newer CPUs do more monitoring internally rather that using absolute
+temperature thresholds from the BMC. The CPU knows best what its
+thresholds should be, and the thresholds may be different for different
+CPUs. So, there are several IPMI sensors that expose the state of the
+CPU temperature via the newer PECI interface.
+
+1) Thermal Margin - A negative value indicating margin to throttling point.
+ Once margin reaches 0, throttling begins
+2) Therm Control % - Reports the percentage of time within a 5.8 second
+ sliding window during which the processor was throttling
+3) VRD Hot - Discrete sensor indicating one of the phases of the processor
+ VRD circuit on the baseboard has exceeded it's limit. This is not
+ indicative of CPU - just the VR circuit on the baseboard.
+
+Therm Margin is the one to watch if you want max performance without
+throttling. If it reaches 0, you will start losing performance to throttling.
+However, the Therm Margin throttling is well in advance of the temperatures
+that would cause a CPU ThermTrip condition and shut off the system.
+
+
+----------------------------------------------------------------
+4.8 How to configure a system for IPMI Serial-Over-LAN Console
+----------------------------------------------------------------
+
+The Serial-Over-LAN (SOL) console configuration requires
+configuring BIOS, BMC/IPMI, and OS parameters.
+Intel S5000 motherboards and prior use Serial Port B (ttyS1) for SOL,
+but Intel S5500 and most other vendors use Serial Port A (ttyS0).
+
+Enter BIOS Setup for Serial Console Redirection parameters:
+(these vary by platform)
+ Console Redirection = Serial Port A
+ ACPI Redirection = Disabled
+ Baud Rate = 19.2K (or 115.2k)
+ Flow Control = CTS/RTS
+ Terminal Type = VT100
+ Legacy Redirection = Enabled or Disabled (optional, for DOS)
+Note that the Baud Rate can vary, but it must match in all
+locations where it is used (BIOS, IPMI, and Linux).
+Some vendors may have OS utilities to change BIOS parameters, for instance,
+Intel BIOS would use 'syscfg /bcs COM1 19200 CTS VT100' to do this.
+
+Run this sample command for IPMI LAN & SOL configuration:
+ ipmiutil lan -e -u user2 -p password2 [-B 115.2k] [-I 192.168.1.1]
+Use the -I portion if your BMC does not share a MAC address
+with the OS. If not specified, the baud rate defaults to either
+19.2k or the baud previously set with "ipmiutil serial", if set.
+If there is more than one IPMI LAN channel, the alternate channel
+can be configured by adding "-L 3" for channel 3.
+
+---- FOR LINUX SERIAL CONSOLE -----
+Edit /boot/grub/grub.conf to:
+ add "console=ttyS0,19200n8" on the end of the kernel line,
+ then comment out the "splashimage=" line
+ and optionally add these lines for grub menu display
+ serial --unit=0 --speed=19200 --word=8 --parity=no --stop=1
+ (use --unit=1 if ttyS1)
+ terminal --timeout=10 serial console
+ (Adding these two lines sometimes does not timeout and continue
+ without user interaction using some grub-0.9x versions.)
+
+If using /etc/inittab, edit it to add:
+ co:2345:respawn:/sbin/agetty -h -L 19200 ttyS0 vt100
+If using Ubuntu, RHEL6, or Fedora 11, the /etc/inittab has been replaced by
+Upstart, with a different procedure.
+
+If using Upstart (Ubuntu, RHEL6), adding the console=ttyS0,19200n8 in grub
+will auto-start everything. Editing the serial init for getty is not
+required. However, if you want to use hardware flow control, change the
+/etc/init/serial.conf last line to:
+ exec /sbin/agetty -h -L $SPEED /dev/$DEV vt100-nav
+
+Edit /etc/securetty to add:
+ ttyS0
+
+Edit $HOME/.bashrc or /etc/bashrc to add:
+ stty crtscts
+Adding "stty crtscts" in your bashrc turns on RTS/CTS flow control
+once you are logged in. Otherwise operations with lots of output may
+miss some chunks of data. Some Linux distributions do not turn this
+on by default.
+
+---- FOR WINDOWS SERIAL CONSOLE -----
+To configure Windows for Serial (System Admin Console),
+these BOOTCFG.EXE commands manipulate the BOOT.INI for SAC:
+BOOTCFG /EMS ON /PORT BIOSSET /ID 1 (Enables SAC)
+BOOTCFG /EMS OFF /ID 1 (Disables SAC)
+
+
+---- FOR FREEBSD SERIAL CONSOLE -----
+Open the file /etc/ttys with an editor and set up a line like this:
+ ttyu0 "/usr/libexec/getty std.19200" vt100 on secure
+For more details, see
+http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/serialconsole-setup.html
+
+
+----------------------------------------------------------------
+4.9 Using ipmiutil Library APIs for custom programs
+----------------------------------------------------------------
+
+The various driver modules and LAN interfaces are included in
+libipmiutil.a which is built by "cd util; make libipmiutil.a".
+The library is named ipmiutil.lib in Windows.
+
+The library is built by default along with the ipmi_sample application
+to show how to use this library. Note that ipmi_sample is linked
+with libcrypto.so (option -lcrypto) in order to support the lanplus
+interface. Only the SOL console function requires lanplus, all other
+functions can use the lan interface, since the IPMI 2.0 firmware is
+required to support both lan and lanplus. If the custom program does
+not require the lanplus interface, it can be reconfigured without
+lanplus by first running './configure --enable-standalone'.
+
+This library provides a common interface to use IPMI commands.
+See section 9.0 for more information about the common library APIs.
+See util/ipmi_sample.c for an example of how these APIs can be used.
+
+
+----------------------------------------------------------------
+4.10 How to configure a system for SNMP Traps via IPMI PEF rules
+----------------------------------------------------------------
+
+The IPMI Platform Event Filter (PEF) actions support sending
+SNMP v1 traps from the IPMI firmware when IPMI events occur,
+regardless of the state of the OS.
+
+1) Configure the server to send IPMI PET traps.
+These can be configured using ipmiutil on the target server
+with ipmiutil. This command will enable the PEF rules
+for SNMP traps.
+ # ipmiutil lan -e -I <bmc_ip> -A <alert_ip> [-k] [-a num]
+The -k option enables PEF rules for the "OK" or clearing traps
+for certain IPMI events.
+Note that several SNMP alert destinations can be specified
+by using the -a num option, where num=1,2,3,4 (1 is the default).
+
+This enables the following PEF rules:
+ PEFilter(01): 01 Temperature Sensor event - enabled for alert
+ PEFilter(02): 02 Voltage Sensor event - enabled for alert
+ PEFilter(03): 04 Fan Failure event - enabled for alert
+ PEFilter(04): 05 Chassis Intrusion event - enabled for alert
+ PEFilter(05): 08 Power Supply Fault event - enabled for alert
+ PEFilter(06): 0c Memory ECC Error event - enabled for alert
+ PEFilter(07): 0f BIOS POST Error event - enabled for alert
+ PEFilter(08): 07 FRB Failure event - enabled for alert
+ PEFilter(09): 13 Fatal NMI event - enabled for alert
+ PEFilter(10): 23 Watchdog Timer Reset event - enabled for alert
+ PEFilter(11): 12 System Restart event - enabled for alert
+ PEFilter(12): 20 OS Critical Stop event - enabled for alert
+ PEFilter(13): 09 Power Redundancy Lost event - enabled for alert
+ PEFilter(14): 09 Power Unit OK event - enabled for alert
+ PEFilter(15): 01 Temperature OK event - enabled for alert
+ PEFilter(16): 02 Voltage OK event - enabled for alert
+Note that Fan failure events do not have a clearing trap because
+a fan failure would usually require removing system power to
+physically replace the fan.
+
+The IPMI Platform Event Traps (PET) can then be tested with these steps:
+
+2) On the trap receiver, start the SNMP services.
+ For Linux, this would be:
+ Optionally edit /etc/snmp/snmpd.conf for a broader view, e.g.:
+ view systemview included .1
+ /etc/init.d/snmpd start
+ /etc/init.d/snmptrapd start
+
+3) On the server under test, cause an event by:
+ a) removing and reinserting a power supply, or
+ b) setting the temperature thresholds out of range:
+ ipmiutil sensor -n 20 -t -h 15
+ (sets the Baseboard Temp high threshold to 15 degrees C)
+ then setting the temperature thresholds back to normal:
+ ipmiutil sensor -n 20 -t -h 61
+ (sets the Baseboard Temp high threshold to 61 degrees C)
+ c) you can see the IPMI events generated by doing:
+ ipmiutil sel
+
+The IPMI PET traps (enterprises.3183) are defined in
+/usr/share/ipmiutil/bmclanpet.mib, and the alert destination system
+(trap receiver) can interpret them with the ipmiutil events utility
+as follows:
+
+4) Get the sensor output from a server of the same type.
+Copy /usr/share/ipmiutil/sensor_out.txt to the system where the
+traps are received. This would not be required if the trap receiver
+and server are both the same type.
+
+5) Get the hex data bytes from the IPMI PET trap.
+This sample was taken from /var/log/messages on a Linux system with snmptrapd:
+Sep 26 11:22:17 chapin1 snmptrapd[19859]: 2008-09-26 11:22:17 ac1-tigw1u-bmc [10.243.42.235] (via 10.243.42.235) TRAP, SNMP v1, community public SNMPv2-SMI::enterprises.3183.1.1 Enterprise Specific Trap (65792) Uptime: 141 days, 11:37:06.13 SNMPv2-SMI::enterprises.3183.1.1.1 = Hex-STRING: B1 D8 4F 76 1D E2 11 DC B3 E8 00 0E 0C C7 1B A0 11 08 14 31 D3 D4 FF FF 20 20 10 20 30 53 44 50 2B 30 00 00 00 00 00 19 00 00 01 57 08 11 C1
+
+6) Skip the first 8 hex bytes from the hex data above and pass the data to
+the ipmiutil events application.
+ # sfil=/usr/share/ipmiutil/sensor_out.txt
+ # ipmiutil events -p -s $sfil B3 E8 00 0E 0C C7 1B A0 11 08 14 31 D3 D4 FF FF 20 20 10 20 30 53 44 50 2B 30 00 00 00 00 00 19 00 00 01 57 08 11 C1
+events version 2.34
+000b SDR Full 01 01 20 a 01 snum 30 Baseboard Temp
+0008 09/26/08 04:50:12 BMC 01 Temperature #30 Lo Noncrit thresh act=2b thr=30
+
+This output should match the output from 'ipmiutil sel' on the server.
+
+See also section 4.6 for the format of the IPMI PET data.
+
+
+
+----------------------------------
+5.0 IPMI UTILITIES ON WINDOWS
+----------------------------------
+
+Sample file contents of the ipmiutil win32/64 zip archive:
+ README.txt - Information about the archive, with install instructions
+ LICENSE.txt - the BSD license
+ UserGuide.txt - the ipmiutil User Guide
+ ChangeLog.txt - change history
+ install.cmd - INSTALL ipmiutil
+ uninstall.cmd - UNINSTALL ipmiutil
+ ipmiutil.exe - meta-command for all of the functions
+ ipmiutil_wdt.cmd - automatically resets the watchdog timer
+ checksel.cmd - automatically checks the SEL for nearly full
+ ialarms.cmd - shortcut for ipmiutil alarms
+ icmd.cmd - shortcut for ipmiutil cmd
+ iconfig.cmd - shortcut for ipmiutil config
+ idiscover.cmd - shortcut for ipmiutil discover
+ ievents.exe - shortcut for ipmiutil events
+ ifru.cmd - shortcut for ipmiutil fru
+ igetevent.cmd - shortcut for ipmiutil getevent
+ ihealth.cmd - shortcut for ipmiutil health
+ ilan.cmd - shortcut for ipmiutil lan
+ isensor.cmd - shortcut for ipmiutil sensor
+ iserial.cmd - shortcut for ipmiutil serial
+ isel.cmd - shortcut for ipmiutil sel
+ isol.cmd - shortcut for ipmiutil sol
+ ireset.cmd - shortcut for ipmiutil reset
+ iwdt.cmd - shortcut for ipmiutil wdt
+ showsel.reg - to add showsel DLL to registry
+ showselun.reg - to remove showsel DLL from registry
+ showselmsg.dll - DLL for System Log IPMI messages
+ libeay32.dll - from openssl crypto
+ ssleay32.dll - from openssl crypto
+ buildsamp.cmd - to build the sample programs
+ ipmiutil.dll - use this with the static library
+ ipmiutil.lib - static library with ipmiutil functions
+ ipmiutillib.dll - Use this for dynamic DLL
+ ipmiutillib.lib - link this into samples to use dynamic DLL
+ ipmiutillib.exp - exported list of ipmiutil functions
+ ipmi_sample.exe - sample application
+ ipmi_sample_evt.exe - sample application with eventing
+
+The install and build instructions are below, all other information
+in the UserGuide.txt is the same for Windows and Linux.
+
+
+----------------------------------
+5.1 WINDOWS INSTALL INSTRUCTIONS
+----------------------------------
+
+If installing from an MSI file, just double-click to run the install wizard.
+
+If installing from the ZIP file, just run install.cmd.
+
+Otherwise, these are the manual steps to perform.
+
+The showselmsg.dll needs to be copied into the %SystemRoot%\System32
+directory and then run showsel.reg, so that the Windows EventLog service
+can find information about the showsel events.
+
+Note that the openssl crypto libraries (libeay32.dll and ssleay32.dll)
+should be copied to %SystemRoot%\System32 also to provide crypto functions
+for the lanplus logic, if they are not already present.
+
+Note that for Windows Vista/7 workstation and later, make sure to
+'Run as administrator' when installing. Windows Server should not
+require this step.
+
+The utilities can be run separately, or an ipmiutil directory can be
+added into the %PATH%.
+
+A sample install batch file:
+> set MYBIN=c:\bin
+> copy libeay32.dll %SystemRoot%\system32
+> copy ssleay32.dll %SystemRoot%\system32
+> copy showselmsg.dll %SystemRoot%\system32
+> start showsel.reg
+> mkdir %MYBIN%
+> copy *.exe %MYBIN%
+
+The usage of ipmiutil in Windows is the same as in Linux OS, with the
+exception of drivers:
+ * The Intel IPMI driver supported is the Intel IMB driver (imbdrv.sys),
+ which can be obtained from the Intel Resource CD for your system,
+ from the ISM CD, or from http://www.intel.com by searching downloads
+ for IMB driver.
+ http://downloadfinder.intel.com/scripts-df-external/Product_Search.aspx?Prod_nm=imb+driver
+ or cached at http://ipmiutil.sf.net/kern/imbdrv130.zip
+ * The Microsoft IPMI driver (ipmidrv.sys), which comes with Windows 2003 R2
+ and later, is also supported.
+
+It should be noted that the two IPMI drivers should not be installed at the
+same time, since they will interfere with each other.
+So, for some systems or applications, you may need to uninstall the Microsoft
+IPMI driver, like this:
+ * start Control Panel/System app
+ * go to Hardware tab, start Device Manager
+ * select View/Show Hidden Devices
+ * go to "System Devices",
+ * right-click "Microsoft Generic IPMI Compliant Device"
+ * select Properties
+ * on driver tab, click "Uninstall"
+ * then reboot.
+
+How to install Intel IPMI driver from the cached copy at http://ipmiutil.sf.net/kern/imbdrv130.zip
+ Extract imbdrv130.zip to c:\temp or similar
+> cd c:\temp
+> cd x86_64 (or 'cd ia32' if 32-bit Windows)
+> install.bat (DeviceSetup.exe install imbdrv.inf *IMBDRV)
+> driverquery (shows the drivers currently installed/running)
+
+How to install the Windows Intel IPMI driver (imbdrv.sys from the Intel CD):
+> cd c:\temp
+> copy d:\ism\software\win32\pi\common\imb*.*
+> copy d:\ism\software\win32\pi\common\win2k*.exe
+> ren imbdrv2k.sys imbdrv.sys
+> copy imbapi.dll %SystemRoot%\system32
+> win2kinstall c:\temp\imbdrv.inf *IMBDRV
+> driverquery (shows the drivers currently installed/running)
+
+Note that when using 32-bit binaries on 64-bit Windows Server installations,
+make sure that the Microsoft VC++ Redistributable package is installed
+(vcredist_x86.exe).
+See http://www.microsoft.com/downloads/details.aspx?familyid=200B2FD9-AE1A-4A14-984D-389C36F85647&displaylang=en
+to download this if needed.
+
+
+
+----------------------------------
+5.2 WINDOWS BUILD INSTRUCTIONS
+----------------------------------
+
+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.
+
+5.2.1 Install Visual Studio
+The build environment assumes that VisualStudio 6.0 VC98 or
+later is installed.
+
+5.2.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
+The above zip contains all of the contributed source used.
+Refer to getopt.c from one of these
+ BSD getopt.c:
+ http://www.openmash.org/lxr/source/src/getopt.c?c=gsm
+ public domain getopt.c:
+ http://www.koders.com/c/fid034963469B932D9D87F91C86680EB08DB4DE9AA3.aspx
+ GNU LGPL getopt.c:
+ http://svn.xiph.org/trunk/ogg-tools/oggsplit/
+Refer to openssl from this link (Apache-style license, not gpl)
+ http://www.openssl.org/source/openssl-0.9.7l.tar.gz.
+
+5.2.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 Visual Studio (2003 .Net), Win2003 DDK, or WinSDK.
+> copy iphlpapi.lib %ipmiutil_dir%\lib
+> copy iphlpapi.h %ipmiutil_dir%\util
+
+5.2.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.
+
+5.2.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
+
+5.2.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
+
+
+5.2.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.
+
+----------------------------------
+5.3 WINDOWS COMMAND USAGE
+----------------------------------
+
+Because of the differences in Linux getopt and the getopt used in
+the Windows build, the order of parameters is more important in Windows.
+
+For example in Linux, the following command usages work, but not in Windows:
+ # ipmiutil cmd 00 20 18 01 -N 192.168.1.154
+ # ipmiutil cmd 00 20 -N 192.168.1.154 18 01
+
+The Windows equivalent would have to put the -N option immediately after
+the subfunction, as shown below:
+ > ipmiutil cmd -N 192.168.1.154 00 20 18 01
+
+
+--------------------------
+6.0 SAMPLE OUTPUT
+--------------------------
+Below is sample ipmiutil output from an Intel TIGW1U server.
+
+# ipmiutil alarms
+ipmiutil ver 2.13
+alarms ver 2.13
+-- BMC version 0.19, IPMI version 2.0
+Alarm LEDs: critical = off major = off minor = off power = off
+Alarm Relays: major = off minor = off
+disk slot 0 LED: off
+disk slot 1 LED: off
+disk slot 2 LED: off
+disk slot 3 LED: off
+disk slot 4 LED: off
+disk slot 5 LED: off
+alarms, completed successfully
+
+# ipmiutil cmd 00 20 18 01
+ipmiutil ver 2.21
+icmd ver 2.21
+This is a test tool to compose IPMI commands.
+Do not use without knowledge of the IPMI specification.
+-- BMC version 0.19, IPMI version 2.0
+respData[len=15]: 20 01 00 19 02 9f 57 01 00 11 08 00 48 00 16
+send_icmd ret = 0
+icmd, completed successfully
+
+# ipmiutil config -s /tmp/bmcconfig.out
+ipmiutil ver 2.21
+bmcconfig ver 1.1
+-- BMC version 0.19, IPMI version 2.0
+### bmcconfig, GetPefEntry ...
+### bmcconfig, GetLanEntry for channel 1 ...
+### bmcconfig, GetSOL for channel 1 ...
+### bmcconfig, GetSerEntry for channel 4 ...
+bmcconfig, completed successfully
+
+# cat /tmp/bmcconfig.out
+PEFParam 6,01: 01 c0 01 01 10 ff ff 01 ff 01 95 0a 00 00 00 00 00 00 00 00 00
+PEFParam 6,02: 02 c0 01 01 10 ff ff 02 ff 01 95 0a 00 00 00 00 00 00 00 00 00
+PEFParam 6,03: 03 c0 01 01 08 ff ff 04 ff 01 95 0a 00 00 00 00 00 00 00 00 00
+PEFParam 6,04: 04 c0 01 01 08 ff ff 05 05 6f 01 00 00 00 00 00 00 00 00 00 00
+PEFParam 6,05: 05 c0 01 01 08 ff ff 08 ff 6f 06 00 00 00 00 00 00 00 00 00 00
+PEFParam 6,06: 06 c0 01 01 10 ff ff 0c 08 6f 02 00 00 00 00 00 00 00 00 00 00
+PEFParam 6,07: 07 c0 01 01 08 ff ff 0f 06 6f 01 00 00 00 00 00 00 00 00 00 00
+PEFParam 6,08: 08 c0 01 01 10 ff ff 07 ff 6f 1c 00 00 00 00 00 00 00 00 00 00
+PEFParam 6,09: 09 c0 01 01 02 ff ff 13 ff 6f 3e 03 00 00 00 00 00 00 00 00 00
+PEFParam 6,10: 0a c0 01 01 01 ff ff 23 03 6f 0e 00 00 00 00 00 00 00 00 00 00
+PEFParam 6,11: 0b c0 01 01 01 ff ff 12 ff 6f 02 00 00 00 00 00 00 00 00 00 00
+PEFParam 6,12: 0c 80 01 01 10 ff ff 20 ff 6f ff 00 00 00 00 00 00 00 00 00 00
+PEFParam 6,13: 0d 80 01 01 08 ff ff 09 ff 0b 02 00 00 00 00 00 00 00 00 00 00
+PEFParam 6,14: 0e 80 01 01 04 ff ff 09 ff 0b 01 00 00 00 00 00 00 00 00 00 00
+PEFParam 6,15: 0f 80 01 01 04 ff ff 01 ff 81 95 0a 00 00 00 00 00 00 00 00 00
+PEFParam 6,16: 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PEFParam 6,17: 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PEFParam 6,18: 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PEFParam 6,19: 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PEFParam 6,20: 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+PEFParam 1: 01
+PEFParam 2: 2f
+PEFParam 3: 3c
+PEFParam 4: 3c
+PEFParam 9,1: 01 18 11 00
+PEFParam 9,2: 02 00 00 00
+PEFParam 9,3: 03 00 00 00
+PEFParam 9,4: 04 00 00 00
+LanParam 0,0: 00
+LanParam 1,0: 15
+LanParam 2,0: 14 14 14 14 00
+LanParam 3,0: 0a f3 2a eb
+LanParam 4,0: 01
+LanParam 5,0: 00 0e 0c c7 1b a2
+LanParam 6,0: ff ff ff 00
+LanParam 7,0: 40 40 10
+LanParam 10,0: 01
+LanParam 11,0: 04
+LanParam 12,0: 0a f3 2a fb
+LanParam 13,0: 00 d0 06 21 eb fc
+LanParam 14,0: 00 00 00 00
+LanParam 15,0: 00 00 00 00 00 00
+LanParam 16,0: 70 75 62 6c 69 63 00 00 00 00 00 00 00 00 00 00 00 00
+LanParam 17,0: 04
+LanParam 18,1: 01 00 01 00 00
+LanParam 18,2: 02 00 00 00 00
+LanParam 18,3: 03 00 00 00 00
+LanParam 18,4: 04 00 00 00 00
+LanParam 19,1: 01 00 00 0a f3 2a d8 00 07 e9 06 15 30
+LanParam 19,2: 02 00 00 00 00 00 00 00 00 00 00 00 00
+LanParam 19,3: 03 00 00 00 00 00 00 00 00 00 00 00 00
+LanParam 19,4: 04 00 00 00 00 00 00 00 00 00 00 00 00
+LanParam 192,0: 00 00 00 00
+LanParam 193,0: 00 00 00 00 00 00
+LanParam 194,0: 00
+ChannelAccess 1: 02 04
+SOLParam 1,0: 01
+SOLParam 2,0: 82
+SOLParam 3,0: 04 32
+SOLParam 4,0: 06 14
+SOLParam 5,0: 0a
+SOLParam 6,0: 00
+SOLPayloadSupport 1: 00 15 00 00 00 00 00
+SOLPayloadAccess 1,1: 02 00 00 00
+SOLPayloadAccess 1,2: 02 00 00 00
+SOLPayloadAccess 1,3: 00 00 00 00
+UserAccess 1,1: 0f 02 01 14
+UserName 1: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# UserPassword 1: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+UserAccess 1,2: 0f 02 01 14
+UserName 2: 75 73 72 32 00 00 00 00 00 00 00 00 00 00 00 00
+# UserPassword 2: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+UserAccess 1,3: 0f 02 01 0f
+UserName 3: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# UserPassword 3: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+UserAccess 1,4: 0f 02 01 0f
+UserName 4: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# UserPassword 4: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+SerialParam 0,0: 00
+SerialParam 1,0: 15
+SerialParam 2,0: 14 14 14 14 00
+SerialParam 3,0: 87
+SerialParam 4,0: 00
+SerialParam 5,0: 00 00 ff ff ff
+SerialParam 6,0: 03
+SerialParam 7,0: 20 0a
+SerialParam 8,0: 16 08
+SerialParam 9,0: 3f 00
+SerialParam 10,0: 01 41 54 45 31 51 30 56 31 58 34 26 44 32 26 43 31
+SerialParam 11,0: 2b 2b 2b 00 00
+SerialParam 12,0: 41 54 48 00 00 00 00 00
+SerialParam 13,0: 41 54 44 00 00 00 00 00
+SerialParam 14,0: 00
+SerialParam 15,0: 70 75 62 6c 69 63 00 00 00 00 00 00 00 00 00 00 00 00
+SerialParam 16,0: 08
+SerialParam 17,1: 01 00 05 03 00
+SerialParam 17,2: 02 00 05 03 00
+SerialParam 17,3: 03 00 05 03 00
+SerialParam 17,4: 04 00 05 03 00
+SerialParam 18,0: 3c
+SerialParam 19,1: 01 00 07
+SerialParam 19,2: 02 00 07
+SerialParam 19,3: 03 00 07
+SerialParam 19,4: 04 00 07
+SerialParam 29,0: 66 11
+ChannelAccess 4: 2b 04
+UserAccess 4,1: 0f 02 01 14
+UserName 1: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# UserPassword 1: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+UserAccess 4,2: 0f 02 01 14
+UserName 2: 75 73 72 32 00 00 00 00 00 00 00 00 00 00 00 00
+# UserPassword 2: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+UserAccess 4,3: 0f 02 01 0f
+UserName 3: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# UserPassword 3: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+UserAccess 4,4: 0f 02 01 0f
+UserName 4: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# UserPassword 4: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+
+# ipmiutil discover -a -b 10.243.42.255
+ipmiutil ver 2.21
+idiscover ver 1.3
+Discovering IPMI Devices:
+1: response from 10.243.42.141
+2: response from 10.243.42.7
+3: response from 10.243.42.14
+4: response from 10.243.42.145
+5: response from 10.243.42.172
+6: response from 10.243.42.182
+7: response from 10.243.42.185
+8: response from 10.243.42.183
+9: response from 10.243.42.184
+10: response from 10.243.42.138
+11: response from 10.243.42.181
+12: response from 10.243.42.179
+13: response from 10.243.42.139
+14: response from 10.243.42.216
+15: response from 10.243.42.210
+16: response from 10.243.42.229
+17: response from 10.243.42.150
+18: response from 10.243.42.120
+19: response from 10.243.42.246
+20: response from 10.243.42.158
+21: response from 10.243.42.168
+22: response from 10.243.42.248
+23: response from 10.243.42.242
+24: response from 10.243.42.243
+25: response from 10.243.42.223
+26: response from 10.243.42.171
+27: response from 10.243.42.174
+28: response from 10.243.42.222
+29: response from 10.243.42.226
+30: response from 10.243.42.228
+31: response from 10.243.42.110
+32: response from 10.243.42.120
+33: response from 10.243.42.128
+34: response from 10.243.42.169
+idiscover: 1 pings sent, 34 responses
+
+# ipmiutil events 18 00 02 02 00 00 00 20 00 04 09 01 6f 44 0f ff
+ipmiutil ver 2.40
+ievents version 2.40
+RecId Date/Time_______ Source_ Evt_Type SensNum Evt_detail - Trig [Evt_data]
+0018 12/31/69 19:00:02 BMC 09 Power Unit #01 AC Lost 6f [44 0f ff]
+ievents, completed successfully
+
+# ipmiutil events -p -s sensor-TIGW1U.out B3 E8 00 0E 0C C7 1B A0 11 08 12 7F 10 90 FF FF 20 20 00 20 02 15 01 41 0F FF
+ipmiutil ver 2.40
+ievents version 2.40
+0023 SDR Comp 02 2b 20 a 09 snum 02 Power Redundancy
+0008 11/01/07 10:13:20 BMC 09 Power Unit #02 Redundancy Lost 0b [41 0f ff]
+ievents, completed successfully
+
+
+# ipmiutil fru
+ipmiutil ver 2.21
+fruconfig: version 2.21
+-- BMC version 0.19, IPMI version 2.0
+SDR[004c] FRU 20 00 0c 01 Baseboard FRU
+SDR[004d] FRU 20 02 15 01 Power Dist FRU
+Component FRU Size : 256
+Product Manufacturer: DELTA
+Product Name : AC-061 B
+Product Part Number : D76441-003
+Product Version : 00
+Product Serial Num : DLD0719000969
+Product Asset Tag :
+Product FRU File ID :
+SDR[004e] FRU 20 03 0a 01 Pwr Supply 1 FRU
+Component FRU Size : 256
+Product Manufacturer: DELTA
+Product Name : DPS-450KBA
+Product Part Number : D40117-007
+Product Version : S6
+Product Serial Num : DLD0721003047
+Product Asset Tag :
+Product FRU File ID :
+SDR[004f] FRU 20 04 0a 02 Pwr Supply 2 FRU
+Component FRU Size : 256
+Product Manufacturer: DELTA
+Product Name : DPS-450KBA
+Product Part Number : D40117-003
+Product Version : S2
+Product Serial Num : DLC0630000244
+Product Asset Tag :
+Product FRU File ID :
+SDR[0050] IPMB 20 00 07 01 Basbrd Mgmt Ctlr
+
+Mainboard FRU Size : 256
+Chassis Type : Rack-Mount Chassis
+Chassis Part Number : TIGW1U
+Chassis Serial Num :
+Chassis OEM Field : TIGW1U
+Board Mfg DateTime : Sun Jun 17 16:11:00 2007
+Board Manufacturer : Intel
+Board Product Name : S5000PHB
+Board Serial Number : CFTW72400602
+Board Part Number : D40552-601
+Board FRU File ID : FRU Ver 0.05
+Board OEM Field :
+Product Manufacturer: Intel
+Product Name : S5000PHB
+Product Part Number : TMWA0201W
+Product Version :
+Product Serial Num : sernum4wd
+Product Asset Tag : asset4wd
+Product FRU File ID :
+Product OEM Field :
+System GUID : b1d84f76-1de2-11dc-b3e8-000e0cc71ba0
+BIOS Version : S5000.86B.10.00.D414.081520081354
+fruconfig, completed successfully
+
+# ipmiutil getevt
+ipmiutil ver 2.21
+getevent ver 2.21
+-- BMC version 0.19, IPMI version 2.0
+event receiver sa = 20 lun = 00
+bmc enables = 0f
+Waiting 120 seconds for an event ...
+got event, sensor_type = 01
+event data: 3c 22 02 7b e6 bf 48 20 00 04 01 30 01 50 2e 33
+223c 09/04/08 09:45:31 BMC 01 Temperature #30 Lo Noncrit thresh act=2e thr=33
+Waiting 120 seconds for an event ...
+got event, sensor_type = 01
+event data: 64 22 02 7d e6 bf 48 20 00 04 01 30 81 50 2e 07
+2264 09/04/08 09:45:33 BMC 01 Temperature #30 LoN thresh OK now act=2e thr=07
+Waiting 120 seconds for an event ...
+get_event timeout
+getevent, completed successfully
+
+# ipmiutil health
+ipmiutil ver 2.21
+bmchealth ver 2.21
+BMC version 0.19, IPMI version 2.0
+BMC manufacturer = 000157 (Intel), product = 0811 (TIGW1U)
+BIOS Version = S5000.86B.10.00.D414.081520081354
+Chassis Status = 01 (on, restore_policy=stay_off)
+Power State = 00 (S0: working)
+Selftest status = 0055 (OK)
+Channel 15 Auth Types:
+ Status = 00, OEM ID 000000 OEM Aux 00
+bmchealth, completed successfully
+
+# ipmiutil lan
+ipmiutil ver 2.21
+pefconfig ver 2.21
+-- BMC version 0.19, IPMI version 2.0
+pefconfig, GetPefEntry ...
+PEFilter(01): 01 Temperature Sensor event - enabled for alert
+PEFilter(02): 02 Voltage Sensor event - enabled for alert
+PEFilter(03): 04 Fan Failure event - enabled for alert
+PEFilter(04): 05 Chassis Intrusion event - enabled for alert
+PEFilter(05): 08 Power Supply Fault event - enabled for alert
+PEFilter(06): 0c Memory ECC Error event - enabled for alert
+PEFilter(07): 0f FRB Failure event - enabled for alert
+PEFilter(08): 07 BIOS POST Error event - enabled for alert
+PEFilter(09): 13 Fatal NMI event - enabled for alert
+PEFilter(10): 23 Watchdog Timer Reset event - enabled for alert
+PEFilter(11): 12 System Restart event - enabled for alert
+PEFilter(12): 20 OS Critical Stop event - enabled for alert
+PEFilter(13): 09 Power Redundancy Lost event - enabled for alert
+PEFilter(14): 09 Power Unit OK event - enabled for alert
+PEFilter(15): 01 Temperature OK event - enabled for alert
+PEF Control: 01 : PEFenable
+PEF Actions: 2f : Alert PwrDn Reset PwrCyc DiagInt
+PEF Startup Delay: 3c : 60 sec
+PEF Alert Startup Delay: 3c: 60 sec
+PEF Alert Policy[1]: 01 18 11 00 : Chan[1] Dest[1] Enabled
+PEF Alert Policy[2]: 02 00 00 00 : Disabled
+PEF Alert Policy[3]: 03 00 00 00 : Disabled
+PEF Alert Policy[4]: 04 00 00 00 : Disabled
+
+pefconfig, GetLanEntry for channel 1 ...
+Lan Param(0) Set in progress: 00
+Lan Param(1) Auth type support: 15 : None MD5 Pswd
+Lan Param(2) Auth type enables: 14 14 14 14 00
+Lan Param(3) IP address: 10 243 42 235
+Lan Param(4) IP addr src: 01 : Static
+Lan Param(5) MAC addr: 00 0e 0c c7 1b a2
+Lan Param(6) Subnet mask: 255 255 255 0
+Lan Param(7) IPv4 header: 40 40 10
+Lan Param(10) BMC grat ARP: 01 : Grat-ARP enabled
+Lan Param(11) grat ARP interval: 04 : 2 sec
+Lan Param(12) Def gateway IP: 10 243 42 251
+Lan Param(13) Def gateway MAC: 00 d0 06 21 eb fc
+Lan Param(14) Sec gateway IP: 0 0 0 0
+Lan Param(15) Sec gateway MAC: 00 00 00 00 00 00
+Lan Param(16) Community string: public
+Lan Param(17) Num dest: 04
+Lan Param(18) Dest type: 01 00 01 00 00
+Lan Param(18) Dest type: 02 00 00 00 00
+Lan Param(18) Dest type: 03 00 00 00 00
+Lan Param(18) Dest type: 04 00 00 00 00
+Lan Param(19) Dest address: 01 00 00 [10 243 42 216] 00 07 e9 06 15 30
+Lan Param(19) Dest address: 02 00 00 [0 0 0 0] 00 00 00 00 00 00
+Lan Param(19) Dest address: 03 00 00 [0 0 0 0] 00 00 00 00 00 00
+Lan Param(19) Dest address: 04 00 00 [0 0 0 0] 00 00 00 00 00 00
+Lan Param(192) DHCP Server IP: 0 0 0 0
+Lan Param(193) DHCP MAC Address: 00 00 00 00 00 00
+Lan Param(194) DHCP Enable: 00
+Channel Access Mode(1=lan): 02 04 : Access = Always Avail, PEF Alerts Enabled
+pefconfig, GetSOL for channel 1 ...
+SOL Enable: 01 : enabled
+SOL Auth: 82 : User
+SOL Accum Interval: 04 32 : 20 msec
+SOL Retry Interval: 06 14 : 200 msec
+SOL nvol Baud Rate: 0a : 115.2k
+SOL vol Baud Rate: 00 : nobaud
+SOL Payload Support(1): 03 00 15 00 00 00 00 00
+SOL Payload Access(1,1): 02 00 00 00 : enabled
+SOL Payload Access(1,2): 02 00 00 00 : enabled
+SOL Payload Access(1,3): 00 00 00 00 : disabled
+SOL Payload Access(1,4): 00 00 00 00 : disabled
+Get User Access(1): 0f 02 01 14 : IPMI, Admin ()
+Get User Access(2): 0f 02 01 14 : IPMI, Admin (usr2)
+Get User Access(3): 0f 02 01 0f : No access ()
+Get User Access(4): 0f 02 01 0f : No access ()
+pefconfig, completed successfully
+
+# ipmiutil reset -n
+ipmiutil ver 2.21
+hwreset ver 2.21
+-- BMC version 0.19, IPMI version 2.0
+Power State = 00 (S0: working)
+hwreset: sending NMI ...
+chassis_reset ok
+hwreset: IPMI_Reset ok
+hwreset, completed successfully
+
+# ipmiutil sel
+ipmiutil ver 2.21
+showsel: version 2.21
+-- BMC version 0.19, IPMI version 2.0
+SEL Ver 51 Support f, Size = 3987 records, Free space = 3553 records
+RecId Date/Time_______ Source_ Evt_Type SensNum Evt_detail - Trig [Evt_data]
+0004 07/16/08 15:17:58 BMC 10 SEL Disabled #09 Log Cleared 6f [42 0f ff]
+0018 07/16/08 15:23:08 BIOS 12 System Event #83 Boot: ClockSync_1 6f [05 00 ff]
+002c 07/16/08 10:23:08 BIOS 12 System Event #83 Boot: ClockSync_2 6f [05 80 ff]
+0040 07/16/08 10:24:37 0033 12 System Event #01 OEM System Booted 6f [01 ff 00]
+0054 07/16/08 10:24:49 BMC 22 ACPI Power State #82 S0/G0 Working 6f [40 0f ff]
+0068 07/16/08 11:12:55 BMC 08 Power Supply #70 Removed ef [40 0f ff]
+007c 07/16/08 11:12:55 BMC 09 Power Unit #02 Redundancy Lost 0b [41 0f ff]
+0090 07/16/08 11:12:55 BMC 09 Power Unit #02 Not Redundant 0b [43 0f ff]
+00a4 07/16/08 11:13:23 BMC 08 Power Supply #70 Inserted 6f [40 0f ff]
+00b8 07/16/08 11:13:23 BMC 09 Power Unit #02 Redundancy OK 0b [40 0f ff]
+00cc 07/16/08 11:31:30 BMC 08 Power Supply #70 Removed ef [40 0f ff]
+00e0 07/16/08 11:31:31 BMC 09 Power Unit #02 Redundancy Lost 0b [41 0f ff]
+00f4 07/16/08 11:31:31 BMC 09 Power Unit #02 Not Redundant 0b [43 0f ff]
+0108 07/16/08 11:31:40 BMC 08 Power Supply #70 Inserted 6f [40 0f ff]
+011c 07/16/08 11:31:41 BMC 09 Power Unit #02 Redundancy OK 0b [40 0f ff]
+0130 07/16/08 11:46:34 BMC 01 Temperature #30 Lo Noncrit thresh act=2f thr=34
+0144 07/16/08 11:46:34 BMC 01 Temperature #30 Lo Crit thresh act=2f thr=33
+0158 07/16/08 11:46:36 BMC 01 Temperature #30 LoN thresh OK now act=2f thr=07
+016c 07/16/08 11:46:36 BMC 01 Temperature #30 LoC thresh OK now act=2f thr=06
+0180 07/16/08 12:00:59 BMC 08 Power Supply #70 Removed ef [40 0f ff]
+0194 07/16/08 12:01:00 BMC 09 Power Unit #02 Redundancy Lost 0b [41 0f ff]
+01a8 07/16/08 12:01:00 BMC 09 Power Unit #02 Not Redundant 0b [43 0f ff]
+01bc 07/16/08 12:01:32 BMC 08 Power Supply #70 Inserted 6f [40 0f ff]
+[...]
+1a08 08/12/08 01:57:20 SMI 20 OS Critical Stop #64 panic(dop) 6f [a1 6f 70]
+1a1c 08/12/08 01:58:08 BMC 2a Session Audit #0a Deactivated User 1 6f [a1 01 11]
+1a30 08/12/08 01:58:18 BMC 2a Session Audit #0a Activated User 1 6f [a0 01 01]
+[...]
+219c 08/27/08 06:29:24 BIOS 12 System Event #83 Boot: ClockSync_1 6f [05 00 ff]
+21b0 08/27/08 06:29:25 BIOS 12 System Event #83 Boot: ClockSync_2 6f [05 80 ff]
+21c4 08/27/08 06:30:18 0033 12 System Event #01 OEM System Booted 6f [01 ff 00]
+21d8 08/27/08 06:30:29 BMC 22 ACPI Power State #82 S0/G0 Working 6f [40 0f ff]
+showsel, completed successfully
+
+# ipmiutil sensor
+ipmiutil ver 2.21
+sensor: version 2.21
+-- BMC version 0.20, IPMI version 2.0
+_ID_ SDR_Type_xx ET Own Typ S_Num Sens_Description Hex & Interp Reading
+0001 SDR Full 01 01 20 a 02 snum 10 BB +1.2V Vtt = be OK 1.20 Volts
+0002 SDR Full 01 01 20 a 02 snum 12 BB +1.5V AUX = bd OK 1.47 Volts
+0003 SDR Full 01 01 20 a 02 snum 13 BB +1.5V = 75 OK 1.52 Volts
+0004 SDR Full 01 01 20 a 02 snum 14 BB +1.8V = af OK 1.78 Volts
+0005 SDR Full 01 01 20 a 02 snum 15 BB +3.3V = c1 OK 3.32 Volts
+0006 SDR Full 01 01 20 a 02 snum 16 BB +3.3V STB = bf OK 3.29 Volts
+0007 SDR Full 01 01 20 a 02 snum 17 BB +1.5V ESB = be OK 1.48 Volts
+0008 SDR Full 01 01 20 a 02 snum 18 BB +5V = c3 OK 5.07 Volts
+0009 SDR Full 01 01 20 a 02 snum 1a BB +12V AUX = c1 OK 11.97 Volts
+000a SDR Full 01 01 20 a 02 snum 1b BB +0.9V = ba OK 0.89 Volts
+000b SDR Full 01 01 20 a 01 snum 30 Baseboard Temp = 2d OK 45.00 degrees C
+000c SDR Full 01 01 20 a 01 snum 32 Front Panel Temp = 1a OK 26.00 degrees C
+000d SDR Full 01 01 20 a 01 snum 48 Mem Therm Margin = 00 Init 0.00 degrees C
+000e SDR Full 01 01 20 m 04 snum 50 Fan 1A = 6f OK 7659.00 RPM
+000f SDR Full 01 01 20 m 04 snum 51 Fan 1B = 6b OK 5457.00 RPM
+0010 SDR Full 01 01 20 m 04 snum 52 Fan 2A = 69 OK 7245.00 RPM
+0011 SDR Full 01 01 20 m 04 snum 53 Fan 2B = 6b OK 5457.00 RPM
+0012 SDR Full 01 01 20 m 04 snum 54 Fan 3A = 6c OK 7452.00 RPM
+0013 SDR Full 01 01 20 m 04 snum 55 Fan 3B = 6b OK 5457.00 RPM
+0014 SDR Full 01 01 20 m 04 snum 56 Fan 4A = 6f OK 7659.00 RPM
+0015 SDR Full 01 01 20 m 04 snum 57 Fan 4B = 69 OK 5355.00 RPM
+0016 SDR Full 01 01 20 m 04 snum 58 Fan 5 = 63 OK 6534.00 RPM
+0017 SDR Full 01 01 20 a 03 snum 78 PS1 AC Current = 05 OK 0.31 Amps
+0018 SDR Full 01 01 20 a 03 snum 79 PS2 AC Current = 16 OK 1.39 Amps
+0019 SDR Full 01 01 20 a 03 snum 7a PS1 +12V Current = 01 OK 0.50 Amps
+001a SDR Full 01 01 20 a 03 snum 7b PS2 +12V Current = 12 OK 9.00 Amps
+001b SDR Full 01 01 20 a 0b snum 7c PS1 +12V Power = 01 OK 4.00 Watts
+001c SDR Full 01 01 20 a 0b snum 7d PS2 +12V Power = 1b OK 108.00 Watts
+001d SDR Full 01 01 20 a 01 snum 99 P1 Therm Margin = c7 OK -57.00 degrees C
+001e SDR Full 01 01 20 m 01 snum c0 P1 Therm Ctrl % = 00 OK 0.00 unspecified
+001f SDR Full 01 01 20 a 02 snum d0 Proc 1 Vccp = b0 OK 1.09 Volts
+0020 SDR Comp 02 6f 20 a 09 snum 01 Power Unit = 00 c0 00 00 Enabled
+0021 SDR Comp 02 0b 20 a 09 snum 02 Power Redundancy = 00 c0 01 00 Redundant
+0022 SDR Comp 02 6f 20 a 23 snum 03 BMC Watchdog = 00 c0 00 00 OK
+0023 SDR Comp 02 6f 20 a 06 snum 04 Scrty Violation = 00 c0 00 00 OK
+0024 SDR Comp 02 6f 20 a 13 snum 07 FP Interrupt = 00 c0 00 00 OK
+0025 SDR Comp 02 6f 20 a 10 snum 09 Event Log Clear = 00 c0 00 00 OK
+0026 SDR Comp 02 6f 20 a 2a snum 0a Session Audit = 00 c0 00 00 Activated
+0027 SDR Comp 02 6f 20 a 12 snum 0b System Event = 00 c0 00 00 OK
+0028 SDR Comp 02 6f 20 a 29 snum 1e BB Vbat = 00 c0 00 00 OK
+0029 SDR Comp 02 6f 20 a 08 snum 70 PS1 Status = 00 c0 01 00 Present
+002a SDR Comp 02 6f 20 a 08 snum 71 PS2 Status = 00 c0 01 00 Present
+002b SDR Comp 02 6f 20 a 22 snum 82 ACPI State = 00 c0 01 00 Working
+002c SDR Comp 02 6f 20 a 14 snum 84 Button = 00 c0 00 00 OK
+002d SDR Comp 02 03 20 a f3 snum 85 SMI Timeout = 00 c0 01 00 Enabled
+002e SDR Comp 02 03 20 a c0 snum 87 NMI State = 00 c0 01 00 Enabled
+002f SDR Comp 02 03 20 a c0 snum 88 SMI State = 00 80 01 00 Enabled
+0030 SDR Comp 02 6f 20 m 07 snum 90 Processor 1 Stat = 00 c0 80 00 ProcPresent
+0031 SDR Comp 02 6f 20 a 13 snum a0 PCIe Link0 = 00 c0 00 00 OK
+0032 SDR Comp 02 6f 20 a 13 snum a1 PCIe Link1 = 00 c0 00 00 OK
+0033 SDR Comp 02 6f 20 a 13 snum a2 PCIe Link2 = 00 c0 00 00 OK
+0034 SDR Comp 02 6f 20 a 13 snum a3 PCIe Link3 = 00 c0 00 00 OK
+0035 SDR Comp 02 6f 20 a 13 snum a4 PCIe Link4 = 00 c0 00 00 OK
+0036 SDR Comp 02 6f 20 a 13 snum a5 PCIe Link5 = 00 c0 00 00 OK
+0037 SDR Comp 02 6f 20 a 13 snum a6 PCIe Link6 = 00 c0 00 00 OK
+0038 SDR Comp 02 6f 20 a 13 snum a7 PCIe Link7 = 00 c0 00 00 OK
+0039 SDR Comp 02 6f 20 a 13 snum a8 PCIe Link8 = 00 c0 00 00 OK
+003a SDR Comp 02 6f 20 a 13 snum a9 PCIe Link9 = 00 c0 00 00 OK
+003b SDR Comp 02 6f 20 a 13 snum aa PCIe Link10 = 00 c0 00 00 OK
+003c SDR Comp 02 6f 20 a 13 snum ab PCIe Link11 = 00 c0 00 00 OK
+003d SDR Comp 02 6f 20 a 13 snum ac PCIe Link12 = 00 c0 00 00 OK
+003e SDR Comp 02 6f 20 a 13 snum ad PCIe Link13 = 00 c0 00 00 OK
+003f SDR Comp 02 05 20 m 01 snum c8 CPU1 VRD Temp = 00 c0 00 00 OK*
+0040 SDR Comp 02 05 20 a 02 snum d2 CPU1 Vcc OOR = 00 c0 00 00 OK
+0041 SDR Comp 02 03 20 a 07 snum d8 CPU Popul Error = 00 c0 00 00 OK
+0042 SDR Comp 02 6f 20 a 21 snum e0 DIMM 1A = 00 c0 04 00 Present
+0043 SDR Comp 02 6f 20 a 21 snum e1 DIMM 2A = 00 e0 40 00 NotAvailable
+0044 SDR Comp 02 6f 20 a 21 snum e2 DIMM 3A = 00 e0 40 00 NotAvailable
+0045 SDR Comp 02 6f 20 a 21 snum e3 DIMM 1B = 00 c0 04 00 Present
+0046 SDR Comp 02 6f 20 a 21 snum e4 DIMM 2B = 00 e0 40 00 NotAvailable
+0047 SDR Comp 02 6f 20 a 21 snum e5 DIMM 3B = 00 e0 40 00 NotAvailable
+0048 SDR Comp 02 6f 20 a 0c snum ec Mem A Error = 00 c0 00 00 OK
+0049 SDR Comp 02 6f 20 a 0c snum ed Mem B Error = 00 c0 00 00 OK
+004a SDR Comp 02 6f 20 a 25 snum f0 DIMM Spare Enb = 00 e0 40 00 NotAvailable
+004b SDR Comp 02 0b 20 a 0c snum f1 DIMM Spare Redu = 00 e0 40 00 NotAvailable
+004c SDR FRU 11 18 dev: 20 00 80 00 0c 01 Baseboard FRU
+004d SDR FRU 11 19 dev: 20 02 80 00 15 01 Power Dist FRU
+004e SDR FRU 11 1b dev: 20 03 80 00 0a 01 Pwr Supply 1 FRU
+004f SDR FRU 11 1b dev: 20 04 80 00 0a 02 Pwr Supply 2 FRU
+0050 SDR IPMB 12 1b dev: 20 00 bf 07 01 Basbrd Mgmt Ctlr
+0051 SDR OEM c0 09 Intel: 02 02 00 01 70 71
+0052 SDR OEM c0 05 Intel: 06 01
+0053 SDR OEM c0 19 Intel: 0b 01 01 32 14 f0 0a a4 01 96 00 61 00 08 0a 64 00 05 00 00 00 00
+0054 SDR OEM c0 19 Intel: 0b 02 01 32 14 f0 0a a4 01 ff ff ff ff 10 14 ff ff 06 00 00 00 00
+0055 SDR OEM c0 19 Intel: 0b 01 02 32 14 f0 0a a4 01 96 00 61 00 08 0a 64 00 05 00 00 00 00
+0056 SDR OEM c0 19 Intel: 0b 02 02 32 14 f0 0a a4 01 ff ff ff ff 10 14 ff ff 06 00 00 00 00
+0057 SDR OEM c0 2c Intel: 0c 01 30 64 64 01 02 03 30 20 32 64 01 90 0d 00 2b 20 30 21 35 22 3a 23 3f 24 43 25 47 26 4c 27 51 28 56 29 5b 2a 60 2b 64
+0058 SDR OEM c0 2c Intel: 0c 02 30 64 64 01 02 03 30 20 32 64 01 90 0d 00 2b 20 30 21 35 22 3a 23 3f 24 43 25 47 26 4c 27 51 28 56 29 5b 2a 60 2b 64
+0059 SDR OEM c0 2c Intel: 0c 03 30 64 64 01 02 03 30 20 32 64 01 90 0d 00 2b 20 30 21 35 22 3a 23 3f 24 43 25 47 26 4c 27 51 28 56 29 5b 2a 60 2b 64
+005a SDR OEM c0 15 Intel: 0c 01 30 64 64 01 02 03 00 20 99 64 02 90 01 06 00 11
+005b SDR OEM c0 15 Intel: 0c 01 30 64 64 01 02 03 00 20 48 00 02 b8 01 02 00 00
+005c SDR OEM c0 15 Intel: 0c 02 30 64 64 01 02 03 00 20 99 64 02 90 01 06 00 11
+005d SDR OEM c0 15 Intel: 0c 03 30 64 64 01 02 03 00 20 30 64 02 90 01 02 3c 00
+005e SDR OEM c0 0e Intel: 08 00 00 45 88 45 88 45 88 45 88
+005f SDR OEM c0 16 Intel: 09 00 00 90 33 90 33 90 33 90 33 90 33 90 33 68 42 68 42
+0060 SDR OEM c0 08 Intel: BMC_TAM0 60 01 03 01 20 nrec=4 cfg=01
+0061 SDR OEM c0 31 Intel: BMC_TAM1 60 01 13 00 20 41 01 01 01 23 71 93 41 02 01 02 24 72 94 41 03 01 02 24 72 94 21 04 01 01 23 11 02 05 14 31 29 6f 01 13 23 21 09 0b 14 34
+0062 SDR OEM c0 31 Intel: BMC_TAM2 60 01 23 00 20 71 07 6f 03 13 23 33 43 55 83 11 08 6f 14 21 09 6f 54 64 20 7c 01 72 94 20 7d 01 72 94 11 21 6f 03 53 23 6f 05 15 25 35 85
+0063 SDR OEM c0 17 Intel: BMC_TAM3 60 01 33 00 c0 22 02 00 03 51 22 03 00 03 51 22 04 00 03 51
+0064 SDR OEM c0 0e Intel: SDR File 18
+0065 SDR OEM c0 11 Intel: SDR Package 18
+ SDR IPMI sensor: Power On Hours = 6923 hours
+sensor, completed successfully
+
+# ipmiutil serial
+ipmiutil ver 2.21
+tmconfig ver 2.21
+-- BMC version 0.19, IPMI version 2.0
+Code 0 SEL Ver 81 Support 15
+tmconfig: GetSerEntry for channel 4 ...
+Serial Param(0) Set in progress: 00
+Serial Param(1) Auth type support: 15 : None MD5 Pswd
+Serial Param(2) Auth type enables: 14 14 14 14 00
+Serial Param(3) Connection Mode: 87
+Serial Param(4) Sess Inactiv Timeout: 00 : infinite
+Serial Param(5) Channel Callback: 00 00 ff ff ff
+Serial Param(6) Session Termination: 03
+Serial Param(7) IPMI Msg Comm: 20 0a : no_flow, DTR, 115.2k
+Serial Param(8) Mux Switch: 16 08
+Serial Param(9) Modem Ring Time: 3f 00
+Serial Param(10) Modem Init String: 01 ATE1Q0V1X4&D2&C1
+Serial Param(11) Modem Escape Seq: +++
+Serial Param(12) Modem Hangup Seq: ATH
+Serial Param(13) Modem Dial Command: ATD
+Serial Param(14) Page Blackout Interval: 00
+Serial Param(15) Community String: public
+Serial Param(16) Num of Alert Dest: 08
+Serial Param(17) Destination Info: 01 00 05 03 00
+Serial Param(17) Destination Info: 02 00 05 03 00
+Serial Param(17) Destination Info: 03 00 05 03 00
+Serial Param(17) Destination Info: 04 00 05 03 00
+Serial Param(17) Destination Info: 05 00 05 03 00
+Serial Param(17) Destination Info: 06 00 05 03 00
+Serial Param(17) Destination Info: 07 00 05 03 00
+Serial Param(17) Destination Info: 08 00 05 03 00
+Serial Param(18) Call Retry Interval: 3c
+Serial Param(19) Destination Comm Settings: 01 00 07 : no_flow, 8N1, 19.2k
+Serial Param(19) Destination Comm Settings: 02 00 07 : no_flow, 8N1, 19.2k
+Serial Param(19) Destination Comm Settings: 03 00 07 : no_flow, 8N1, 19.2k
+Serial Param(19) Destination Comm Settings: 04 00 07 : no_flow, 8N1, 19.2k
+Serial Param(19) Destination Comm Settings: 05 00 07 : no_flow, 8N1, 19.2k
+Serial Param(19) Destination Comm Settings: 06 00 07 : no_flow, 8N1, 19.2k
+Serial Param(19) Destination Comm Settings: 07 00 07 : no_flow, 8N1, 19.2k
+Serial Param(19) Destination Comm Settings: 08 00 07 : no_flow, 8N1, 19.2k
+Serial Param(20) Number Dial Strings: 06
+Serial Param(21) Dest Dial String: 01 01
+Serial Param(21) Dest Dial String: 02 01
+Serial Param(21) Dest Dial String: 03 01
+Serial Param(21) Dest Dial String: 04 01
+Serial Param(21) Dest Dial String: 05 01
+Serial Param(21) Dest Dial String: 06 01
+Serial Param(22) Number Dest IP Addrs: 04
+Serial Param(23) Dest IP Address: 01 0 0 0 0
+Serial Param(23) Dest IP Address: 02 0 0 0 0
+Serial Param(23) Dest IP Address: 03 0 0 0 0
+Serial Param(23) Dest IP Address: 04 0 0 0 0
+Serial Param(29) Terminal Mode Config: 66 11
+Channel Access Mode(4=Ser): 2b 04 : Access = Shared, PEF Alerts Disabled
+Get User Access (1): 0f 02 01 14 : IPMI, Admin ()
+Get User Access (2): 0f 02 01 14 : IPMI, Admin (usr2)
+Get User Access (3): 0f 02 01 0f : No access ()
+Get User Access (4): 0f 02 01 0f : No access ()
+Get Serial MUX Status: 04
+Get Boot Options(3): 01 03 00
+tmconfig, completed successfully
+
+# ipmiutil sol -a -N 10.243.42.136
+ipmiutil ver 2.21
+isolconsole ver 2.21
+Opening connection to node 10.243.42.136 ...
+Connected to node 10.243.42.136 10.243.42.136
+-- BMC version 0.17, IPMI version 2.0
+Opening connection to node 10.243.42.136 ...
+[SOL session is running, use '~' to end session.]
+
+isolconsole exit via user input
+isolconsole, completed successfully
+
+# ipmiutil wdt
+ipmiutil ver 2.21
+wdt ver 2.21
+-- BMC version 0.19, IPMI version 2.0
+wdt data: 01 01 00 00 00 00 00 00
+Watchdog timer is stopped for use with BIOS FRB2. Logging
+ pretimeout is 0 seconds, pre-action is None
+ timeout is 0 seconds, counter is 0 seconds
+ action is Hard Reset
+
+wdt, completed successfully
+
+# ipmi_port
+ipmi_port ver 1.1
+open_rmcp_port(623) succeeded, sleeping
+
+
+--------------------------
+7.0 PROBLEMS
+--------------------------
+Note that each utility function has an option for extra debug output (-x),
+which can be used to find out the specific function which returned an
+error.
+
+For best-effort support, email the ipmiutil-developer mailing list:
+ http://lists.sourceforge.net/lists/listinfo/ipmiutil-developers
+or enter a bug report at:
+ http://sourceforge.net/tracker/?group_id=116222&func=browse
+
+7.1 ERROR RETURN CODES
+
+Return code = 0 means success, negative numbers indicate failure, and a
+positive return code represents an IPMI completion code.
+RetCode Description
+------ -----------------------------------------
+ 0 "completed successfully"
+ -1 "error -1", a generic error, usually returned by an OS routine
+ -2 "send to BMC failed" over IPMI LAN
+ -3 "receive from BMC failed" over IPMI LAN
+ -4 "cannot connect to BMC" over IPMI LAN
+ -5 "abort signal caught", the user pressed Ctl-C
+ -6 "timeout occurred", the timeout for a response expired
+ -7 "length greater than max", length supplied was too big
+ -8 "invalid lan parameter", invalid parameter for IPMI LAN function
+ -9 "request not supported", a requested function is not supported
+ -10 "receive too short", did not receive the minimum number of bytes
+ -11 "error resolving hostname" neither DNS or hosts could resolve to an IP
+ -12 "error during ping" could not perform the RMCP ping function
+ -13 "BMC only supports lan v1". LAN 2.0 (lanplus) was attempted, but this
+ BMC firmware only supports IPMI LAN 1.x
+ -14 "BMC only supports lan v2". LAN 1.x was attempted, but this BMC
+ supports LAN 2.0 but not LAN 1.x, which violates the IPMI 2.0 spec.
+ -15 "other error", an unknown error occurred
+ -16 "cannot open IPMI driver". No IPMI driver could be opened. Since
+ the driverless mode is also attempted, this usually means that the
+ user does not have root privilege.
+ -17 "invalid parameter" a parameter was out of bounds
+ -18 "access not allowed" user does not have access to this file or function
+ -19 "session dropped by BMC" the BMC firmware aborted the IPMI session
+ -20 "cannot open file" cannot open the specified file
+ -21 "item not found" requested item was not found
+ -22 "usage or help requested", the user requested usage/help
+ -23 "bad format", the data format is invalid, cannot proceed
+-504 "error getting msg from BMC" during driverless I/Os, a command did
+ not get a response.
+
+7.2 IPMI COMPLETION CODES
+
+IPMI Completion Codes are defined in IPMI 1.5, Table 5-2, and are also
+included below in both hex and decimal format. Note that the meaning of
+completion codes 0x80-0x9f may vary depending on the command.
+
+Code Dec Description
+---- --- -----------------------------------------
+0x00, 0, "Command completed successfully",
+0x80, 128, "Invalid Session Handle or Empty Buffer",
+0x81, 129, "Lost Arbitration",
+0x82, 130, "Bus Error",
+0x83, 131, "NAK on Write - busy",
+0x84, 132, "Truncated Read",
+0xC0, 192, "Node Busy",
+0xC1, 193, "Invalid Command",
+0xC2, 194, "Command invalid for given LUN",
+0xC3, 195, "Timeout while processing command",
+0xC4, 196, "Out of space",
+0xC5, 197, "Invalid Reservation ID, or cancelled",
+0xC6, 198, "Request data truncated",
+0xC7, 199, "Request data length invalid",
+0xC8, 200, "Request data field length limit exceeded",
+0xC9, 201, "Parameter out of range",
+0xCA, 202, "Cannot return requested number of data bytes",
+0xCB, 203, "Requested sensor, data, or record not present",
+0xCC, 204, "Invalid data field in request",
+0xCD, 205, "Command illegal for this sensor/record type",
+0xCE, 206, "Command response could not be provided",
+0xCF, 207, "Cannot execute duplicated request",
+0xD0, 208, "SDR Repository in update mode, no response",
+0xD1, 209, "Device in firmware update mode, no response",
+0xD2, 210, "BMC initialization in progress, no response",
+0xD3, 211, "Destination unavailable",
+0xD4, 212, "Cannot execute command. Insufficient privilege level",
+0xD5, 213, "Cannot execute command. Request parameters not supported",
+0xFF, 255, "Unspecified error"
+
+
+-------------------------------
+8.0 BUILDING IPMI UTILITIES
+-------------------------------
+
+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.
+
+To get the ipmiutil source:
+
+Download the latest released ipmiutil-*.tar.gz from
+http://sourceforge.net/projects/ipmiutil/files/
+
+Or download a tar.gz of the current subversion trunk with the latest source
+http://ipmiutil.svn.sourceforge.net/viewvc/ipmiutil/trunk/?view=tar
+
+Or, if you have subversion installed, you can check out the latest source
+by doing:
+# svn co https://ipmiutil.svn.sourceforge.net/svnroot/ipmiutil ipmiutil
+
+See also section 4.9 for information about building custom applications
+using ipmiutil library APIs. The ipmi_sample.c shows a sample application
+using the ipmiutil library.
+
+
+8.1 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 --enable-standalone"
+builds it without lanplus libs and without GPL code.
+Only the SOL console function requires lanplus, all other functions can
+use the lan interface, since the IPMI 2.0 firmware is required to support
+both lan and lanplus. However, lanplus does have more secure encryption,
+as provided by libcrypto.
+
+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".
+
+
+8.2 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.
+
+ 1) Install Visual Studio (e.g. VS 6.0 or VC98)
+
+ 2) Download contrib files from
+ http://ipmiutil.sf.net/FILES/ipmiutil-contrib.zip
+ and see section 5.2 for getopt.c and openssl.
+
+ 3) Copy initial contrib files into ipmiutil
+ See section 5.2.3 for details
+
+ 4) Build the openssl libraries according to its INSTALL.W32
+
+ 5) Copy the resulting openssl LIB and DLL binaries to ipmiutil
+
+ 6) Set the Visual C variables
+ Example: "C:\Program Files\Microsoft Visual Studio 8\VC\bin\vcvars32.bat"
+
+ 7) Run buildwin.cmd
+ buildwin.cmd will build all of the Windows EXE and DLL files.
+
+
+8.3 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
+
+
+8.4 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
+
+
+8.5 Build instructions for ARM (Android)
+
+# tar -xzvf ipmiutil-${iver}.tar.gz
+# cd ipmiutil-${iver}
+# ./configure --enable-standalone --host=arm
+# make
+
+
+-----------------------------
+10.0 IPMIUTIL LIBRARY APIS
+-----------------------------
+
+Below are some common routines available in the ipmiutil library.
+Also refer to util/ipmi_sample.c for an example of how these APIs are used.
+
+/*
+ * ipmi_cmd
+ * ushort cmd (input): (netfn << 8) + command
+ * uchar *pdata (input): pointer to ipmi data
+ * int sdata (input): size of ipmi data
+ * uchar *presp (output): pointer to response data buffer
+ * int *sresp (input/output): on input, size of response buffer,
+ * on output, length of response data
+ * uchar *cc (output): completion code
+ * char fdebugcmd(input): flag =1 if debug output desired
+ * returns 0 if successful, <0 if error
+ */
+int ipmi_cmd(ushort cmd, uchar *pdata, int sdata, uchar *presp,
+ int *sresp, uchar *pcc, char fdebugcmd);
+/*
+ * ipmi_cmdraw
+ * uchar cmd (input): IPMI Command
+ * uchar netfn (input): IPMI NetFunction
+ * uchar sa (input): IPMI Slave Address of the MC
+ * uchar bus (input): BUS of the MC
+ * uchar lun (input): IPMI LUN
+ * uchar *pdata (input): pointer to ipmi data
+ * int sdata (input): size of ipmi data
+ * uchar *presp (output): pointer to response data buffer
+ * int *sresp (input/output): on input, size of response buffer,
+ * on output, length of response data
+ * uchar *cc (output): completion code
+ * char fdebugcmd(input): flag =1 if debug output desired
+ * returns 0 if successful, <0 if error
+ */
+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);
+/*
+ * ipmi_close_
+ * Called to close an IPMI session.
+ * returns 0 if successful, <0 if error
+ */
+int ipmi_close_(void);
+int ipmi_close(void); /*ditto*/
+/*-----------------------------------------------------------------*
+ * These externals are conditionally compiled in ipmicmd.c
+ ipmi_cmdraw_ia() Intel IMB driver, /dev/imb
+ ipmi_cmdraw_mv() MontaVista OpenIPMI driver
+ ipmi_cmdraw_va() VALinux driver
+ ipmi_cmdraw_ld() LANDesk driver
+ ipmi_cmdraw_direct() Direct/Driverless KCS or SSIF
+ ipmi_cmdraw_lan() IPMI LAN
+ ipmi_cmdraw_lan2() IPMI LANplus (RMCP+ in IPMI 2.0)
+ *-----------------------------------------------------------------*/
+
+/*
+ * parse_lan_options
+ * Parse the IPMI LAN options from the command-line getopt.
+ * int c (input): command-line option from getopt, one of:
+ case 'F': force driver type
+ case 'T': auth type
+ case 'V': priv level
+ case 'J': cipher suite
+ case 'N': nodename
+ case 'U': username
+ case 'R': remote password
+ case 'P': remote password
+ case 'E': get password from IPMI_PASSWORD environment var
+ case 'Y': prompt for remote password
+ case 'Z': set local MC address
+ * char *optarg (input): command-line argument from getopt
+ * char fdebug (input): show debug messages if =1, default=0
+ */
+void parse_lan_options(int c, char *optarg, char fdebug);
+/*
+ * set_lan_options
+ * Use this routine to set the lan options 'gnode','guser','gpswd', etc.
+ * This would only be required before opening a new session.
+ * char *node (input): IP address or nodename of remote node's IPMI LAN
+ * char *user (input): IPMI LAN username
+ * char *pswd (input): IPMI LAN password
+ * int auth (input): IPMI LAN authentication type (1 - 5)
+ * IPMI_SESSION_AUTHTYPE_NONE 0x00
+ * IPMI_SESSION_AUTHTYPE_MD2 0x01
+ * IPMI_SESSION_AUTHTYPE_MD5 0x02
+ * IPMI_SESSION_AUTHTYPE_PASSWORD 0x04
+ * IPMI_SESSION_AUTHTYPE_OEM 0x05
+ * int priv (input): IPMI LAN privilege level (1 - 5)
+ * IPMI_PRIV_LEVEL_CALLBACK 0x01
+ * IPMI_PRIV_LEVEL_USER 0x02
+ * IPMI_PRIV_LEVEL_OPERATOR 0x03
+ * IPMI_PRIV_LEVEL_ADMIN 0x04
+ * IPMI_PRIV_LEVEL_OEM 0x05
+ * int cipher (input): IPMI LAN cipher suite (0 thru 17, default is 3)
+ * See table 22-19 in the IPMIv2 spec.
+ * void *addr (input): Socket Address to use (SOCKADDR_T *) if not NULL
+ * This is only used in itsol.c because it has an
+ * existing socket open. Default is NULL for this.
+ * int addr_len (input): length of Address buffer (128 if ipv6, 16 if ipv4)
+ * returns 0 if successful, <0 if error
+ */
+int set_lan_options(char *node, char *user, char *pswd, int auth, int priv,
+ int cipher, void *addr, int addr_len);
+int get_lan_options(char *node, char *user, char *pswd, int *auth, int *priv,
+ int *cipher, void *addr, int *addr_len);
+void print_lan_opt_usage(void);
+int ipmi_getdeviceid(uchar *presp, int sresp, char fdebugcmd);
+/* int ipmi_open(void); * embedded in ipmi_cmd() */
+int ipmi_getpicmg(uchar *presp, int sresp, char fdebug);
+char *show_driver_type(int idx);
+int set_driver_type(char *tag);
+int get_driver_type(void);
+int nodeislocal(char *nodename);
+
+/* These *_mc routines are used to manage changing the mc.
+ * The local mc (mymc) may be changed via -Z, and
+ * the remote mc (mc) may be changed with -m. */
+void ipmi_set_mc(uchar bus, uchar sa, uchar lun, uchar type);
+void ipmi_get_mc(uchar *bus, uchar *sa, uchar *lun, uchar *type);
+void ipmi_restore_mc(void);
+void ipmi_set_mymc(uchar bus, uchar sa, uchar lun, uchar type);
+void ipmi_get_mymc(uchar *bus, uchar *sa, uchar *lun, uchar *type);
+/* ipmi_cmdraw_mc and ipmi_cmd_mc are used in cases where the mc may
+ * have been changed via ipmi_set_mc. */
+int ipmi_cmdraw_mc(uchar cmd, uchar netfn,
+ uchar *pdata, int sdata, uchar *presp,
+ int *sresp, uchar *pcc, char fdebugcmd);
+int ipmi_cmd_mc(ushort icmd, uchar *pdata, int sdata, uchar *presp,
+ int *sresp, uchar *pcc, char fdebugcmd);
+
+/* ipmi_sendrecv is a wrapper for ipmi_cmdraw which maps to ipmitool syntax */
+int ipmi_sendrecv(struct ipmi_rq * req, uchar *rsp, int *rsp_len);
+
+/* other common subroutines */
+char * decode_rv(int rv); /*ipmicmd.c*/
+char * decode_cc(ushort icmd, int cc);
+void dump_buf(char *tag,uchar *pbuf,int sz, char fshowascii);
+int get_lan_channel(uchar chstart, uchar *chan);
+void show_fru_picmg(uchar *pdata, int dlen); /* ifru_picmg.c*/
+
+/* show_outcome outputs the meaning of the return code. */
+void show_outcome(char *prog, int ret);
+
+/* these log routines are primarily for the isol debug log */
+FILE *open_log(char *mname);
+void close_log(void);
+void flush_log(void);
+void print_log( char *pattn, ... );
+void dump_log(FILE *fp,char *tag,uchar *pbuf,int sz, char fshowascii);
+void logmsg( char *pname, char *pattn, ... );
+
+#ifdef WIN32
+/* Implement the Linux strncasecmp for Windows. */
+int strncasecmp(const char *s1, const char *s2, int n);
+#endif
+const char *val2str(ushort val, const struct valstr *vs); /*ipmilanplus.c*/
+const char * oemval2str(ushort oem, uchar val, const struct oemvalstr *vs);
+void set_debug(void); /*used only by oem_sun.c*/
+void set_iana(int iana); /*ipmicmd.c*/
+void set_mfgid(uchar *devid, int len);
+void get_mfgid(int *pvend, int *pprod);
+void get_devid_ver(uchar *bmaj, uchar *bmin, uchar *iver);
+
+char *get_nodename(void);
+char is_remote(void);
+void show_devid(uchar b1, uchar b2, uchar i1, uchar i2);
+int set_max_kcs_loops(int ms); /* ipmicmd.c, calls ipmidir.c if ok */
+
+/* These common subroutines are in subs.c */
+int str_icmp(char *s1, char *s2); /*used internally in ipmicmd.c*/
+char * strdup_(const char *instr); /*wrapper for strdup, supports WIN32*/
+int strlen_(const char *s); /*wrapper for strlen, avoids compile warnings*/
+uchar htoi(char *inhex);
+void os_usleep(int s, int u);
+char *get_iana_str(int mfg); /*subs.c*/
+int get_errno(void); /*subs.c*/
+const char * buf2str(uchar * buf, int len); /*subs.c*/
+int str2uchar(char *str_in, uchar *uchr_out);
+uchar atob(char *str_in); /* calls str2uchar*/
+void atoip(uchar *array,char *instr);
+int get_system_info(uchar parm, char *pbuf, int *szbuf); /*subs.c*/
+int set_system_info(uchar parm, uchar *pbuf, int szbuf); /*subs.c*/
+int ipmi_reserved_user(int vend, int userid); /*subs.c*/
+
+/* from mem_if.c */
+int get_BiosVersion(char *str);
+
+/* See util/isensor.h for SDR cache routines. */
+/* See util/ievents.h for sensor_type_desc, sel_opts, decode_sel routines. */
+
+
+--------------------------
+10.0 RELATED INFORMATION
+--------------------------
+
+10.1 History
+
+History of ipmiutil:
+This project started in October 2001 as part of the Carrier Grade Linux effort.
+It was then known as 'panicsel' and included a kernel patch to write a Linux
+panic event to the IPMI firmware log, as well as utilities.
+This code was first included in MontaVista CGE Linux 2.1 in July 2002.
+The panicsel functionality was included in OSDL CGL 1.0 and 2.0 requirements.
+The kernel panic functionality was included in the OpenIPMI driver for 2.6
+Linux kernels. Compile flags for Windows 2000 & 2003 support were added in
+Jan 2004.
+In August 2004, the project was moved from panicsel.sf.net to ipmiutil.sf.net.
+The new name more clearly reflects the purpose of the project in its current
+state. In November 2004, support for the FreeIPMI library was added.
+A Linux rpm and a Windows setup package for ipmiutil is included on the
+Resource CD with Intel carrier-grade servers.
+The ipmiutil (or panicsel) rpm is known to be included in the following
+distributions: MontaVista CGE 2.1/3.0/3.1/4.0, SuSE SLES9, Red Flag 5.0
+
+
+10.2 Links
+
+Links with information related to the IPMI Management Utilities project.
+
+ipmiutil project, sourceforge http://ipmiutil.sourceforge.net (current)
+panicsel project, sourceforge http://panicsel.sourceforge.net (old)
+IPMI Specification http://www.intel.com/design/servers/ipmi/index.htm
+OSDL Carrier Grade Linux http://www.osdl.org/lab_activities/carrier_grade_linux/
+Intel imb driver source http://downloadfinder.intel.com/scripts-df-external/Product_Search.asp?Prod_nm=ipmi*driver*source
+Intel imb driver for Windows http://downloadfinder.intel.com/scripts-df-external/Product_Search.aspx?Prod_nm=imb+driver
+OpenIPMI project http://sourceforge.net/projects/openipmi/
+ by Corey Minyard of MontaVista (home= http://openipmi.sourceforge.net)
+ipmitools project by San Mehat http://sourceforge.net/projects/ipmitools/
+ valinux IPMI driver http://cvs.sf.net/cgi-bin/viewcvs.cgi/ipmitools/ipmitools/kernel/kcs/patches/2.4.x/
+GNU FreeIPMI library project http://www.gnu.org/software/freeipmi/
+LANDesk IPMI driver/daemon http://www.landesk.com/Support/ (or see
+ Intel System Resource CD for Intel servers)
+lm-sensors project http://secure.netroedge.com/~lm78/
+dmidecode project http://www.nongnu.org/dmidecode/
+IPMI vendor/mfg IDs http://www.iana.org/assignments/enterprise-numbers
+
diff --git a/doc/bmclanaol.mib b/doc/bmclanaol.mib
new file mode 100644
index 0000000..bdac611
--- /dev/null
+++ b/doc/bmclanaol.mib
@@ -0,0 +1,210 @@
+--************************************************************************\
+--* *
+--* Copyright (c) 1998-2004 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. *
+--* *
+--\***********************************************************************/
+
+--/**************************************************************************
+--*
+--* NAME:
+--* aolnprxy.mib
+--*
+--* DESCRIPTION:
+--* Alert on LAN MIB
+--*
+--*
+--* $WorkFile: $
+--* $Revision: 6 $
+--* $ModTime: $
+--* $Author: Psaranga $
+--*
+--***************************************************************************
+
+PET-MIB
+
+DEFINITIONS ::= BEGIN
+
+-- Title : Alert on LAN pET MIB version 1.0.
+
+IMPORTS
+ MODULE-IDENTITY,
+ OBJECT-TYPE,
+ Integer32, IpAddress
+ FROM SNMPv2-SMI
+ enterprises
+ FROM RFC1155-SMI
+ DisplayString
+ FROM RFC1213-MIB
+ TRAP-TYPE
+ FROM RFC-1215
+ ;
+
+
+wired_for_management OBJECT IDENTIFIER ::= { enterprises 3183 }
+pET OBJECT IDENTIFIER ::= { wired_for_management 1 }
+pET_version_1 OBJECT IDENTIFIER ::= { pET 1 }
+
+
+-- MODULE IDENTIFICATION
+--
+-- Alert_on_LAN MODULE-IDENTITY
+-- LAST-UPDATED "9807210000Z"
+-- ORGANIZATION "Intel Corporation"
+-- CONTACT-INFO
+-- " Alert On LAN* Software
+-- Intel Corporation, JF3-4
+-- Hillsboro, OR. "
+-- DESCRIPTION
+-- " This is the pET MIB. Version 1.0 "
+-- We should be able to plug this branch into any tree from this point forward
+
+
+-- ****************************************
+-- SYSTEM INFORMATION BRANCH STARTS HERE.
+-- ****************************************
+
+
+pETTrap OBJECT-TYPE
+ SYNTAX OCTET STRING ( SIZE(110) )
+ ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Trap information"
+::= { pET_version_1 1 }
+
+pET_PresenceHeartbeat TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "Presence Heartbeat Expired"
+ ::= 2584320
+
+pET_CoverTamper TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "Cover Tamper"
+ ::= 356096
+
+pET_Voltage_Fan_Temperature TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "Voltage/Fan/Temperature Out of Specification"
+ ::= 552706
+
+pET_LANLeash TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "LAN Leash Tamper"
+ ::= 356100
+
+pET_Temperature TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "Temperature Out of Specification"
+ ::= 93952
+
+pET_ProcessorMissing TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "Processor Missing"
+ ::= 356099
+
+pET_ProcessorTemperature TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "Processor Over Temperature"
+ ::= 487169
+
+pET_Watchdog TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "Watchdog Event"
+ ::= 1142534
+
+pET_P_O_S_T TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "P.O.S.T."
+ ::= 1011456
+
+pET_Voltage TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "Voltage Out of Specification"
+ ::= 159488
+
+pET_Fan TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "Fan Out of Specification"
+ ::= 290560
+
+pET_Fan_Temperature TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "Fan/Temperature Out of Specification"
+ ::= 683778
+
+pET_Undock TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "Surprised Undock event"
+ ::= 356101
+
+pET_EventClear TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "Event clear"
+ ::= 1076994
+
+pET_AlertOnLAN_2 TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "Alert on LAN 2 Event has occurred"
+ ::= 2277391
+
+pET_AlertOnLAN_Boot TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "System Boot Event occurred"
+ ::= 1208065
+
+pET_AlertOnLAN_Fan TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "Fan Event occurred"
+ ::= 262400
+
+pET_AlertOnLAN_Fan2 TRAP-TYPE
+ ENTERPRISE pET_version_1
+ DESCRIPTION
+ "Fan Event occurred"
+ ::= 262402
+
+END
diff --git a/doc/bmclanpet.mib b/doc/bmclanpet.mib
new file mode 100644
index 0000000..5f7641e
--- /dev/null
+++ b/doc/bmclanpet.mib
@@ -0,0 +1,1083 @@
+--/************************************************************************
+--* *
+--* Copyright (c) 1998-2004 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. *
+--* *
+--*************************************************************************
+--* Name : PetEvents.mib
+--* Description : MIB file for PET events
+--* Created : Wesdnesday, December 17, 2003
+--* Author : Intel Corporation
+--*
+--* $History:$
+--*
+--* Date : March 7th,2002
+--* Changed by :
+--* Change Description : Updated MIB file
+--*
+--* Date : December 17th,2003
+--* Changed by :
+--* Change Description : Started with ASF MIB file
+--*
+--*************************************************************************/
+
+
+
+PET-EVENTS DEFINITIONS ::= BEGIN
+
+ IMPORTS
+ enterprises
+ FROM RFC1155-SMI
+ OBJECT-TYPE
+ FROM RFC-1212
+
+ TRAP-TYPE
+ FROM RFC-1215
+
+
+ DisplayString
+ FROM RFC1213-MIB;
+
+ wiredformgmt OBJECT IDENTIFIER ::= { enterprises 3183 }
+ pet OBJECT IDENTIFIER ::= { wiredformgmt 1 }
+
+-- MODULE IDENTIFICATION
+--
+-- PET Events Alerting MODULE-IDENTITY
+-- LAST-UPDATED "February 4, 2004"
+-- ORGANIZATION "Intel Corporation"
+-- CONTACT-INFO
+-- " PET Events,
+-- Intel Corporation, DP3-407
+-- DuPont, WA 98352"
+-- DESCRIPTION
+-- "This is the MIB file for SNMPv1.0 based PET traps"
+
+
+-- ****************************************
+-- SYSTEM INFORMATION BRANCH STARTS HERE.
+-- ****************************************
+
+ petevts OBJECT IDENTIFIER ::= { pet 1 }
+
+
+-- **********************************************
+-- * Temperature *
+-- **********************************************
+
+-- Lower Non Critical threshold crossed
+ trapUnderTemperatureWarning TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Under-Temperature Warning (Lower non-critical, going low)"
+
+ --#TYPE "Temperature Event"
+ --#SUMMARY "Under-Temperature Warning (Lower non-critical, going low)"
+ --#ARGUMENTS {}
+ --#SEVERITY WARNING
+
+ ::= 65792
+
+-- Lower Critical threshold crossed
+ trapUnderTemperatureCritical TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Critical Under-Temperature Problem (Lower Critical - going low)"
+
+ --#TYPE "Temperature Event"
+ --#SUMMARY "Critical Under-Temperature Problem (Lower Critical - going low)"
+ --#ARGUMENTS {}
+ --#SEVERITY CRITICAL
+
+ ::= 65794
+
+-- Upper Non Critical threshold crossed
+ trapOverTemperatureWarning TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Over-Temperature Warning (Upper non-critical, going high)"
+
+ --#TYPE "Temperature Event"
+ --#SUMMARY "Over-Temperature Warning (Upper non-critical, going high)"
+ --#ARGUMENTS {}
+ --#SEVERITY WARNING
+
+ ::= 65799
+
+-- Upper Critical threshold crossed
+ trapOverTemperatureCritical TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Critical Over-Temperature Problem (Upper Critical - going high)"
+
+ --#TYPE "Temperature Event"
+ --#SUMMARY "Critical Over-Temperature Problem (Upper Critical - going high)"
+ --#ARGUMENTS {}
+ --#SEVERITY CRITICAL
+
+ ::= 65801
+
+-- Back to Normal from Lower Non Critical
+ trapUnderTemperatureWarningCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Under-Temperature Warning Cleared"
+
+ --#TYPE "Temperature Event"
+ --#SUMMARY "Under-Temperature Warning Cleared"
+ --#ARGUMENTS {}
+ --#SEVERITY INFORMATIONAL
+
+ ::= 65920
+
+-- Back to Normal from Lower Critical
+ trapUnderTemperatureCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Under-Temperature Problem Cleared"
+
+ --#TYPE "Temperature Event"
+ --#SUMMARY "Under-Temperature Problem Cleared"
+ --#ARGUMENTS {}
+ --#SEVERITY INFORMATIONAL
+
+ ::= 65922
+
+-- Back to Normal from Upper Non Critical
+ trapOverTemperatureWarningCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Over-Temperature warning Cleared"
+
+ --#TYPE "Temperature Event"
+ --#SUMMARY "Over-Temperature Warning Cleared"
+ --#ARGUMENTS {}
+ --#SEVERITY INFORMATIONAL
+
+ ::= 65927
+
+-- Back to Normal from Upper Critical
+ trapOverTemperatureCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Over-Temperature Problem Cleared"
+
+ --#TYPE "Temperature Event"
+ --#SUMMARY "Over-Temperature Problem Cleared"
+ --#ARGUMENTS {}
+ --#SEVERITY INFORMATIONAL
+
+ ::= 65929
+
+-- Generic critical temperature problem
+ trapGenericCriticalTemperature TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Generic Critical Temperature Problem (Transition to Critical from less severe)"
+
+ --#TYPE "Temperature Event"
+ --#SUMMARY "Generic Critical Temperature Problem (Transition to Critical from less severe)"
+ --#ARGUMENTS {}
+ --#SEVERITY CRITICAL
+
+ ::= 67330
+
+-- Generic temperature warning
+ trapGenericTemperatureWarning TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Generic Temperature Warning (Transition to Warning from less severe)"
+
+--#TYPE "Temperature Event"
+--#SUMMARY "Generic Temperature Warning (Transition to Warning from less severe)"
+--#ARGUMENTS {}
+--#SEVERITY WARNING
+
+ ::= 67331
+
+
+-- **********************************************
+-- * Voltage *
+-- **********************************************
+
+-- (Analog voltage) Lower Non Critical threshold crossed
+ trapUnderAnalogVoltageWarning TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Under-Voltage Warning (Lower Non Critical - going low)"
+--#TYPE "Voltage Event"
+--#SUMMARY "Under-Voltage Warning (Lower Non Critical - going low)"
+--#ARGUMENTS {}
+--#SEVERITY WARNING
+
+ ::= 131328
+
+-- (Analog voltage) Lower Critical threshold crossed
+ trapUnderAnalogVoltageCritical TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Critical Under-Voltage Problem (Lower Critical - going low)"
+
+--#TYPE "Voltage Event"
+--#SUMMARY "Critical Under-Voltage Problem (Lower Critical - going low)"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 131330
+
+-- (Analog voltage) Upper Non Critical threshold crossed
+ trapOverAnalogVoltageWarning TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Over-Voltage Warning (Upper Non Critical - going high)"
+
+--#TYPE "Voltage Event"
+--#SUMMARY "Over-Voltage Warning (Upper Non Critical - going high)"
+--#ARGUMENTS {}
+--#SEVERITY WARNING
+
+ ::= 131335
+
+-- (Analog voltage) Upper Critical threshold crossed
+ trapOverAnalogVoltageCritical TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Critical Over-Voltage Problem (Upper Critical - going high)"
+
+--#TYPE "Voltage Event"
+--#SUMMARY "Critical Over-Voltage Problem (Upper Critical - going high)"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 131337
+
+-- (Analog voltage) Voltage back to OK from Lower Non Critical
+ trapUnderAnalogVoltageWarningCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Under-Voltage Warning Cleared"
+
+--#TYPE "Voltage Event"
+--#SUMMARY "Under-Voltage Warning Cleared"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 131456
+
+-- (Analog voltage) Voltage back to OK from Lower Non Critical
+ trapUnderAnalogVoltageCriticalCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Under-Voltage Problem Cleared"
+
+--#TYPE "Voltage Event"
+--#SUMMARY "Under-Voltage Problem Cleared"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 131458
+
+-- (Analog voltage) Voltage back to OK from Upper Non Critical Warning
+ trapOverAnalogVoltageWarningCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Over-Voltage Warning Cleared"
+
+--#TYPE "Voltage Event"
+--#SUMMARY "Over-Voltage Warning Cleared"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 131463
+
+-- (Analog voltage) Voltage back to OK from Upper Critical
+ trapOverAnalogVoltageCriticalCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Over-Voltage Problem Cleared"
+
+--#TYPE "Voltage Event"
+--#SUMMARY "Over-Voltage Problem Cleared"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 131465
+
+-- (Discrete voltage) Critical voltage problem
+ trapGenericCriticalDiscreteVoltageCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Generic Critical Voltage Problem Cleared"
+
+--#TYPE "Voltage Event"
+--#SUMMARY "Generic Critical Voltage Problem Cleared"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 131840
+
+-- (Discrete voltage) Critical voltage problem
+ trapGenericCriticalDiscreteVoltage TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Generic Critical Voltage Problem (Transition to Critical from less severe)"
+
+--#TYPE "Voltage Event"
+--#SUMMARY "Generic Critical Voltage Problem (Transition to Critical from less severe)"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 131841
+
+-- (Discrete voltage) Critical voltage problem
+ trapGenericCriticalDiscreteVoltage2 TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Generic Critical Voltage Problem (Transition to Critical from less severe)"
+
+--#TYPE "Voltage Event"
+--#SUMMARY "Generic Critical Voltage Problem (Transition to Critical from less severe)"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 132866
+
+-- (Discrete voltage) Non-Critical voltage problem
+ trapGenericDiscreteVoltageWarning TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Generic Voltage Warning (Transition to Non-Critical from less severe)"
+
+--#TYPE "Voltage Event"
+--#SUMMARY "Generic Voltage Warning (Transition to Non-Critical from less severe)"
+--#ARGUMENTS {}
+--#SEVERITY WARNING
+
+ ::= 132867
+
+
+-- **********************************************
+-- * Fan *
+-- **********************************************
+
+-- Lower Non Critical threshold crossed
+ trapFanUnderSpeedWarning TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Fan speed warning (Fan speed below expected speed)"
+
+--#TYPE "Fan Event"
+--#SUMMARY "Fan speed Warning (Fan speed below expected speed)"
+--#ARGUMENTS {}
+--#SEVERITY WARNING
+
+ ::= 262400
+
+-- Fan Lower Critical threshold crossed
+ trapFanCriticalUnderSpeed TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Generic Critical Fan Failure (Transition to Critical from less severe)"
+
+--#TYPE "Fan Event"
+--#SUMMARY "Critical Fan Failure (Transition to Critical from less severe)"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 262402
+
+-- Fan back to OK from warning level
+ trapFanUnderSpeedWarningCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Fan speed Warning Cleared"
+
+--#TYPE "Fan Event"
+--#SUMMARY "Fan speed Warning Cleared"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 262528
+
+-- Fan back to OK from critical level
+ trapFanCriticalUnderSpeedCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Critical Fan Failure Cleared"
+
+--#TYPE "Fan Event"
+--#SUMMARY "Critical Fan Failure Cleared"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 262530
+
+-- Fan Full Redundancy
+ trapFanFullRedundancy TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Fan redundancy has returned to Normal"
+
+--#TYPE "Fan Event"
+--#SUMMARY "Fan redundancy has returned to Normal"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 264960
+
+-- Fan Redundancy lost
+ trapFanRedundancyLost TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Fan Redundancy has been Lost"
+
+--#TYPE "Fan Event"
+--#SUMMARY "Fan Redundancy has been Lost"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 264961
+
+-- Fan Redundancy degraded
+ trapFanRedundancyDegraded TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Fan Redundancy is in a degraded state"
+
+--#TYPE "Fan Event"
+--#SUMMARY "Fan Redundancy is in a degraded state"
+--#ARGUMENTS {}
+--#SEVERITY WARNING
+
+ ::= 264962
+
+
+-- **********************************************
+-- * Power Supply *
+-- **********************************************
+
+-- Power Supply Full Redundancy
+ trapPowerSupplyFullRedundancy TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Power Supply Redundancy Has Returned to Normal"
+
+--#TYPE "Power Supply Event"
+--#SUMMARY "Power Supply Redundancy Has Returned to Normal"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 527104
+
+-- Power Supply Redundancy lost
+ trapPowerSupplyRedundancyLost TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Power Supply Redundancy has been Lost"
+
+--#TYPE "Power Supply Event"
+--#SUMMARY "Power Supply Redundancy has been Lost"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 527105
+
+-- Power Supply Redundancy degraded
+ trapPowerSupplyRedundancyDegraded TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Power Supply Redundancy is in a degraded state"
+
+--#TYPE "Power Supply Event"
+--#SUMMARY "Power Supply Redundancy is in a degraded state"
+--#ARGUMENTS {}
+--#SEVERITY WARNING
+
+ ::= 527106
+
+-- Power Supply presence detected
+ trapPowerSupplyPresenceDeteced TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Power Supply Inserted"
+
+--#TYPE "Power Supply Event"
+--#SUMMARY "Power Supply Inserted"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 552704
+
+trapPowerSupplyFailureDetected TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Power supply Failure detected"
+
+--#TYPE "Power Supply Event"
+--#SUMMARY "Power Supply failure detected"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 552705
+
+trapPowerSupplyWarning TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Power supply Warning"
+
+--#TYPE "Power Supply Event"
+--#SUMMARY "Power Supply Warning"
+--#ARGUMENTS {}
+--#SEVERITY WARNING
+
+ ::= 552706
+
+ -- AC Lost
+ trapPowerSupplyACLost TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Power Supply AC Lost"
+
+--#TYPE "Power Supply Event"
+--#SUMMARY "Power Supply AC Lost"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 552707
+
+-- Power Supply removed
+ trapPowerSupplyPresenceRemoved TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Power Supply Removed"
+
+--#TYPE "Power Supply Event"
+--#SUMMARY "Power Supply Removed"
+--#ARGUMENTS {}
+--#SEVERITY WARNING
+
+ ::= 552832
+
+-- Back to normal from failure
+ trapPowerSupplyFailureCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Power Supply Failure Cleared"
+
+--#TYPE "Power Supply Event"
+--#SUMMARY "Power Supply Failure Cleared"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 552833
+
+-- Predictive Failure cleared
+ trapPowerSupplyWarningCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Power Supply Warning Cleared"
+
+--#TYPE "Power Supply Event"
+--#SUMMARY "Power Supply Warning Cleared"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 552834
+
+ -- AC Back
+ trapPowerSupplyACBack TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Power Supply AC Restored"
+
+--#TYPE "Power Supply Event"
+--#SUMMARY "Power Supply AC Restored"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 552835
+
+-- Power Unit Redundancy OK
+ trapPowerUnitRedundancyOk TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Power Unit Redundancy has been restored"
+
+--#TYPE "Power Supply Event"
+--#SUMMARY "Power Unit Redundancy has been restored"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 592640
+
+-- Power Unit Redundancy lost
+ trapPowerUnitRedundancyLost TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Power Unit Redundancy has been Lost"
+
+--#TYPE "Power Supply Event"
+--#SUMMARY "Power Unit Redundancy has been Lost"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 592641
+
+-- **********************************************
+-- * Processor *
+-- **********************************************
+
+-- Processor internal error
+ trapProcessorInternalError TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Processor Internal Error"
+
+--#TYPE "Processor Event"
+--#SUMMARY "Processor Internal Error"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 487168
+
+-- Processor Thermal Trip
+ trapProcessorThermalTrip TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Processor Thermal Trip (Over Temperature Shutdown)"
+
+--#TYPE "Processor Event"
+--#SUMMARY "Processor Thermal Trip (Over Temperature Shutdown)"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 487169
+
+-- Processor Fault Resilient Booting (FRB) 1 / Built-in self test (BIST) Error
+ trapProcessorBistError TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Processor Fault Resilient Booting (FRB) 1 / BIST (Built In Self Test) Failure"
+
+--#TYPE "Processor Event"
+--#SUMMARY "Processor Fault Resilient Booting (FRB) 1 / Processor BIST (Built In Self Test) Failure"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 487170
+
+-- Processor Fault Resilient Booting (FRB) 2 / Hang in Power On Self Test (POST)
+trapProcessorFRB2Failure TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Processor Fault Resilient Booting (FRB) 2 / Hang in Power On Self Test (POST) Failure"
+
+--#TYPE "Processor Event"
+--#SUMMARY "Processor Fault Resilient Booting (FRB) 2 / Hang in Power On Self Test (POST) Failure"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 487171
+
+-- Processor Fault Resilient Booting (FRB) 3 / Processor Setup / Initialization Failure
+trapProcessorFRB3Failure TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Processor Fault Resilient Booting (FRB) 3 / Processor Setup / Initialization Failure"
+
+--#TYPE "Processor Event"
+--#SUMMARY "Processor Fault Resilient Booting (FRB) 3 / Processor Setup / Initialization Failure"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 487172
+
+-- Processor config error
+ trapProcessorConfigError TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Processor Configuration Error"
+
+--#TYPE "Processor Event"
+--#SUMMARY "Processor Configuration Error"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 487173
+
+-- Processor throttle.
+ trapProcessorThrottle TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Processor Throttled (Processor Speed Reduced)"
+
+--#TYPE "Processor Event"
+--#SUMMARY "Processor Throttled (Processor Speed Reduced)"
+--#ARGUMENTS {}
+--#SEVERITY WARNING
+
+ ::= 487178
+
+-- Processor internal error cleared
+ trapProcessorInternalErrorCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Processor Internal Error Cleared"
+
+--#TYPE "Processor Event"
+--#SUMMARY "Processor Internal Error Cleared"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 487296
+
+-- Processor Back to normal from Thermal Trip
+ trapProcessorThermalTripCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Processor Thermal Trip (Over Temperature Shutdown) Cleared"
+
+--#TYPE "Processor Event"
+--#SUMMARY "Processor Thermal Trip (Over Temperature Shutdown) Cleared"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 487297
+
+-- Processor BIST Error cleared
+ trapProcessorBistErrorCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Processor BIST (Built In Self Test) Failure Cleared"
+
+--#TYPE "Processor Event"
+--#SUMMARY "Processor BIST (Built In Self Test) Failure Cleared"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 487298
+
+-- Processor config error cleared
+ trapProcessorConfigErrorCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Processor Configuration Error Cleared"
+
+--#TYPE "Processor Event"
+--#SUMMARY "Processor Configuration Error Cleared"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 487301
+
+-- Processor return to normal from throttled
+ trapProcessorThrottleCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Processor Throttle Cleared (Normal Processor Speed)"
+
+--#TYPE "Processor Event"
+--#SUMMARY "Processor Throttle Cleared (Normal Processor Speed)"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 487306
+
+-- **********************************************
+-- * Memory *
+-- **********************************************
+
+trapMemoryUncorrectableECC TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Uncorrectable ECC or other uncorrectable memory error"
+
+--#TYPE "Memory Event"
+--#SUMMARY "Uncorrectable ECC or other uncorrectable memory error"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 814849
+
+
+--**********************
+--* Chassis Intrusion *
+--**********************
+
+-- Chassis Intrusion
+ trapChassisIntrusion TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Chassis Intrusion - Physical Security Violation"
+
+--#TYPE "Chassis Intrusion Event"
+--#SUMMARY "Chassis Intrusion - Physical Security Violation"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 356096
+
+-- Chassis Intrusion cleared
+ trapChassisIntrusionCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Chassis Intrusion (Physical Security Violation) Event Cleared"
+
+--#TYPE "Chassis Intrusion Event"
+--#SUMMARY "Chassis Intrusion( Physical Security Violation) Event Cleared"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 356224
+
+
+-- **********************************************
+-- * Critical Interrupts *
+-- **********************************************
+
+-- Critical Interrupt, Bus timeout error
+trapCriticalInterruptBusTimeout TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Critical Interrupt, Bus Timeout error"
+
+--#TYPE "Critical Interrupts Event"
+--#SUMMARY "Critical Interrupt, Bus Timeout error"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 1273601
+
+-- Critical Interrupt, IO Channel Non-Maskable Interrupt
+trapCriticalInterruptIOChannelNMI TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Critical Interrupt, IO Channel check NMI error"
+
+--#TYPE "Critical Interrupts Event"
+--#SUMMARY "Critical Interrupt, IO Channel check NMI error"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 1273602
+
+-- Critical Interrupt, Software Non-Maskable Interrupt error
+trapCriticalInterruptSoftwareNMI TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Critical Interrupt, software NMI error"
+
+--#TYPE "Critical Interrupts Event"
+--#SUMMARY "Critical Interrupt, software NMI error"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 1273603
+
+-- Non special-cycle parity errors
+trapCriticalInterruptPCIPERR TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Critical Interrupt, PCI PERR parity error"
+
+--#TYPE "Critical Interrupts Event"
+--#SUMMARY "Critical Interrupt, PCI PERR parity error"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 1273604
+
+-- Special-cycle parity errors
+trapCriticalInterruptPCISERR TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Critical Interrupt, PCI SERR parity error"
+
+--#TYPE "Critical Interrupts Event"
+--#SUMMARY "Critical Interrupt, PCI SERR parity error"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 1273605
+
+-- Bus uncorrectable error
+trapCriticalInterruptBusUncorrect TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Critical Interrupt, Bus Uncorrectable error"
+
+--#TYPE "Critical Interrupts Event"
+--#SUMMARY "Critical Interrupt, Bus Uncorrectable error"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 1273608
+
+-- Fatal non-maskable interrupt (NMI)
+trapCriticalInterruptFatalNMI TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Critical Interrupt, Fatal NMI error"
+
+--#TYPE "Critical Interrupts Event"
+--#SUMMARY "Critical Interrupt, Fatal NMI error"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 1273609
+
+
+-- **********************************************
+-- * System Firmware Progress *
+-- **********************************************
+
+-- Power On Self Test (POST) code error
+trapBIOSPOSTCodeError TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "System Firmware Progress: BIOS POST code error"
+
+--#TYPE "System Firmware Progress Event"
+--#SUMMARY "System Firmware Progress: BIOS POST code error"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 1011456
+
+
+-- **********************************************
+-- * WatchDog *
+-- **********************************************
+
+-- Watchdog reset event
+trapWatchdogReset TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Watchdog Reset"
+
+--#TYPE "Watchdog Event"
+--#SUMMARY "Watchdog Reset"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 2322177
+
+-- Watchdog power down event
+trapWatchdogPowerDown TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Watchdog Power Down"
+
+--#TYPE "Watchdog Event"
+--#SUMMARY "Watchdog Power Down"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 2322178
+
+-- Watchdog power cycle event
+trapWatchdogPowerCycle TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "Watchdog Power Cycle"
+
+--#TYPE "Watchdog Event"
+--#SUMMARY "Watchdog Power cycle"
+--#ARGUMENTS {}
+--#SEVERITY WARNING
+
+ ::= 2322179
+
+
+-- **********************************************
+-- * System Event Log *
+-- **********************************************
+
+-- System Event Log Cleared
+ trapSystemEventLogCleared TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "System Event Log (SEL) Cleared"
+
+--#TYPE "System Event Log"
+--#SUMMARY "System Event Log (SEL) Cleared"
+--#ARGUMENTS {}
+--#SEVERITY INFORMATIONAL
+
+ ::= 1076994
+
+-- System Event Log Full
+ trapSystemEventLogFull TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "System Event Log (SEL) Full (Logging Disabled)"
+
+--#TYPE "System Event Log"
+--#SUMMARY "System Event Log (SEL) Full (Logging Disabled)"
+--#ARGUMENTS {}
+--#SEVERITY CRITICAL
+
+ ::= 1076995
+
+
+-- **********************************************
+-- * System *
+-- **********************************************
+
+-- System boot event
+trapSystemBootEvent TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "System Boot Event"
+
+--#TYPE "System Event"
+--#SUMMARY "System Boot Event"
+--#ARGUMENTS {}
+--#SEVERITY WARNING
+
+ ::= 1208065
+
+-- **********************************************
+-- * Linux Panic, Critical Stop *
+-- **********************************************
+
+-- Linux panic event
+trapOSCriticalStop TRAP-TYPE
+ ENTERPRISE petevts
+ DESCRIPTION
+ "OS Critical Stop occurred"
+
+--#TYPE "System Event"
+--#SUMMARY "System Boot Event"
+--#ARGUMENTS {}
+--#SEVERITY WARNING
+
+ ::= 2125569
+
+END
diff --git a/doc/ialarms.8 b/doc/ialarms.8
new file mode 100644
index 0000000..34de55a
--- /dev/null
+++ b/doc/ialarms.8
@@ -0,0 +1,103 @@
+.TH IALARMS 8 "Version 1.3: 20 Apr 2007"
+.SH NAME
+ipmiutil_alarms \- display and set alarm indicators
+.SH SYNOPSIS
+.B "ipmiutil alarms [-abcdimnoprx -N node -U user -P/-R pswd -EFJTVY]"
+
+.SH DESCRIPTION
+.I ipmiutil alarms
+is a program that uses IPMI commands to
+display and set alarm indicators, which are usually LEDs on the system
+chassis front panel.
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+Note that a LAN user must have Administrative privileges to read or write
+the alarm LEDs.
+
+Note that this utility may not be the only logic setting alarm states.
+The BMC firmware, system management software, or cluster fault manager
+may also want to set alarm states. Intel provides a Telco Alarms Manager API
+which presents a consolidated interface for all alarm management applications.
+
+.SH OPTIONS
+Command line options are described below.
+.IP "-r"
+Read-only. Show the alarms status, but do not set any states.
+This is also the default mode if no parameters are specified.
+.IP "-iN"
+Sets the Chassis Identify feature, which can be an LED or some other
+alarm. If N=0, turn off the Chassis ID, otherwise turn the ID on
+for N seconds. N=255 will turn on the ID indefinitely, if it is IPMI 2.0.
+.IP "-aN"
+Sets Disk A Fault LED. If N=0, turn it off. If N=1, turn it on. Used only for TIGPT1U platform.
+.IP "-bN"
+Sets Disk B Fault LED. If N=0, turn it off. If N=1, turn it on. Used only for TIGPT1U platform.
+.IP "-dXN"
+Sets Disk X Fault LED, where X=0-6. If N=0, turn it off. If N=1, turn it on. Used only for NSC2U platform.
+.IP "-cN"
+Sets the Critical Alarm. If N=0, turn it off. If N=1, turn it on.
+.IP "-mN"
+Sets the Major Alarm. If N=0, turn it off. If N=1, turn it on.
+.IP "-nN"
+Sets the Minor Alarm. If N=0, turn it off. If N=1, turn it on.
+.IP "-pN"
+Sets the Power Alarm. If N=0, turn it off. If N=1, turn it on.
+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.
+Refer to the system Technical Product Specification for System Faults.
+.IP "-o"
+Sets all alarms off, including the Chassis ID.
+.IP "-x"
+Causes extra debug messages to be displayed.
+
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use this IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use this IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+
+.SH "SEE ALSO"
+ipmiutil(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/icmd.8 b/doc/icmd.8
new file mode 100644
index 0000000..f786528
--- /dev/null
+++ b/doc/icmd.8
@@ -0,0 +1,113 @@
+.TH ICMD 8 "Version 1.0: 10 Aug 2004"
+.SH NAME
+ipmiutil_cmd \- a tool to send specific IPMI commands via the command line.
+
+.SH SYNOPSIS
+.B "ipmiutil cmd [-qsx -NUPREFJTVY] bus rsSa netFn/lun cmd [data bytes]"
+
+.SH DESCRIPTION
+This
+.I ipmiutil cmd
+tool sends specific IPMI commands to the firmware. The commands
+are composed as hex values on the command line. This tool was
+written to allow in-band use to match the DOS CMDTOOL.EXE or
+IPMITOOL.EXE program which is distributed with many Intel servers.
+Certain scripts or pre-written commands may have been supplied for
+the DOS tool that can now be used while the system is running
+Linux or Windows.
+
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+
+This tool should only be used if you are familiar with the IPMI 1.5
+specification, or you have specific pre-written commands to send.
+
+
+.SH OPTIONS
+Command line options are described below.
+.IP "-q"
+Quiet mode. Show only minimal header information.
+.IP "-s"
+Skips the GetDeviceID command
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH PARAMETERS
+The following parameters are used by icmd. Each is represented as
+a two-digit hex byte. The parameters have no default values.
+
+.IP "bus"
+This byte contains the bus number for this command, usually 00.
+
+.IP "rsSa"
+This is the resource slave address, usually 0x20 for the BMC.
+
+.IP "netFn/lun"
+This byte combines the net Function and Lun. The 2 low-order bits
+are the Lun and the 6 high-order bits are the net Function.
+This representation is consistent with the DOS CMDTOOL/IPMITOOL.
+
+.IP "cmd"
+This byte contains the IPMI command.
+
+.IP "[data bytes]"
+This is a sequence of zero to 16 bytes that represent data bytes
+specific to this command.
+
+.SH "EXAMPLES"
+icmd 00 20 18 01
+.br
+Sends the GetDevice ID command to the BMC.
+.PP
+icmd 00 20 28 43 00 00 ff ff 00 ff
+.br
+Sends a Get SEL entry command for the last entry in the firmware log.
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/iconfig.8 b/doc/iconfig.8
new file mode 100644
index 0000000..d95ed0b
--- /dev/null
+++ b/doc/iconfig.8
@@ -0,0 +1,96 @@
+.TH ICONFIG 8 "Version 1.4: 17 Feb 2010"
+.SH NAME
+ipmiutil_config \- list, save, and restore BMC configuration parameters
+.SH SYNOPSIS
+.B "ipmiutil config [-lpxLNUPREFJTVY] [-r file] [-s file]"
+
+.SH DESCRIPTION
+.I ipmiutil config
+is a program that uses an IPMI driver to send IPMI commands which list,
+save and restore BMC configuration parameters for LAN, Serial, PEF,
+SOL, User, Channel. This combines the functionality of ipmiutil lan (ilan)
+and ipmiutil serial (iserial).
+Note that some of the LAN parameters cannot be restored remotely over
+the IPMI LAN, changing the configuration that is in use.
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+
+.SH OPTIONS
+Command line options are described below.
+
+.IP "-l"
+Lists BMC configuration parameters with a keyword, index, and its hex values.
+This is the default behavior if no options are specified.
+.IP "-r config_file"
+Restores BMC configuration from config_file, which was produced with \-s below.
+.IP "-s config_file"
+Saves BMC configuration to config_file. This file could be edited, in certain
+cases, such as to vary the BMC IP address (LanParam 3), or to use the
+UserPassword records. Note that lines beginning with '#' are comments
+and are ignored.
+For editing UserPassword records, convert your text value to hex format;
+for example "echo 'mypassword' |od \-t x1", and leave off the trailing 0a.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-p password_to_set"
+This specifies the firmware password to set for BMC LAN access for all users
+during the restore.
+If not specified, the password configuration will not be changed, unless a
+valid UserPassword record is present in the file to be restored.
+Note that user passwords are write-only via standard IPMI commands.
+.IP "-L lan_ch_num"
+This specifies the IPMI LAN channel number used for BMC LAN. This varies
+by platform, and can be found in the platform technical specifications.
+By default, bmcconfig scans all IPMI channels to find a LAN channel for
+BMC LAN.
+
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) icmd(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/idcmi.8 b/doc/idcmi.8
new file mode 100644
index 0000000..c110afd
--- /dev/null
+++ b/doc/idcmi.8
@@ -0,0 +1,122 @@
+.TH IDCMI 8 "Version 1.0: 02 Feb 2012"
+.SH NAME
+ipmiutil_dcmi \- handle DCMI functions
+
+.SH SYNOPSIS
+.B "ipmiutil dcmi [-admsx -NUPREFTVY] <function>
+
+.SH DESCRIPTION
+This
+.I ipmiutil dcmi
+subcommand handles DCMI command functions according to the DCMI
+specification.
+
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+
+.SH OPTIONS
+Command line options are described below.
+.IP "-a string"
+Set the DCMI Asset Tag to this string.
+.IP "-d string"
+Set the DCMI MC ID to this string.
+.IP "-m 002000"
+Target a specific MC (e.g. bus 00, sa 20, lun 00).
+This could be used for PICMG or ATCA blade systems.
+The trailing character, if present, indicates SMI addressing if 's',
+or IPMB addressing if 'i' or not present.
+.IP "-s"
+When getting info, also get the DCMI sensor information.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH FUNCTIONS
+
+.IP "info"
+Get DCMI Capabilities, MC ID, and Asset Tag. This is the default function
+if no function was specified.
+
+.IP "power "
+Get DCMI Power reading and DCMI Power limit, if supported in the DCMI capabilties.
+.IP "power set_limit"
+Set Power limit
+.IP "power set_action <action>"
+Set Power limit exception action
+(where action = no_action | power_off | log_sel)
+.IP "power set_correction"
+Set Power limit correction time (in ms)
+.IP "power set_sample"
+Set Power limit sampling period (in sec)
+.IP "power activate"
+Activate Power limit
+.IP "power deactivate"
+Deactivate Power limit
+
+
+.IP "thermal"
+Get/Set DCMI Thermal parameters. This requires DCMI 1.5 support.
+
+.IP "config"
+Get/Set DCMI Configuration parameters. This requires DCMI 1.5 support.
+
+.IP "help"
+Show the help (usage) message
+
+.SH "EXAMPLES"
+ipmiutil dcmi info \-s
+.br
+Gets DCMI information, plus DCMI sensor information
+.PP
+ipmiutil dcmi \-N 192.168.1.1 \-U root \-P pswd
+.br
+Gets DCMI information over IPMI LAN.
+
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2010 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/idelloem.8 b/doc/idelloem.8
new file mode 100644
index 0000000..997fe16
--- /dev/null
+++ b/doc/idelloem.8
@@ -0,0 +1,177 @@
+.TH IDELLOEM 8 "Version 1.0: 17 Aug 2011"
+.SH NAME
+ipmiutil_delloem \- OEM commands for Dell servers
+.SH SYNOPSIS
+.B "ipmiutil delloem [-mx -NPRUEFJTVY] commands"
+
+.SH DESCRIPTION
+.I ipmiutil delloem commands
+is a program that uses Dell OEM IPMI commands to
+perform platform-specific functions.
+
+.SH OPTIONS
+
+.IP "-m 002000"
+Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00).
+This could be used for PICMG or ATCA blade systems.
+The trailing character, if present, indicates SMI addressing if 's',
+or IPMB addressing if 'i' or not present.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH COMMANDS
+
+.RS
+.RE
+.TP
+\fImac\fP \fIlist\fP
+.RS
+ Lists the MAC address of LOMs
+
+.RE
+.TP
+\fImac\fP \fIget\fP <\fBNIC number\fR>
+.RS
+ Shows the MAC address of specified LOM. 0-7 System LOM, 8- DRAC/iDRAC.
+
+.RE
+.TP
+\fIlan\fP \fIset\fP <\fBMode\fR>
+.RS
+ Sets the NIC Selection Mode (dedicated, shared,
+ shared with failover lom2, shared with Failover all loms).
+
+.RE
+.TP
+\fIlan\fP \fIget\fP
+.RS
+ Returns the current NIC Selection Mode (dedicated, shared,
+ shared with failover lom2, shared with Failover all loms).
+
+.RE
+.TP
+\fIlan\fP \fIget\fP \fIactive\fP
+.RS
+ Returns the current active NIC (dedicated, LOM1, LOM2, LOM3, LOM4).
+
+.RE
+.TP
+\fIpowermonitor\fP
+.RS
+ Shows power tracking statistics
+
+.RE
+.TP
+\fIpowermonitor\fP \fIclear\fP \fIcumulativepower\fP
+.RS
+ Reset cumulative power reading
+
+.RE
+.TP
+\fIpowermonitor\fP \fIclear\fP \fIpeakpower\fP
+.RS
+ Reset peak power reading
+
+.RE
+.TP
+\fIpowermonitor\fP \fIpowerconsumption\fP
+.RS
+ Displays power consumption in <watt|btuphr>
+
+.RE
+.TP
+\fIpowermonitor\fP \fIpowerconsumptionhistory\fP <\fBwatt|btuphr\fR>
+.RS
+ Displays power consumption history
+
+.RE
+.TP
+\fIpowermonitor\fP \fIgetpowerbudget\fP
+.RS
+ Displays power cap in <watt|btuphr>
+
+.RE
+.TP
+\fIpowermonitor\fP \fIsetpowerbudget\fP <\fBval\fR> <\fBwatt|btuphr|percent\fR>
+.RS
+ Allows user to set the power cap in <watt|BTU/hr|percentage>
+
+.RE
+.TP
+\fIpowermonitor\fP \fIenablepowercap\fP
+.RS
+ To enable set power cap
+
+.RE
+.TP
+\fIpowermonitor\fP \fIdisablepowercap\fP
+.RS
+ To disable set power cap
+
+.RE
+.TP
+\fIwindbg\fP \fIstart\fP
+.RS
+ Starts the windbg session (Cold Reset & SOL Activation)
+
+.RE
+.TP
+\fIwindbg\fP \fIend\fP
+.RS
+ Ends the windbg session (SOL Deactivation)
+
+.RE
+.TP
+\fIvFlash\fP \fIinfo\fP \fICard\fP
+.RS
+ Shows Extended SD Card information
+.RE
+
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/idiscover.8 b/doc/idiscover.8
new file mode 100644
index 0000000..e7b05b0
--- /dev/null
+++ b/doc/idiscover.8
@@ -0,0 +1,92 @@
+.TH IDISCOVER 8 "Version 1.0: 02 May 2007"
+.SH NAME
+ipmiutil_discover \- discover IPMI LAN-enabled nodes
+.SH SYNOPSIS
+.B "idiscover [-abegisx]"
+
+.SH DESCRIPTION
+.I idiscover
+is a program that uses IPMI LAN commands to discover any nodes
+on the LAN that are available, by probing the RMCP port (623.)
+on those nodes.
+This utility uses IPMI LAN, so no IPMI drivers are needed.
+There are three methods that can be used:
+.br
+\-a = broadcast RMCP ping method (default)
+.br
+\-g = GetChannelAuthCap command method
+.br
+else = specific RMCP ping method
+.P
+A beginning IP address can be specified with \-b for broadcast and specific
+methods. An ending IP can be specified for non-broadcast methods.
+
+.SH OPTIONS
+Command line options are described below.
+.IP "-a"
+All nodes, use the broadcast ping method. This is the default if no options
+are specified. This will detect the first enabled ethernet interface, and
+defaults to the broadcast address x.x.x.255 (where x.x.x.x is IP address)
+unless \-b is used to specify otherwise.
+.IP "-b <ip>"
+Beginning IP address, required, unless using broadcast with defaults.
+This could be a specific IP address, or a broadcast address, ending in 255,
+if the broadcast method (\-a) is used.
+.IP "-e <ip>"
+Endign IP address of the range. Not used for broadcast method.
+If this is not specified, a range of one IP address matching the beginning
+IP is assumed.
+.IP "-g"
+Use the GetChannelAuthenticationCapabilities command method over IPMI LAN
+instead of the RMCP ping. Not compatible with broadcast.
+This may be useful if the vendor BMC does not support RMCP ping for some
+reason.
+.IP "-i eth0"
+The interface name to use when sending the probes. The default is to
+detect the first enabled ethernet interface (e.g. eth0).
+.IP "-m"
+shows MAC address. Uses the broadcast ping method, but uses a raw socket
+so that the MAC address can be displayed. This detects the first enabled
+ethernet interface, and defaults to the broadcast address 255.255.255.255
+like \-a. Using \-m with raw sockets requires root privilege.
+.IP "-r N"
+Repeat the ping N times to each node. Default is to send 1 ping per node.
+.IP "-x"
+Causes extra debug messages to be displayed.
+
+
+.SH "EXAMPLES"
+
+ idiscover \-a \-b 192.168.1.255
+.br
+Sends a broadcast RMCP ping to discover IPMI LAN nodes on the specified subnet.
+.PP
+ idiscover \-b 192.168.1.100 \-e 192.168.1.254
+.br
+Sends RMCP pings to a range of IP addresses.
+.PP
+ idiscover \-g \-b 192.168.1.100 \-e 192.168.1.254
+.br
+Sends GetChannelAuthCap commands to a range of IP addresses.
+
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/iekanalyzer.8 b/doc/iekanalyzer.8
new file mode 100644
index 0000000..c4ca1e2
--- /dev/null
+++ b/doc/iekanalyzer.8
@@ -0,0 +1,251 @@
+.TH IEKANALYZER 8 "Version 1.0: 09 Sep 2010"
+.SH NAME
+ipmiutil_ekanalyzer \- run FRU-Ekeying analyzer with FRU files
+.SH SYNOPSIS
+.B "ipmiutil ekanalyzer [-mx -NPRUEFJTVY] commands"
+.B (deprecated, see ifru instead)
+
+.SH DESCRIPTION
+.I ipmiutil ekanalyzer
+is a program that analyzes FRU Ekeying information from files
+saved from PICMG IPMI systems.
+
+.br
+\fIekanalyzer\fP \fBcommand\fR \fBxx=filename1\fR \fBxx=filename2\fR [\fBrc=filename3\fR]
+.br
+NOTE: This command can support a maximum of 8 files per command line
+
+.IP "\fIfilename1\fP"
+binary file that stores FRU data of a Carrier or an AMC module
+
+.IP "\fIfilename2\fP"
+binary file that stores FRU data of an AMC module.
+These binary files can be generated from this command:
+ \fIipmiutil fru \-i id \-d filename\fP
+
+.IP "\fIfilename3\fP"
+configuration file used for configuring On-Carrier Device ID or OEM GUID. This file is optional.
+
+.IP "\fIxx\fP"
+indicates the type of the file. It can take the following value:
+.br
+ \fIoc\fP : On-Carrier device
+.br
+ \fIa1\fP : AMC slot A1
+.br
+ \fIa2\fP : AMC slot A2
+.br
+ \fIa3\fP : AMC slot A3
+.br
+ \fIa4\fP : AMC slot A4
+.br
+ \fIb1\fP : AMC slot B1
+.br
+ \fIb2\fP : AMC slot B2
+.br
+ \fIb3\fP : AMC slot B3
+.br
+ \fIb4\fP : AMC slot B4
+.br
+ \fIsm\fP : Shelf Manager
+
+
+.SH OPTIONS
+
+.IP "-m 002000"
+Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00).
+This could be used for PICMG or ATCA blade systems.
+The trailing character, if present, indicates SMI addressing if 's',
+or IPMB addressing if 'i' or not present.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH "COMMANDS"
+.RE
+.TP
+.br
+The available commands for ekanalyzer are:
+
+.RE
+.RS
+.TP
+\fIprint\fP [\fBcarrier\fR | \fBpower\fR | \fBall\fR]
+.RS
+.TP
+\fIcarrier\fP (default) \fBoc=filename1\fR \fBoc=filename2\fR \fB...\fR
+.br
+
+Display point to point physical connectivity between carriers and AMC modules.
+ Example:
+ # ipmiutil ekanalyzer print carrier oc=fru oc=carrierfru
+ From Carrier file: fru
+ Number of AMC bays supported by Carrier: 2
+ AMC slot B1 topology:
+ Port 0 =====> On Carrier Device ID 0, Port 16
+ Port 1 =====> On Carrier Device ID 0, Port 12
+ Port 2 =====> AMC slot B2, Port 2
+ AMC slot B2 topology:
+ Port 0 =====> On Carrier Device ID 0, Port 3
+ Port 2 =====> AMC slot B1, Port 2
+ *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+ From Carrier file: carrierfru
+ On Carrier Device ID 0 topology:
+ Port 0 =====> AMC slot B1, Port 4
+ Port 1 =====> AMC slot B1, Port 5
+ Port 2 =====> AMC slot B2, Port 6
+ Port 3 =====> AMC slot B2, Port 7
+ AMC slot B1 topology:
+ Port 0 =====> AMC slot B2, Port 0
+ AMC slot B1 topology:
+ Port 1 =====> AMC slot B2, Port 1
+ Number of AMC bays supported by Carrier: 2
+
+.TP
+\fIpower\fP \fBxx=filename1\fR \fBxx=filename2\fR \fB...\fr
+.br
+
+Display power supply information between carrier and AMC modules.
+.TP
+\fIall\fP \fBxx=filename\fR \fBxx=filename\fR \fB...\fr
+.br
+
+Display both physical connectivity and power supply of each carrier and AMC
+modules.
+
+.RE
+.TP
+\fIfrushow\fP \fBxx=filename\fR
+.br
+Convert a binary FRU file into human readable text format. Use \-v option to get
+more display information.
+
+.RE
+.RS
+.TP
+\fIsummary\fP [\fBmatch\fR | \fBunmatch\fR | \fBall\fR]
+.RS
+.TP
+\fImatch\fP (default) \fBxx=filename\fR \fBxx=filename\fR \fB...\fR
+.br
+Display only matched results of Ekeying match between an On-Carrier device
+and an AMC module or between 2 AMC modules. Example:
+ # ipmiutil ekanalyzer summary match oc=fru b1=amcB1 a2=amcA2
+ On-Carrier Device vs AMC slot B1
+ AMC slot B1 port 0 ==> On-Carrier Device 0 port 16
+ Matching Result
+ From On-Carrier Device ID 0
+ Channel ID 11 || Lane 0: enable
+ Link Type: AMC.2 Ethernet
+ Link Type extension: 1000BASE-BX (SerDES Gigabit) Ethernet link
+ Link Group ID: 0 || Link Asym. Match: exact match
+ To AMC slot B1
+ Channel ID 0 || Lane 0: enable
+ Link Type: AMC.2 Ethernet
+ Link Type extension: 1000BASE-BX (SerDES Gigabit) Ethernet link
+ Link Group ID: 0 || Link Asym. Match: exact match
+ *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+ AMC slot B1 port 1 ==> On-Carrier Device 0 port 12
+ Matching Result
+ From On-Carrier Device ID 0
+ Channel ID 6 || Lane 0: enable
+ Link Type: AMC.2 Ethernet
+ Link Type extension: 1000BASE-BX (SerDES Gigabit) Ethernet link
+ Link Group ID: 0 || Link Asym. Match: exact match
+ To AMC slot B1
+ Channel ID 1 || Lane 0: enable
+ Link Type: AMC.2 Ethernet
+ Link Type extension: 1000BASE-BX (SerDES Gigabit) Ethernet link
+ Link Group ID: 0 || Link Asym. Match: exact match
+ *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+ On-Carrier Device vs AMC slot A2
+ AMC slot A2 port 0 ==> On-Carrier Device 0 port 3
+ Matching Result
+ From On-Carrier Device ID 0
+ Channel ID 9 || Lane 0: enable
+ Link Type: AMC.2 Ethernet
+ Link Type extension: 1000BASE-BX (SerDES Gigabit) Ethernet link
+ Link Group ID: 0 || Link Asym. Match: exact match
+ To AMC slot A2
+ Channel ID 0 || Lane 0: enable
+ Link Type: AMC.2 Ethernet
+ Link Type extension: 1000BASE-BX (SerDES Gigabit) Ethernet link
+ Link Group ID: 0 || Link Asym. Match: exact match
+ *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+ AMC slot B1 vs AMC slot A2
+ AMC slot A2 port 2 ==> AMC slot B1 port 2
+ Matching Result
+ From AMC slot B1
+ Channel ID 2 || Lane 0: enable
+ Link Type: AMC.3 Storage
+ Link Type extension: Serial Attached SCSI (SAS/SATA)
+ Link Group ID: 0 || Link Asym. Match: FC or SAS interface {exact match}
+ To AMC slot A2
+ Channel ID 2 || Lane 0: enable
+ Link Type: AMC.3 Storage
+ Link Type extension: Serial Attached SCSI (SAS/SATA)
+ Link Group ID: 0 || Link Asym. Match: FC or SAS interface {exact match}
+ *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
+.TP
+\fIunmatch\fP \fBxx=filename\fR \fBxx=filename\fR \fB...\fr
+.br
+
+Display the unmatched results of Ekeying match between an On-Carrier device
+and an AMC module or between 2 AMC modules
+.TP
+\fIall\fP \fBxx=filename\fR \fBxx=filename\fR \fB...\fr
+.br
+
+Display both matched result and unmatched results of Ekeying match between two
+cards or two modules.
+.RE
+
+.SH "SEE ALSO"
+ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifirewall(8)
+ifru(8) ifruset(8) ifwum(8) igetevent(8) ihealth(8) ihpm(8)
+ilan(8) ipicmg(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) isunoem(8)
+iwdt(8) ipmiutil(8) ipmi_port(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/ievents.8 b/doc/ievents.8
new file mode 100644
index 0000000..4dc72a7
--- /dev/null
+++ b/doc/ievents.8
@@ -0,0 +1,93 @@
+.TH IEVENTS 8 "Version 1.3: 23 June 2009"
+.SH NAME
+ievents \- decode IPMI and PET event data
+.SH SYNOPSIS
+.B "ievents [-bfhnprsx] 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10"
+
+.SH DESCRIPTION
+.I ievents
+is a standalone utility delivered with ipmiutil, used to interpret raw
+hex data from IPMI events or from IPMI PET SNMP trap varbind data.
+This utility uses the same interpretation logic as is used by
+"ipmiutil sel" (showsel) and "ipmiutil getevt" (getevents).
+
+The data bytes in the input are always assumed to be in hex form.
+
+This could be useful if a utility other than "ipmiutil sel" were used to
+obtain IPMI SEL records or events and interpretation is needed.
+
+This would also be needed at an enterprise management station to
+interpret the PET SNMP trap hex data into human-readable form,
+see option \-p.
+
+.SH OPTIONS
+
+.IP "-b bin_file"
+Interpret a file containing raw binary/hex SEL data dumped in binary form,
+such as that produced by "ipmitool sel writeraw bin_file".
+Each set of 16 bytes in the file will be interpreted as an IPMI event.
+(same as \-h)
+
+.IP "-f sel_file"
+Interpret a file containing raw ascii text SEL data captured with
+ipmiutil sel \-r, or some other similar utility.
+Each line in the file should be in this
+form, with no leading spaces:
+.br
+04 00 02 76 a9 4a 47 20 00 04 10 09 6f 42 0f ff
+.br
+If this option is not specified, the default is to use the 16 bytes
+taken from the command-line arguments.
+(same as \-r)
+
+.IP "-h bin_file"
+Interpret a file containing raw binary/hex SEL data dumped in binary form,
+such as that produced by "ipmitool sel writeraw bin_file".
+Each set of 16 bytes in the file will be interpreted as an IPMI event.
+(same as \-b)
+
+.IP "-n"
+This option generates a New IPMI platform event, using 9 bytes of input.
+The input bytes are the same as the last 9 bytes of an IPMI event.
+
+.IP "-p"
+Decode as PET event bytes, where the input is 34 PET hex data bytes,
+skipping the first 8 of the 47-byte PET data.
+The default without \-p assumes that the input is a 16-byte IPMI event.
+
+.IP "-r sel_file"
+Interpret a file containing raw ascii text SEL data captured with
+ipmiutil sel \-r, or some other similar utility.
+(same as \-f)
+
+.IP "-s sensor_file"
+Sensor file with the output of "ipmiutil sensor", used
+to get the PET sensor_type from the sensor_num.
+The default is /usr/share/ipmiutil/sensor_out.txt as
+generated during the ipmiutil package installation.
+This is only needed with PET interpretation (\-p).
+
+.IP "-x"
+show eXtra debug messages
+
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/ifirewall.8 b/doc/ifirewall.8
new file mode 100644
index 0000000..a327a2b
--- /dev/null
+++ b/doc/ifirewall.8
@@ -0,0 +1,152 @@
+.TH IFIREWALL 8 "Version 1.0: 04 Jun 2010"
+.SH NAME
+ipmiutil_firewall \- configure the IPMI firmware firewall functions
+
+.SH SYNOPSIS
+.B "ipmiutil firewall [-mxNUPREFJTVY] parameters"
+
+.SH DESCRIPTION
+This
+.I ipmiutil firewall
+command supports the IPMI Firmware Firewall capability. It may be used to
+add or remove security-based restrictions on certain commands/command
+sub-functions or to list the current firmware firewall restrictions set on
+any commands. For each firmware firewall command listed below, parameters
+may be included to cause the command to be executed with increasing
+granularity on a specific LUN, for a specific NetFn, for a specific IPMI
+Command, and finally for a specific command's sub-function.
+See Appendix H in the IPMI 2.0 Specification for a listing of any
+sub-function numbers that may be associated with a particular command.
+
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+
+.SH OPTIONS
+Command line options are described below.
+.IP "-m 002000"
+Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00).
+This could be used for PICMG or ATCA blade systems.
+The trailing character, if present, indicates SMI addressing if 's',
+or IPMB addressing if 'i' or not present.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH PARAMETERS
+Parameter syntax and dependencies are as follows:
+
+firewall [\fIchannel\fP \fBH\fR] [\fIlun\fP \fBL\fR [ \fInetfn\fP \fBN\fR [\fIcommand\fP \fBC\fR [\fIsubfn\fP \fBS\fR]]]]
+
+Note that if "netfn \fBN\fR" is specified, then "lun \fBL\fR" must also be
+specified; if "command \fBC\fR" is specified, then "netfn \fBN\fR" (and
+therefore "lun \fBL\fR") must also be specified, and so forth.
+
+"channel \fBH\fR" is an optional and standalone parameter. If not specified,
+the requested operation will be performed on the current channel. Note that
+command support may vary from channel to channel.
+
+Firmware firewall commands:
+.RS
+.TP
+\fIinfo\fP [\fB(Parms as described above)\fR]
+.br
+
+List firmware firewall information for the specified LUN, NetFn, and
+Command (if supplied) on the current or specified channel. Listed
+information includes the support, configurable, and enabled bits for
+the specified command or commands.
+
+Some usage examples:
+.RS
+.TP
+\fIinfo\fP [\fBchannel H\fR] [\fBlun L\fR]
+.br
+
+This command will list firmware firewall information for all NetFns for the
+specified LUN on either the current or the specified channel.
+.TP
+\fIinfo\fP [\fBchannel H\fR] [\fBlun L\fR [ \fBnetfn N\fR ]
+.br
+
+This command will print out all command information for a single LUN/NetFn pair.
+.TP
+\fIinfo\fP [\fBchannel H\fR] [\fBlun L\fR [ \fBnetfn N\fR [\fBcommand C\fR] ]]
+.br
+
+This prints out detailed, human-readable information showing the support, configurable,
+and enabled bits for the specified command on the specified LUN/NetFn pair. Information
+will be printed about each of the command subfunctions.
+.TP
+\fIinfo\fP [\fBchannel H\fR] [\fBlun L\fR [ \fBnetfn N\fR [\fBcommand C\fR [\fBsubfn S\fR]]]]
+.br
+
+Print out information for a specific sub-function.
+.RE
+.TP
+\fIenable\fP [\fB(Parms as described above)\fR]
+.br
+
+This command is used to enable commands for a given NetFn/LUN combination on
+the specified channel.
+.TP
+\fIdisable\fP [\fB(Parms as described above)\fR] [\fBforce\fR]
+.br
+
+This command is used to disable commands for a given NetFn/LUN combination on
+the specified channel. Great care should be taken if using the "force"
+option so as not to disable the "Set Command Enables" command.
+.TP
+\fIreset\fP [\fB(Parms as described above)\fR]
+.br
+
+This command may be used to reset the firmware firewall back to a state
+where all commands and command sub-functions are enabled.
+
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2010 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/ifru.8 b/doc/ifru.8
new file mode 100644
index 0000000..5162ed0
--- /dev/null
+++ b/doc/ifru.8
@@ -0,0 +1,111 @@
+.TH IFRU 8 "Version 1.4: 09 Sep 2010"
+.SH NAME
+ipmiutil_fru \- show Field Replacable Unit configuration data
+.SH SYNOPSIS
+.B "ipmiutil fru [-abcdeikmsvx -N node -U user -P/-R pswd -EFJTVY]"
+
+.SH DESCRIPTION
+.I ipmiutil fru
+is a program that uses IPMI commands to
+show FRU configuration data and optionally
+write an asset tag string into the FRU data.
+Setting the asset tag is a function that can be
+used to uniquely identify the unit, even if the
+storage devices are removed or changed.
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+
+.SH OPTIONS
+Command line options are described below.
+.IP "-a asset_string"
+This option specifies an asset tag string to be written
+to the baseboard FRU Product area. The asset tag length is
+limited by the existing FRU Product data, but is usually
+allowed up to 16 characters. The default is to not modify this FRU field.
+.IP "-b"
+Only show the Baseboard FRU data. The default behavior is to also scan
+for any SDR FRU data or DIMM SPD data referenced by the SDRs.
+.IP "-c"
+Show FRU output in a canonical format, with a default delimiter of '|'.
+.IP "-d file"
+Dump binary FRU data to the specified file.
+.IP "-e"
+Show Every FRU output in a bladed chassis, including those under child MCs.
+The default is to show FRUs referred to by just the target MC.
+.IP "-i 00"
+This option specifies a specific FRU ID to show. The input value should be
+in hex (0b, 1a, etc.), as shown from the sensor SDR output.
+By default, all FRU IDs that are specified in the FRU locator SDRs are shown.
+.IP "-k <setsn | setmfgdate | nextboot>"
+These Kontron OEM functions set FRU data based on existing data stored
+elsewhere. The setsn option sets the FRU Board and Product serial number,
+and the setmfgdate option sets the FRU Board Mfg DateTime. The nextboot
+option specifies the boot device for the next boot:
+BIOS, FDD, HDD, CDROM, or network.
+These options are only supported on Kontron ATCA boards which have this
+functionality.
+.IP "-m 002000"
+Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00).
+This could be used for PICMG or ATCA blade systems.
+The trailing character, if present, indicates SMI addressing if 's',
+or IPMB addressing if 'i' or not present.
+.IP "-s serial_num"
+This option specifies a serial number string to be written
+to the baseboard FRU Product area. The serial number can be
+any string up to 16 characters. The default is to not modify this FRU field.
+.IP "-v prod_ver"
+This option specifies a product version number string to be written
+to the baseboard FRU Product area. The version number can be
+any string up to 16 characters. The default is to not modify this FRU field.
+.IP "-x"
+Causes eXtra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/ifruset.8 b/doc/ifruset.8
new file mode 100644
index 0000000..9f72eda
--- /dev/null
+++ b/doc/ifruset.8
@@ -0,0 +1,122 @@
+.TH IFRUSET 8 "Version 1.0: 14 Apr 2010"
+.SH NAME
+ifruset \- show/set Field Replacable Unit configuration data
+.SH SYNOPSIS
+.B "ifruset [-bcimx -unpvsafo -N node -U user -P/-R pswd -EFJTVY]"
+
+.SH DESCRIPTION
+.I ifruset
+is a program that uses IPMI commands to
+show FRU configuration data and optionally
+write any Product area fields into the FRU data.
+Setting the FRU Product area fields is a function
+that might be done by a manufacturer or system integrator.
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if -N.
+
+This program is not built or installed by default.
+Integrators who wish to use it should build ipmiutil from source,
+then do 'cd util; make ifruset'.
+
+.SH OPTIONS
+Command line options are described below.
+.IP "-u manuf"
+This option specifies a product manufacturer string to be written
+to the baseboard FRU Product area field 0. This field can be
+any string up to 20 characters. The default is to not modify this FRU field.
+.IP "-n name"
+This option specifies a product name string to be written
+to the baseboard FRU Product area field 1. This field can be
+any string up to 20 characters. The default is to not modify this FRU field.
+.IP "-p partnum"
+This option specifies a product part number string to be written
+to the baseboard FRU Product area field 2. This field can be
+any string up to 20 characters. The default is to not modify this FRU field.
+.IP "-v prod_ver"
+This option specifies a product version number string to be written
+to the baseboard FRU Product area field 3. The version number can be
+any string up to 20 characters. The default is to not modify this FRU field.
+.IP "-s serial_num"
+This option specifies a serial number string to be written
+to the baseboard FRU Product area field 4. The serial number can be
+any string up to 20 characters. The default is to not modify this FRU field.
+.IP "-a asset_string"
+This option specifies an asset tag string to be written
+to the baseboard FRU Product area field 5. The asset tag length is
+limited by the existing FRU Product data, but is usually
+allowed up to 20 characters. The default is to not modify this FRU field.
+.IP "-f fruid"
+This option specifies a product FRU file ID string to be written
+to the baseboard FRU Product area field 6. This field can be
+any string up to 20 characters.
+.IP "-o oem"
+This option specifies a product OEM field string to be written
+to the baseboard FRU Product area field 7. This field can be
+any string up to 20 characters.
+
+.IP "-b"
+Only show the Baseboard FRU data. The default behavior is to also scan
+for any SDR FRU data or DIMM SPD data referenced by the SDRs.
+.IP "-c"
+Show FRU output in a canonical format, with a default delimiter of '|'.
+.IP "-i 00"
+This option specifies a specific FRU ID to show. The input value should be
+in hex (0b, 1a, etc.), as shown from the sensor SDR output.
+By default, all FRU IDs that are specified in the FRU locator SDRs are shown.
+.IP "-m 002000"
+Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00).
+This could be used for PICMG or ATCA blade systems.
+The trailing character, if present, indicates SMI addressing if 's',
+or IPMB addressing if 'i' or not present.
+.IP "-x"
+Causes eXtra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are -E or -P.
+
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/ifwum.8 b/doc/ifwum.8
new file mode 100644
index 0000000..330811b
--- /dev/null
+++ b/doc/ifwum.8
@@ -0,0 +1,124 @@
+.TH IFWUM 8 "Version 1.0: 24 Aug 2010"
+.SH NAME
+ipmiutil_fwum \- Update IPMC using Kontron OEM Firmware Update Manager
+
+.SH SYNOPSIS
+.B "ipmiutil fwum [-mixNUPREFJTVY] parameters"
+
+.SH DESCRIPTION
+This
+.I ipmiutil fwum
+subcommand updates IPMC firmware using Kontron OEM Firmware Update Manager.
+
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+
+.SH OPTIONS
+Command line options are described below.
+.IP "-i 00"
+This option specifies a specific FRU ID to show. The input value should be
+in hex (0b, 1a, etc.), as shown from the sensor SDR output.
+The default FRU ID is zero (0).
+.IP "-m 002000"
+Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00).
+This could be used for PICMG or ATCA blade systems.
+The trailing character, if present, indicates SMI addressing if 's',
+or IPMB addressing if 'i' or not present.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH PARAMETERS
+\fIfwum\fP \fBparameters\fR
+.RS
+
+.TP
+\fIinfo\fP
+.br
+Show information about current firmware.
+
+.TP
+\fIstatus\fP
+.br
+Show status of each firmware bank present in the hardware.
+
+.TP
+\fIdownload\fP \fBfilename\fR
+.br
+Download the specified firmware image.
+
+.TP
+\fIupgrade\fP [\fBfilename\fR]
+.br
+Install firmware upgrade. If the filename is specified,
+the file is downloaded first, otherwise the last firmware
+downloaded is used.
+
+.TP
+\fIrollback\fP
+.br
+Ask IPMC to rollback to previous version.
+
+.TP
+\fItracelog\fP
+.br
+Show the firmware upgrade log.
+
+
+.SH "EXAMPLES"
+ipmiutil fwum info
+.br
+Gets Firmware information
+.PP
+ipmiutil fwum \-N 192.168.1.1 \-U root \-P pswd download firmware.img
+.br
+Downloads the firmware version contained in firmware.img over IPMI LAN.
+
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2010 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/igetevent.8 b/doc/igetevent.8
new file mode 100644
index 0000000..c5df169
--- /dev/null
+++ b/doc/igetevent.8
@@ -0,0 +1,154 @@
+.TH IGETEVENT 8 "Version 1.2: 17 Feb 2010"
+.SH NAME
+ipmiutil_getevt \- wait for IPMI events
+.SH SYNOPSIS
+.B "ipmiutil getevt [-abosx -t secs -N node -U user -P/-R pswd -EFJTVY]"
+
+.SH DESCRIPTION
+.I ipmiutil getevt
+is a program that uses IPMI commands to
+wait for IPMI events sent from the BMC firmware. These events are
+also sent to the IPMI System Event Log (SEL).
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+
+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.
+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.
+
+.br
+There are several methods to do this which are implemented here.
+.PP
+The SEL method:
+.br
+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.
+This is the only method supported over IPMI LAN, i.e. with \-N.
+.PP
+The ReadEventMessageBuffer method:
+.br
+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.
+.PP
+The OpenIPMI custom method:
+.br
+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 if the OpenIPMI driver is detected, and
+no other method is specified.
+.PP
+The Async Event method:
+.br
+This only gets certain Asynchronous requests from the BMC to an
+SMS OS service, like a remote OS shutdown, and get_software_id.
+This method is disabled by default and only turned on if
+the getevent \-a option is specified. This method is only
+supported via the Intel IMB and OpenIPMI driver interfaces.
+There is an init script provided with ipmiutil to automate the
+task of starting this async event daemon.
+.br
+# chkconfig \-\-add ipmiutil_asy (skip this if no chkconfig)
+.br
+# /etc/init.d/ipmiutil_asy start
+.br
+This listens for IPMI LAN requests for soft-shutdown, and logs
+the output to /var/log/ipmiutil_asy.log
+
+.SH OPTIONS
+Command line options are described below.
+
+.IP "-a"
+Use the Async request method, which receives SMS OS requests
+from the BMC using the IMB or OpenIPMI driver interface. This services
+remote SMS bridge agent requests, like remote OS shutdown and get software_id.
+.IP "-b"
+Run in Background as a daemon. If this option is specified, normal output
+will be redirected to /var/log/ipmiutil_getevt.log. The default is to run
+in foreground.
+.IP "-c"
+Show output in a canonical format, with a delimiter of '|'.
+.IP "-e N"
+Wait for a specific event sensor type N.
+The parameter can be in hex (0x23) or decimal (35).
+The default is 0xFF which means wait for any event.
+.IP "-r F"
+Run script file F when an event occurs. The filename can include a full path.
+The script will be passed the event description as a parameter.
+A sample evt.sh script is included with the ipmiutil package.
+.IP "-o"
+Only run one pass to wait for the first event. Default is to loop for multiple events for the timeout period.
+.IP "-s"
+Use the SEL method to get events. This polls the SEL once a second for new
+events. The last SEL record read is saved in /usr/share/ipmiutil/evt.idx.
+Otherwise, the default is to use the ReadEventMessageBuffer method
+to get new events.
+.IP "-t N"
+Set the timeout period to N seconds. Default is 120 seconds.
+A timeout of 0 means an infinite period.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifru(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/ihealth.8 b/doc/ihealth.8
new file mode 100644
index 0000000..8d510f4
--- /dev/null
+++ b/doc/ihealth.8
@@ -0,0 +1,93 @@
+.TH IHEALTH 8 "Version 1.1: 17 Feb 2010"
+.SH NAME
+ipmiutil_health\- show IPMI health
+.SH SYNOPSIS
+.B "ipmiutil health [-ifhglmnopqsx -N node -U user -P/-R pswd -EFJTVY]"
+
+.SH DESCRIPTION
+.I ipmiutil health
+is a program that uses IPMI commands to
+show the health of the BMC.
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+
+.SH OPTIONS
+Command line options are described below.
+
+.IP "-c"
+Show canonical, delimited output.
+.IP "-f"
+Show the FRUSDR version also.
+.IP "-g"
+Show the IPMI GUID of this system. The GUID is a read-only unique identifier.
+.IP "-h"
+Check the health of the HotSwap Controller also.
+.IP "-l"
+Show the IPMI LAN channel statistics also.
+.IP "-m 002000"
+Target a specific MC (e.g. bus 00, sa 20, lun 00).
+This could be used for PICMG or ATCA blade systems.
+The trailing character, if present, indicates SMI addressing if 's',
+or IPMB addressing if 'i' or not present.
+.IP "-n string"
+Set the System Name to this string in the IPMI System Information.
+.IP "-o string"
+Set the Primary Operating System to this string in the IPMI System Information.
+.IP "-p 1"
+Set the chassis Power restore policy, governing the desired behavior when power was lost and is restored. Values: 0 = stay off, 1 = last state, 2 = always on.
+.IP "-q string"
+Set the Secondary Operating System to this string in the IPMI System Information.
+.IP "-s"
+Show the IPMI Session information also.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/ihpm.8 b/doc/ihpm.8
new file mode 100644
index 0000000..1b93358
--- /dev/null
+++ b/doc/ihpm.8
@@ -0,0 +1,185 @@
+.TH IHPM 8 "Version 1.0: 25 Aug 2010"
+.SH NAME
+ipmiutil_hpm \- PICMG HPM.1 Upgrade Agent
+
+.SH SYNOPSIS
+.B "ipmiutil hpm [-mxNUPREFJTVY] parameters"
+
+.SH DESCRIPTION
+This
+.I ipmiutil hpm
+subcommand updates HPM components using PICMG HPM.1 file
+
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+
+.SH OPTIONS
+Command line options are described below.
+.IP "-m 002000"
+Target a specific MC (e.g. bus 00, sa 20, lun 00).
+This could be used for PICMG or ATCA blade systems.
+The trailing character, if present, indicates SMI addressing if 's',
+or IPMB addressing if 'i' or not present.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH PARAMETERS
+\fIhpm\fP \fBparameters\fR
+.RS
+
+.TP
+\fIcheck\fR
+.br
+Check the target information.
+
+.TP
+\fIcheck\fP \fBfilename\fR
+.br
+Display both the existing target version and image version on the screen.
+
+.TP
+\fIdownload\fP \fBfilename\fR
+.br
+Download specified firmware.
+
+.TP
+\fIupgrade\fP \fBfilename\fR [\fBall\fR] [\fBcomponent x\fR] [\fBactivate\fR]
+.br
+Upgrade the firmware using a valid HPM.1 image file. If no option is specified,
+the firmware versions are checked first and the firmware is upgraded only if they
+are different.
+
+.RS
+.TP
+\fIall\fR
+.br
+Upgrade all components even if the firmware versions are the same
+(use this only after using "check" command).
+
+.TP
+\fIcomponent\fP \fBx\fR
+.br
+Upgrade only given component from the given file.
+.br
+component 0 - BOOT
+.br
+component 1 - RTK
+
+.TP
+\fIactivate\fR
+.br
+Activate new firmware right away.
+
+.RE
+
+.TP
+\fIactivate\fR
+.br
+Activate the newly uploaded firmware.
+
+.TP
+\fItargetcap\fR
+.br
+Get the target upgrade capabilities.
+
+.TP
+\fIcompprop\fP \fBid\fR \fBopt\fR
+.br
+Get the specified component properties. Valid component \fBid\fR: 0-7.
+\fBOpt\fR can be one of following:
+.br
+0 - General properties
+.br
+1 - Current firmware version
+.br
+2 - Description string
+.br
+3 - Rollback firmware version
+.br
+4 - Deferred firmware version
+
+.TP
+\fIabort\fR
+.br
+Abort the on-going firmware upgrade.
+
+.TP
+\fIupgstatus\fR
+.br
+Show status of the last long duration command.
+
+.TP
+\fIrollback\fR
+.br
+Perform manual rollback on the IPM Controller firmware.
+
+.TP
+\fIrollbackstatus\fR
+.br
+Show the rollback status.
+
+.TP
+\fIselftestresult\fR
+.br
+Query the self test results.
+
+.RE
+
+.SH "EXAMPLES"
+ipmiutil hpm targetcap
+.br
+Gets HPM target capabilities
+.PP
+ipmiutil hpm \-N 192.168.1.1 \-U root \-P pswd download firmware.img
+.br
+Downloads the HPM firmware version contained in firmware.img over IPMI LAN.
+
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2010 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/ilan.8 b/doc/ilan.8
new file mode 100644
index 0000000..31b26ae
--- /dev/null
+++ b/doc/ilan.8
@@ -0,0 +1,305 @@
+.TH ILAN 8 "Version 1.8: 17 Feb 2010"
+.SH NAME
+ipmiutil_lan \- show and configure BMC LAN parameters and
+set up a PEF entry to send BMC LAN Alerts for OS Critical Stop log events
+.SH SYNOPSIS
+.B "ipmiutil lan [-abcdefghijklmnopq#rstuvwxyzBDQK -i eth1 ]"
+ [\-I ipadr \-M macadr \-S subnet \-B baud_sol ]
+ [\-G gwyip \-H gwymac \-L lan_channel_num ]
+ [\-A alertip \-X alertmac \-C community ]
+ [\-u user_to_set \-p password_to_set ]
+ [\-N nodename \-U username \-Fimb ]
+ [\-P/\-R rmt_node_pswd \-EFJTVY ]
+
+.SH DESCRIPTION
+.I ipmiutil lan
+shows or sets all of the IPMI LAN Parameters to enable
+remote LAN sessions or BMC LAN Alerts. The IP address and MAC address of
+the local system, the default gateway, and the alert destination
+can be defaulted to those specified in Linux, or can be overridden
+by user parameters.
+It also creates a new Platform Event Filter table entry for an OS Critical
+Stop (0x20) SEL firmware log event, so that it will be enabled to send a
+BMC LAN Alert. This utility will skip the PEF records if the system does
+not support IPMI 1.5 or greater.
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+
+.SH OPTIONS
+Command line options are described below.
+Note that without options, ipmiutil lan behaves as if option \-r were used.
+To configure IPMI LAN & PEF, use option \-e.
+
+.IP "-a alertnum"
+Specify which PEF alert number is to be used. Default is 1. This would only
+be used if extra PEF alert destinations had been set.
+.IP "-b authmask"
+Specify a certain authtype mask in hex to use when configuring this channel.
+The default mask is 0x16, so to include authtype None (bit 0), it would
+require entering '\-b 17'.
+.IP "-c"
+Show Canonical output, which shows only interpreted text and streamlines
+the parameters shown, using a common delimiter.
+.IP "-d"
+This option disables the IPMI LAN and PEF parameters, so as not to allow BMC
+LAN connections or alerts. This option also sets the IP address to zeros.
+.IP "-e"
+This option enables the BMC LAN configuration and PEF event alerts.
+The utility will attempt to obtain the default BMC LAN parameters
+from the OS automatically, or they can be specified with command
+options below.
+.IP "-f"
+Set the ARP control parameter to 1 = gratuituous ARPs, 2 = ARP responses,
+or 3 = both grat ARP and ARP responses. The default is 1.
+.IP "-g"
+This specifies the secondary gateway IP address to use for the BMC LAN.
+The default is to omit this parameter and only use the default gateway.
+See also \-G.
+.IP "-h"
+Set the IPMI VLAN ID to this value. Setting to a value >=4096 disables the
+VLAN ID. The default behavior is not to set this parameter.
+.IP "-i ethif"
+By default, the eth0 interface is used to find IP and MAC addresses.
+Sometimes, however, the first ethernet port on the baseboard may
+be represented by Linux as eth1 or eth2 instead. If so, use this
+option to indicate the correct ethernet interface to use. By default,
+ipmiutil lan will scan up to 32 eth interfaces for the onboard one that
+BMC LAN uses.
+.IP "-j"
+This sets a custom PEF rule as the last PEF entry. The input is
+a series of 10 hex bytes, forming the PEF entry. For example, this
+sample PEF entry would perform a power down action if the Baseboard Temp
+reached its threshold.
+ "ipmiutil lan \-e \-j020110ffff013001950a"
+.IP "-k"
+This causes ipmiutil lan to also insert two rules to send alerts for
+transition-to-OK events, including Power Redundancy OK and Temperature OK.
+.IP "-l"
+This option enables the BMC LAN configuration, but not PEF events.
+The utility will attempt to obtain the default BMC LAN parameters
+from the OS automatically, or they can be specified with command
+options below.
+.IP "-n num"
+By default, the new PEF entry for OS Critical Stop is inserted at
+offset 12 into the table. This can be changed to insert it at an
+offset > 12 if another entry already exists at offset 12.
+.IP "-o"
+Disable Only SOL. This could be used after the IPMI LAN was configured, to
+disable Serial-Over-LAN console access but still allow other IPMI LAN access.
+.IP "-p password_to_set"
+This specifies the firmware password to set for BMC LAN access.
+If not specified, the user and password configuration will not be changed.
+.IP "-q"
+Specify an alternate user number for the LAN username from the \-u option.
+This is normally user number 2, 3, or 4, where 2 is the default.
+The maximum number of users is 15. Same as -# below.
+.IP "-#"
+Specify an alternate user number for the LAN username from the \-u option.
+Same as \-q above.
+.IP "-r"
+This option just reads the configuration without writing any BMC LAN
+parameters or writing any new entries to the PEF table.
+.IP "-s"
+This option will also display some of the Serial parameters.
+.IP "-t"
+Test if the BMC LAN has already been configured. Returns 0 if so.
+.IP "-u username_to_set"
+This specifies the firmware username to set for BMC LAN access.
+If a username is specified, user 3 will be set.
+If not specified, the default user 1 will be used.
+.IP "-v priv"
+Set a specific access priVilege for this user, where priv can be:
+1=Callback, 2=User, 3=Operator, 4=Admin, 5=OEM, 15=NoAccess
+The default if not specified or specified in error, is to use 4=Admin.
+.IP "-w N"
+Set the Gratuitous ARP Interval to N seconds. This has no effect if
+the firmware does not support Grat-ARP, as shown in Lan Param 10.
+If not set, the interval remains at the firmware default.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-y N"
+Set the OEM LAN Failover parameter to N. Values for N with Intel Romley/S2600 baseboards: 1 = enable, 0 = disable. Values for N with SuperMicro baseboards: 2 = failover, 1 = lan1 , 0 = dedicated.
+.IP "-z"
+Also show the IPMI LAN Statistics
+.IP "-A alert_ip_addr"
+This specifies the SNMP Alert Destination IP address to use for the BMC LAN.
+By default, this utility will attempt to obtain this from the
+/etc/snmp/snmpd.conf file, via the trapsink parameter.
+The alert destination will see the BMC LAN traps with the
+enterprises.3183.1.1 OID. If no alert IP address is specified in either
+snmpd.conf or this parameter, or if that IP address does not respond,
+the other SNMP parameters for BMC LAN will be skipped.
+.IP "-B baud_sol"
+This specifies the Baud rate for SerialOverLan. The possible values are:
+9600, 19.2k, 38.4k, 57.6k, and 115.2k. The default is 19.2k.
+.IP "-C snmp_community"
+This specifies the SNMP Community name to use for BMC LAN Alerts.
+The default community string is "public".
+This parameter is ignored if there is no Alert IP address.
+.IP "-D "
+This causes the local IP address to be determined by DHCP instead of a
+static IP address.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-G gwy_ip_addr"
+This specifies the default gateway IP address to use for the BMC LAN.
+The default is to automatically obtain this from the Linux route table.
+.IP "-H gwy_mac_addr"
+This specifies the default gateway MAC address to use for the BMC LAN.
+The format can be either 11:22:33:44:55:66 or 11-22-33-44-55-66.
+The default is to try to automatically obtain this by sending an arp request
+from an OS LAN eth interface: the default one, or as specified by \-i.
+.IP "-K hostname"
+This specifies the IPMI hostname to set, for Kontron servers only.
+This enables the firmware to properly map the IP address to a hostname,
+especially with the web interface.
+The default is not to set this parameter, and use IP address only.
+.IP "-I ip_addr"
+This specifies the local IP address to use for the BMC LAN on eth0.
+The default is to automatically obtain this from the Linux ifconfig.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-L lan_ch_num"
+This specifies the IPMI LAN channel number used for BMC LAN. This varies
+by platform, and can be found in the platform technical specifications.
+For instance, Intel platforms usually use channels 1 & 2 for onboard NICs,
+and channel 3 for optional RMM NICs.
+By default, ipmiutil lan scans all IPMI channels to find the first LAN
+channel for BMC LAN.
+To just list all IPMI channels to see what is available, use the string 'list'
+instead of a LAN channel number. This will list the channels and exit.
+.IP "-M mac_addr"
+This specifies the local MAC address to use for the BMC LAN on eth0.
+The format can be either 11:22:33:44:55:66 or 11-22-33-44-55-66.
+The default is to automatically obtain this from the Linux ifconfig.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-P rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+Same as \-R below.
+.IP "-Q"
+Set the IPMI VLAN Priority. The default priority is 0.
+.IP "-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+Same as \-P above.
+.IP "-S subnet"
+This specifies the local subnet mask to use for the BMC LAN on eth0.
+The default is to automatically obtain this from the Linux ifconfig.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5,
+4=Straight Password, 5=OEM.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level,
+3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-X alert_mac_addr"
+This specifies the SNMP Alert Destinations's MAC address to use for the BMC LAN.
+The format can be either 11:22:33:44:55:66 or 11-22-33-44-55-66.
+The default is to attempt to obtain this from the Linux arp cache.
+This parameter is ignored if there is no Alert IP address.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH EXAMPLES
+To read existing settings:
+.br
+ipmiutil lan \-r
+.PP
+To enable IPMI LAN with default settings detected, assuming shared MAC/IP:
+.br
+ipmiutil lan \-e
+.PP
+To set up IPMI LAN for a unique IP address and set PEF SNMP Alerts:
+.br
+ipmiutil lan \-e \-I 192.168.1.1 \-A 192.168.1.10
+.PP
+To set the IPMI LAN password for the default user:
+.br
+ipmiutil lan \-e \-p mypassword
+.PP
+To disable access to the IPMI LAN channel:
+.br
+ipmiutil lan \-d
+
+.SH "SAMPLE PEF TABLE"
+These 11 PEF table entries are configured from the factory for various
+Intel Sahalee BMC systems, and will be applied as the defaults for a
+system with an empty PEF table:
+.br
+PEF(01): 01 Temperature Sensor event - enabled for alert
+.br
+01 c0 01 01 00 ff ff 01 ff 01 95 0a 00 00 00 00 00 00 00 00 00
+.br
+PEF(02): 02 Voltage Sensor event - enabled for alert
+.br
+02 c0 01 01 00 ff ff 02 ff 01 95 0a 00 00 00 00 00 00 00 00 00
+.br
+PEF(03): 04 Fan Failure event - enabled for alert
+.br
+03 c0 01 01 00 ff ff 04 ff 01 95 0a 00 00 00 00 00 00 00 00 00
+.br
+PEF(04): 05 Chassis Intrusion event - enabled for alert
+.br
+04 c0 01 01 00 ff ff 05 05 6f 01 00 00 00 00 00 00 00 00 00 00
+.br
+PEF(05): 08 Power Supply Fault event - enabled for alert
+.br
+05 c0 01 01 00 ff ff 08 ff 6f 06 00 00 00 00 00 00 00 00 00 00
+.br
+PEF(06): 0c Memory ECC Error event - enabled for alert
+.br
+06 c0 01 01 00 ff ff 0c 08 6f 02 00 00 00 00 00 00 00 00 00 00
+.br
+PEF(07): 0f FRB Failure event - enabled for alert
+.br
+07 c0 01 01 00 ff ff 0f 06 6f 01 00 00 00 00 00 00 00 00 00 00
+.br
+PEF(08): 07 BIOS POST Error event - enabled for alert
+.br
+08 c0 01 01 00 ff ff 07 ff 6f 1c 00 00 00 00 00 00 00 00 00 00
+.br
+PEF(09): 13 Fatal NMI event - enabled for alert
+.br
+09 c0 01 01 00 ff ff 13 ff 6f 3e 03 00 00 00 00 00 00 00 00 00
+.br
+PEF(10): 23 Watchdog Timer Reset event - enabled for alert
+.br
+0a c0 01 01 00 ff ff 23 03 6f 0e 00 00 00 00 00 00 00 00 00 00
+.br
+PEF(11): 12 System Restart event - enabled for alert
+.br
+0b c0 01 01 00 ff ff 12 ff 6f 02 00 00 00 00 00 00 00 00 00 00
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/ipicmg.8 b/doc/ipicmg.8
new file mode 100644
index 0000000..0f4523f
--- /dev/null
+++ b/doc/ipicmg.8
@@ -0,0 +1,157 @@
+.TH IPICMG 8 "Version 1.0: 04 Jun 2010"
+.SH NAME
+ipmiutil_picmg \- send specific PICMG extended IPMI commands
+
+.SH SYNOPSIS
+.B "ipmiutil picmg [-mixNUPREFJTVY] parameters"
+
+.SH DESCRIPTION
+This
+.I ipmiutil picmg
+subcommand sends specific PICMG/ATCA extended IPMI commands to the firmware.
+
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+
+.SH OPTIONS
+Command line options are described below.
+.IP "-i 00"
+This option specifies a specific FRU ID to show. The input value should be
+in hex (0b, 1a, etc.), as shown from the sensor SDR output.
+The default FRU ID is zero (0).
+.IP "-m 002000"
+Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00).
+This could be used for PICMG or ATCA blade systems.
+The trailing character, if present, indicates SMI addressing if 's',
+or IPMB addressing if 'i' or not present.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH PARAMETERS
+\fIpicmg\fP \fBparameters\fR
+.RS
+
+.TP
+\fIproperties\fP
+Get PICMG properties may be used to
+obtain and print Extension major version information, PICMG identifier,
+FRU Device ID and Max FRU Device ID.
+
+.TP
+\fIaddrinfo\fP
+.br
+
+Get address information. This command may return information on the Hardware
+address, IPMB-0 Address, FRU ID, Site/Entity ID, and Site/Entity Type.
+.TP
+\fIfrucontrol\fP \fBfru id\fR \fBoptions\fR
+.br
+
+Set various control options:
+.RS
+.TP
+\fI0x00\fP - Cold Reset
+.br
+.TP
+\fI0x01\fP - Warm Reset
+.br
+.TP
+\fI0x02\fP - Graceful Reboot
+.br
+.TP
+\fI0x03\fP - Issue Diagnostic Interrupt
+.br
+.TP
+\fI0x04\fP - Quiesce [AMC only]
+.br
+.TP
+\fI0x05-0xFF\fP - Cold Reset
+.br
+.RE
+.TP
+\fIactivate\fP \fBfru id\fR
+.br
+
+Activate the specified FRU.
+.TP
+\fIdeactivate\fP \fBfru id\fR
+.br
+
+Deactivate the specified FRU.
+.TP
+\fIpolicy\fP \fIget\fP \fBfru id\fR
+.br
+
+Get FRU activation policy.
+.TP
+\fIpolicy\fP \fIset\fP \fBfru id\fR \fBlockmask\fR \fBlock\fR
+.br
+
+Set FRU activation policy. \fBlockmask\fR is 1 or 0 to indicate action
+on the deactivation or activation locked bit respectively. \fBlock\fR is
+1 or 0 to set/clear locked bit.
+.TP
+\fIportstate\fP \fBset\fR|\fBgetall\fR|\fBgetgranted\fR|\fBgetdenied\fR \fBparameters\fR
+.br
+
+Get or set various port states. See usage for parameter details.
+
+
+
+.SH "EXAMPLES"
+ipmiutil picmg properties
+.br
+Gets PICMG properties from the default target address (slave address 0x20).
+.PP
+ipmiutil picmg \-N 192.168.1.1 \-U root \-P pswd addrinfo
+.br
+Gets PICMG Address Information from the specified IP address.
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2010 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/ipmi_port.8 b/doc/ipmi_port.8
new file mode 100644
index 0000000..15287e2
--- /dev/null
+++ b/doc/ipmi_port.8
@@ -0,0 +1,44 @@
+.TH IPMI_PORT 8 "Version 1.0: 14 Apr 2010"
+.SH NAME
+ipmi_port \- a daemon to bind RMCP port 623 to prevent portmap from using it
+
+.SH SYNOPSIS
+.B "ipmi_port [-bx]"
+
+.SH DESCRIPTION
+This
+.I ipmi_port
+service starts and binds port 623, then sleeps forever, so that the portmap
+service will not try to reuse port 623, which it otherwise might try to do.
+Since the IPMI firmware snoops the NIC channel and grabs any traffic destined
+for RMCP port 623, any application in the OS which tried to use port 623
+would fail.
+
+.SH OPTIONS
+Command line options are described below.
+.IP "-b"
+Background mode. Convert to a daemon and run in background.
+Without specifying this option, ipmi_port will run in foreground.
+.IP "-x"
+Causes eXtra debug messages to be displayed.
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/ipmiutil.8 b/doc/ipmiutil.8
new file mode 100644
index 0000000..24d0a3a
--- /dev/null
+++ b/doc/ipmiutil.8
@@ -0,0 +1,116 @@
+.TH IPMIUTIL 8 "Version 1.1: 10 May 2012"
+.SH NAME
+ipmiutil \- a meta-command to invoke various IPMI functions.
+
+.SH SYNOPSIS
+.B "ipmiutil <command> [-x -NUPREFJTVY] [other command options]
+
+.SH DESCRIPTION
+This utility performs various IPMI functions. Each of the individual
+commands in the ipmiutil project can be invoked via this meta-command.
+The <command> is one of the following:
+ alarms show/set the front panel alarm LEDs and relays
+ leds show/set the front panel alarm LEDs and relays
+ cmd send a specified raw IPMI command to the BMC
+ config list/save/restore BMC configuration parameters
+ dcmi get/set DCMI parameters
+ discover discover all IPMI servers on this LAN
+ ekanalyzer run FRU-EKeying analyzer on FRU files (deprecated, see fru)
+ events decode IPMI events and display them
+ firewall show/set firmware firewall functions
+ fru show decoded FRU inventory data, write asset tag
+ fwum OEM firmware update manager extensions
+ getevt get IPMI events and display them, event daemon
+ getevent get IPMI events and display them, event daemon
+ health check and show the basic health of the IPMI BMC
+ hpm HPM firmware update manager extensions
+ lan show/set IPMI LAN parameters and PEF table
+ picmg show/set picmg extended functions
+ reset cause the BMC to reset or power down the system
+ sel show/clear firmware System Event Log records
+ sensor show Sensor Data Records, readings, thresholds
+ serial show/set IPMI Serial & Terminal Mode parameters
+ sol start/stop an SOL console session
+ smcoem SuperMicro OEM functions
+ sunoem Sun OEM functions
+ delloem Dell OEM functions
+ tsol Tyan SOL console start/stop session
+ wdt show/set/reset the watchdog timer
+.br
+For help on each command (e.g. 'sel'), enter:
+ ipmiutil sel -?
+.br
+For man pages on each command, its man page is named "i<command>",
+or refer to SEE ALSO below.
+
+.br
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N is used.
+
+.SH OPTIONS
+Command options are described in the man page for each command.
+Below are a few of the common options.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH "EXAMPLES"
+ipmiutil sel
+.br
+Shows the IPMI System Event Log entries.
+.PP
+ipmiutil wdt
+.br
+Shows the watchdog timer values.
+.PP
+
+.SH "SEE ALSO"
+ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifirewall(8)
+ifru(8) ifruset(8) ifwum(8) igetevent(8) ihealth(8) ihpm(8)
+ilan(8) ipicmg(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) isunoem(8)
+iwdt(8) ipmiutil(8) ipmi_port(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/ipmiutil.spec b/doc/ipmiutil.spec
new file mode 100644
index 0000000..cd849f2
--- /dev/null
+++ b/doc/ipmiutil.spec
@@ -0,0 +1,424 @@
+# spec file for package ipmiutil
+#
+# Copyright (c) 2012 Andy Cress
+#
+Name: ipmiutil
+Version: 2.9.3
+Release: 1%{?dist}
+Summary: Easy-to-use IPMI server management utilities
+License: BSD
+Group: System/Management
+Source: http://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.gz
+URL: http://ipmiutil.sourceforge.net
+BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
+# Suggests: cron or vixie-cron or cronie or similar
+%if 0%{?fedora} >= 15
+BuildRequires: systemd
+Requires: systemd-units
+%endif
+%if 0%{?suse_version} >= 1210
+%define req_systemd 1
+%endif
+%if 0%{?req_systemd}
+BuildRequires: openssl-devel gcc gcc-c++ libtool systemd
+%define unit_dir %{_unitdir}
+%define systemd_fls %{unit_dir}
+# Requires: %{?systemd_requires}
+%else
+BuildRequires: openssl-devel gcc gcc-c++ libtool
+%if 0%{?fedora} == 16
+%define unit_dir /lib/systemd/system
+%else
+%define unit_dir %{_unitdir}
+%endif
+%define systemd_fls %{_datadir}/%{name}
+%endif
+%define init_dir %{_initrddir}
+
+%description
+The ipmiutil package provides easy-to-use utilities to view the SEL,
+perform an IPMI chassis reset, set up the IPMI LAN and Platform Event Filter
+entries to allow SNMP alerts, Serial-Over-LAN console, event daemon, and
+other IPMI tasks.
+These can be invoked with the metacommand ipmiutil, or via subcommand
+shortcuts as well. IPMIUTIL can also write sensor thresholds, FRU asset tags,
+and has a full IPMI configuration save/restore.
+An IPMI driver can be provided by either the OpenIPMI driver (/dev/ipmi0)
+or the Intel IPMI driver (/dev/imb), etc. If used locally and no driver is
+detected, ipmiutil will use user-space direct I/Os instead.
+
+%package devel
+Group: Development/Libraries
+Summary: Includes libraries and headers for the ipmiutil package
+Provides: ipmiutil-static = %{version}-%{release}
+
+%description devel
+The ipmiutil-devel package contains headers and libraries which are
+useful for building custom IPMI applications.
+
+%prep
+%setup -q
+
+%build
+%if 0%{?fedora} >= 15
+autoconf
+%endif
+%if 0%{?req_systemd}
+%configure --enable-systemd
+%else
+%configure
+%endif
+make
+
+%install
+rm -rf %{buildroot}
+make install DESTDIR=%{buildroot}
+
+%clean
+rm -rf %{buildroot}
+
+%files
+%defattr(-, root, root, -)
+%dir %{_datadir}/%{name}
+%dir %{_var}/lib/%{name}
+%{_bindir}/ipmiutil
+%{_bindir}/idiscover
+%{_bindir}/ievents
+%{_sbindir}/iseltime
+%{_sbindir}/ipmi_port
+%{_sbindir}/ialarms
+%{_sbindir}/iconfig
+%{_sbindir}/icmd
+%{_sbindir}/ifru
+%{_sbindir}/igetevent
+%{_sbindir}/ihealth
+%{_sbindir}/ilan
+%{_sbindir}/ireset
+%{_sbindir}/isel
+%{_sbindir}/isensor
+%{_sbindir}/iserial
+%{_sbindir}/isol
+%{_sbindir}/iwdt
+%{_sbindir}/ipicmg
+%{_sbindir}/ifirewall
+%{_sbindir}/ifwum
+%{_sbindir}/ihpm
+%{_datadir}/%{name}/ipmiutil_evt
+%{_datadir}/%{name}/ipmiutil_asy
+%{_datadir}/%{name}/ipmiutil_wdt
+%{_datadir}/%{name}/ipmi_port
+%{_datadir}/%{name}/ipmi_info
+%{_datadir}/%{name}/checksel
+%{systemd_fls}/ipmiutil_evt.service
+%{systemd_fls}/ipmiutil_asy.service
+%{systemd_fls}/ipmiutil_wdt.service
+%{systemd_fls}/ipmi_port.service
+%{_datadir}/%{name}/ipmiutil.env
+%{_datadir}/%{name}/ipmiutil.pre
+%{_datadir}/%{name}/ipmiutil.setup
+%{_datadir}/%{name}/ipmi_if.sh
+%{_datadir}/%{name}/evt.sh
+%{_datadir}/%{name}/ipmi.init.basic
+%{_datadir}/%{name}/bmclanpet.mib
+%{_mandir}/man8/isel.8*
+%{_mandir}/man8/isensor.8*
+%{_mandir}/man8/ireset.8*
+%{_mandir}/man8/igetevent.8*
+%{_mandir}/man8/ihealth.8*
+%{_mandir}/man8/iconfig.8*
+%{_mandir}/man8/ialarms.8*
+%{_mandir}/man8/iwdt.8*
+%{_mandir}/man8/ilan.8*
+%{_mandir}/man8/iserial.8*
+%{_mandir}/man8/ifru.8*
+%{_mandir}/man8/icmd.8*
+%{_mandir}/man8/isol.8*
+%{_mandir}/man8/ipmiutil.8*
+%{_mandir}/man8/idiscover.8*
+%{_mandir}/man8/ievents.8*
+%{_mandir}/man8/ipmi_port.8*
+%{_mandir}/man8/ipicmg.8*
+%{_mandir}/man8/ifirewall.8*
+%{_mandir}/man8/ifwum.8*
+%{_mandir}/man8/ihpm.8*
+%{_mandir}/man8/isunoem.8*
+%{_mandir}/man8/idelloem.8*
+%{_mandir}/man8/ismcoem.8*
+%{_mandir}/man8/iekanalyzer.8*
+%{_mandir}/man8/itsol.8*
+%{_mandir}/man8/idcmi.8*
+%doc AUTHORS ChangeLog COPYING NEWS README TODO
+%doc doc/UserGuide
+
+%files devel
+%defattr(-,root,root)
+# %{_datadir}/%{name} is used by both ipmiutil and ipmituil-devel
+%dir %{_datadir}/%{name}
+%{_datadir}/%{name}/ipmi_sample.c
+%{_datadir}/%{name}/ipmi_sample_evt.c
+%{_datadir}/%{name}/isensor.c
+%{_datadir}/%{name}/ievents.c
+%{_datadir}/%{name}/isensor.h
+%{_datadir}/%{name}/ievents.h
+%{_datadir}/%{name}/Makefile
+%{_includedir}/ipmicmd.h
+%{_libdir}/libipmiutil.a
+%{_libdir}/libipmiutil.so
+
+
+%pre
+%if 0%{?req_systemd}
+%service_add_pre ipmi_port.service ipmiutil_evt.service ipmiutil_asy.service ipmiutil_wdt.service
+%endif
+
+%post
+# POST_INSTALL, $1 = 1 if rpm -i, $1 = 2 if rpm -U
+if [ "$1" = "1" ]
+then
+ # doing rpm -i, first time
+ vardir=%{_var}/lib/%{name}
+ scr_dir=%{_datadir}/%{name}
+
+%if 0%{?req_systemd}
+%service_add_post ipmi_port.service ipmiutil_evt.service ipmiutil_asy.service ipmiutil_wdt.service
+%else
+ if [ -x /bin/systemctl ]; then
+ echo "IINITDIR=%{init_dir}" >>%{_datadir}/%{name}/ipmiutil.env
+ cp -f ${scr_dir}/ipmiutil_evt.service %{unit_dir}
+ cp -f ${scr_dir}/ipmiutil_asy.service %{unit_dir}
+ cp -f ${scr_dir}/ipmiutil_wdt.service %{unit_dir}
+ cp -f ${scr_dir}/ipmi_port.service %{unit_dir}
+ # systemctl enable ipmi_port.service >/dev/null 2>&1 || :
+ else
+ cp -f ${scr_dir}/ipmiutil_wdt %{init_dir}
+ cp -f ${scr_dir}/ipmiutil_asy %{init_dir}
+ cp -f ${scr_dir}/ipmiutil_evt %{init_dir}
+ cp -f ${scr_dir}/ipmi_port %{init_dir}
+ cp -f ${scr_dir}/ipmi_info %{init_dir}
+ fi
+%endif
+
+ # Run some ipmiutil command to see if any IPMI interface works.
+ %{_bindir}/ipmiutil sel -v >/dev/null 2>&1 || :
+ IPMIret=$?
+ # If IPMIret==0, the IPMI cmd was successful, and IPMI is enabled locally.
+ if [ $IPMIret -eq 0 ]; then
+ # If IPMI is enabled, automate managing the IPMI SEL
+ if [ -d %{_sysconfdir}/cron.daily ]; then
+ cp -f %{_datadir}/%{name}/checksel %{_sysconfdir}/cron.daily
+ fi
+ # IPMI_IS_ENABLED, so enable services, but only if Red Hat
+ if [ -f /etc/redhat-release ]; then
+ if [ -x /bin/systemctl ]; then
+ touch ${scr_dir}/ipmi_port.service
+ elif [ -x /sbin/chkconfig ]; then
+ /sbin/chkconfig --add ipmi_port
+ /sbin/chkconfig --add ipmiutil_wdt
+ /sbin/chkconfig --add ipmiutil_evt
+ /sbin/chkconfig --add ipmi_info
+ fi
+ fi
+
+ # Capture a snapshot of IPMI sensor data once now for later reuse.
+ sensorout=$vardir/sensor_out.txt
+ if [ ! -f $sensorout ]; then
+ %{_bindir}/ipmiutil sensor -q >$sensorout || :
+ if [ $? -ne 0 ]; then
+ # remove file if error, try again in ipmi_port on reboot.
+ rm -f $sensorout
+ fi
+ fi
+ fi
+else
+ # postinstall, doing rpm update
+ %{_bindir}/ipmiutil sel -v >/dev/null 2>&1 || :
+ if [ $? -eq 0 ]; then
+ if [ -d %{_sysconfdir}/cron.daily ]; then
+ cp -f %{_datadir}/%{name}/checksel %{_sysconfdir}/cron.daily
+ fi
+ fi
+fi
+%if 0%{?fedora} >= 18
+%systemd_post ipmiutil_evt.service
+%systemd_post ipmiutil_asy.service
+%systemd_post ipmiutil_wdt.service
+%systemd_post ipmi_port.service
+%endif
+
+%preun
+# before uninstall, $1 = 1 if rpm -U, $1 = 0 if rpm -e
+if [ "$1" = "0" ]
+then
+%if 0%{?req_systemd}
+%service_del_preun ipmi_port.service ipmiutil_evt.service ipmiutil_asy.service ipmiutil_wdt.service
+%else
+ if [ -x /bin/systemctl ]; then
+ if [ -f %{unit_dir}/ipmiutil_evt.service ]; then
+%if 0%{?fedora} >= 18
+%systemd_preun ipmiutil_evt.service
+%systemd_preun ipmiutil_asy.service
+%systemd_preun ipmiutil_wdt.service
+%systemd_preun ipmi_port.service
+%else
+ systemctl disable ipmi_port.service >/dev/null 2>&1 || :
+ systemctl disable ipmiutil_evt.service >/dev/null 2>&1 || :
+ systemctl disable ipmiutil_asy.service >/dev/null 2>&1 || :
+ systemctl disable ipmiutil_wdt.service >/dev/null 2>&1 || :
+ systemctl stop ipmiutil_evt.service >/dev/null 2>&1 || :
+ systemctl stop ipmiutil_asy.service >/dev/null 2>&1 || :
+ systemctl stop ipmiutil_wdt.service >/dev/null 2>&1 || :
+ systemctl stop ipmi_port.service >/dev/null 2>&1 || :
+%endif
+ fi
+ else
+ if [ -x /sbin/service ]; then
+ /sbin/service ipmi_port stop >/dev/null 2>&1 || :
+ /sbin/service ipmiutil_wdt stop >/dev/null 2>&1 || :
+ /sbin/service ipmiutil_asy stop >/dev/null 2>&1 || :
+ /sbin/service ipmiutil_evt stop >/dev/null 2>&1 || :
+ fi
+ if [ -x /sbin/chkconfig ]; then
+ /sbin/chkconfig --del ipmi_port >/dev/null 2>&1 || :
+ /sbin/chkconfig --del ipmiutil_wdt >/dev/null 2>&1 || :
+ /sbin/chkconfig --del ipmiutil_asy >/dev/null 2>&1 || :
+ /sbin/chkconfig --del ipmiutil_evt >/dev/null 2>&1 || :
+ fi
+ fi
+%endif
+ if [ -f %{_sysconfdir}/cron.daily/checksel ]; then
+ rm -f %{_sysconfdir}/cron.daily/checksel
+ fi
+fi
+
+%postun
+%if 0%{?req_systemd}
+%service_del_postun ipmi_port.service ipmiutil_evt.service ipmiutil_asy.service ipmiutil_wdt.service
+%else
+if [ -x /bin/systemctl ]; then
+%if 0%{?fedora} >= 18
+%systemd_postun_with_restart ipmi_port.service
+%else
+ systemctl daemon-reload || :
+ if [ $1 -ge 1 ] ; then
+ # Package upgrade, not uninstall
+ systemctl try-restart ipmi_port.service || :
+ fi
+%endif
+ if [ -f %{unit_dir}/ipmiutil_evt.service ]; then
+ rm -f %{unit_dir}/ipmiutil_evt.service 2>/dev/null || :
+ rm -f %{unit_dir}/ipmiutil_asy.service 2>/dev/null || :
+ rm -f %{unit_dir}/ipmiutil_wdt.service 2>/dev/null || :
+ rm -f %{unit_dir}/ipmi_port.service 2>/dev/null || :
+ fi
+else
+ if [ -f %{init_dir}/ipmiutil_evt.service ]; then
+ rm -f %{init_dir}/ipmiutil_wdt 2>/dev/null || :
+ rm -f %{init_dir}/ipmiutil_asy 2>/dev/null || :
+ rm -f %{init_dir}/ipmiutil_evt 2>/dev/null || :
+ rm -f %{init_dir}/ipmi_port 2>/dev/null || :
+ fi
+fi
+%endif
+
+%changelog
+* Tue Aug 21 2012 Andrew Cress <arcress at users.sourceforge.net> 2.8.5-2
+ Added F18 systemd macros for RH bug #850163
+* Fri May 04 2012 Andrew Cress <arcress at users.sourceforge.net> 2.8.4-1
+ Fixups for devel rpm (RH bug #818910)
+* Tue Apr 24 2012 Andrew Cress <arcress at users.sourceforge.net> 2.8.3-1
+ Use service_* macros if req_systemd is set
+* Thu Mar 08 2012 Andrew Cress <arcress at users.sourceforge.net> 2.8.2-1
+ reworked systemd logic/macros, moved ipmiutil from sbindir to bindir
+* Mon Dec 12 2011 Andrew Cress <arcress at users.sourceforge.net> 2.8.0-1
+ added devel package files
+* Fri Nov 11 2011 Andrew Cress <arcress at users.sourceforge.net> 2.7.9-3
+ fix RH bug #752319 to not copy checksel to cron.daily if IPMI not enabled
+* Tue Sep 13 2011 Andrew Cress <arcress at users.sourceforge.net> 2.7.8-1
+ added systemd scripts, added idelloem.8
+* Mon Jun 06 2011 Andrew Cress <arcress at users.sourceforge.net> 2.7.7-1
+ add gcc,gcc-c++ to BuildRequires to detect broken build systems
+* Mon May 09 2011 Andrew Cress <arcress at users.sourceforge.net> 2.7.6-1
+ updated ipmiutil
+* Fri Nov 12 2010 Andrew Cress <arcress at users.sourceforge.net> 2.7.3-1
+ updated package description
+* Fri Oct 15 2010 Andrew Cress <arcress at users.sourceforge.net> 2.7.1-1
+ skip chkconfig --add if not Red Hat
+* Mon Sep 27 2010 Andrew Cress <arcress at users.sourceforge.net> 2.7.0-1
+ added fwum, hpm, sunoem, ekanalyzer man pages
+* Mon Jul 19 2010 Andrew Cress <arcress at users.sourceforge.net> 2.6.8-1
+ cleaned up two more rpmlint issues
+* Mon Jul 12 2010 Andrew Cress <arcress at users.sourceforge.net> 2.6.7-1
+ cleaned up some rpmlint issues, include ipmiutil_evt in chkconfig's
+* Thu Apr 29 2010 Andrew Cress <arcress at users.sourceforge.net> 2.6.4-1
+ cleaned up some style issues
+* Fri Mar 5 2010 Andrew Cress <arcress at users.sourceforge.net> 2.6.1-1
+ cleaned up some style issues
+* Tue Feb 16 2010 Andrew Cress <arcress at users.sourceforge.net> 2.6.0-1
+ cleaned up some script clutter, changed naming scheme for sub-commands
+* Tue Jan 26 2010 Andrew Cress <arcress at users.sourceforge.net> 2.5.3-1
+ cleaned up some rpmlint issues, removed bmclanaol.mib
+* Mon Nov 9 2009 Andrew Cress <arcress at users.sourceforge.net> 2.5.1-1
+ do not gzip man files, clean up scripts, move distro specifics to configure
+* Tue Jun 23 2009 Andrew Cress <arcress at users.sourceforge.net> 2.4.0-1
+ moved all progs to sbin, install init/cron scripts via files not post
+* Wed Dec 10 2008 Andrew Cress <arcress at users.sourceforge.net> 2.3.2-1
+ changes for Fedora with ipmiutil-2.3.2
+* Fri Jun 08 2007 Andrew Cress <arcress at users.sourceforge.net>
+ rpmlint tweaks for ipmiutil-1.9.8
+* Mon May 21 2007 Andrew Cress <arcress at users.sourceforge.net>
+ added isroot flag for chroot cases
+* Mon May 18 2007 Andrew Cress <arcress at users.sourceforge.net>
+ added ipmi_port init handling
+* Mon Jul 10 2006 Andrew Cress <arcress at users.sourceforge.net>
+ changed to libfreeipmi.so.2, include and run ipmi_if.sh
+* Tue Aug 02 2005 Andrew Cress <arcress at users.sourceforge.net>
+ changed not to run pefconfig if already configured
+* Wed Feb 03 2005 Andrew Cress <arcress at users.sourceforge.net>
+ changed /usr/man to /usr/share/man,
+ fixed postun to recognize rpm -U via arg 1
+* Mon Nov 1 2004 Andrew Cress <arcress at users.sourceforge.net>
+ added freeipmi install files and logic
+* Tue Aug 23 2004 Andrew Cress <arcress at users.sourceforge.net>
+- added MIB links to /usr/share/snmp/mibs
+* Tue Aug 10 2004 Andrew Cress <arcress at users.sourceforge.net>
+- added icmd utility to the rpm
+* Thu Aug 05 2004 Andrew Cress <arcress at users.sourceforge.net>
+- added special logic for SuSE snmpd.conf
+* Fri Apr 02 2004 Andrew Cress <arcress at users.sourceforge.net>
+- added checksel cron job
+* Tue Jan 28 2003 Andrew Cress <arcress at users.sourceforge.net>
+- added sensor & fruconfig for ipmiutil 1.2.8
+* Tue Aug 2 2002 Andrew Cress <arcress at users.sourceforge.net>
+- fixed bug 793 (dont need Require:ipmidrvr) for ipmiutil 1.2.2
+* Tue Jul 2 2002 Andrew Cress <arcress at users.sourceforge.net>
+- fixed bug 555 in showsel for ipmiutil 1.2.1
+* Fri May 10 2002 Andrew Cress <arcress at users.sourceforge.net>
+- fixed bug 504 in pefconfig for ipmiutil 1.1.5
+* Thu Apr 11 2002 Andrew Cress <arcress at users.sourceforge.net>
+- updated pathnames for ipmiutil 1.1.4, some cleanup
+* Mon Mar 18 2002 Andrew Cress <arcress at users.sourceforge.net>
+- updated for 1.1.3-2, added checking for grub vs. lilo to .spec
+* Tue Mar 12 2002 Andrew Cress <arcress at users.sourceforge.net>
+- updated for 1.1.3, added source rpm, changed license, etc.
+* Thu Jan 31 2002 Andrew Cress <arcress at users.sourceforge.net>
+- updated for 1.1.0-2, changed selpef to pefconfig
+* Thu Jan 25 2002 Andrew Cress <arcress at users.sourceforge.net>
+- updated for 1.1.0, changed to ipmidrvr rather than isc dependency
+* Thu Jan 16 2002 Andrew Cress <arcress at users.sourceforge.net>
+- updated for 1.1.0, added hwreset utility
+* Thu Dec 14 2001 Andrew Cress <arcress at users.sourceforge.net>
+- updated for 1.0.0, man page updates
+* Thu Nov 19 2001 Andrew Cress <arcress at users.sourceforge.net>
+- updated for 0.9.0, uses new OSS bmc_panic, so don't install module.
+* Thu Nov 13 2001 Andrew Cress <arcress at users.sourceforge.net>
+- updated for 0.8.5, add "Requires: isc" (#32), hide selpef output (#38)
+* Thu Nov 8 2001 Andrew Cress <arcress at users.sourceforge.net>
+- updated for 0.8.4, eliminate "file exists" messages by fixing removal
+* Thu Oct 25 2001 Andrew Cress <arcress at users.sourceforge.net>
+- updated for 0.8.2, run selpef (objdump:applypatch gives bogus warning)
+* Thu Oct 25 2001 Andrew Cress <arcress at users.sourceforge.net>
+- updated for 0.8.2, run selpef (objdump:applypatch gives bogus warning)
+* Wed Oct 24 2001 Andrew Cress <arcress at users.sourceforge.net>
+- created ipmiutil package 0.8.1 without kbuild
+* Tue Oct 23 2001 Andrew Cress <arcress at users.sourceforge.net>
+- created ipmiutil package 0.8.0
diff --git a/doc/ireset.8 b/doc/ireset.8
new file mode 100644
index 0000000..a018000
--- /dev/null
+++ b/doc/ireset.8
@@ -0,0 +1,118 @@
+.TH IRESET 8 "Version 1.5: 01 Jul 2011"
+.SH NAME
+ipmiutil_reset \- perform a hardware reset on the system
+.SH SYNOPSIS
+.B "ipmiutil reset [-bcdDefhijmnoprsuwxy -N node -U user -P/-R pswd -EFJTVY]"
+
+.SH DESCRIPTION
+.I ipmiutil reset
+is a program that uses IPMI commands to
+perform a hardware reset of the chassis, or boot to a specific
+device.
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+
+.SH OPTIONS
+Command line options are described below.
+.IP "-c"
+Power Cycle the system chassis
+.IP "-d"
+Power Down the system chassis
+.IP "-n"
+Send NMI to the system
+.IP "-u"
+Power Up the system chassis
+.IP "-r"
+Hard Reset the system chassis
+.IP "-D"
+Do a soft shutdown of the OS, and then power down.
+Note that remote soft shutdown (\-D \-N) for Intel S5000 baseboard requires
+ipmiutil getevt \-a running on the target server.
+.IP "-o"
+Do a soft shutdown of the OS, and then reset.
+Note that remote soft shutdown (\-o \-N) for Intel S5000 baseboard requires
+ipmiutil getevt \-a running on the target server.
+.IP "-k"
+Do a cold reset to restart the BMC firmware.
+.IP "-m 002000s"
+Perform these function for a specific MC (e.g. bus 00, sa 20, lun 00).
+The trailing character, if present, indicates SMI addressing if 's',
+or IPMB addressing if 'i' or not present.
+.IP "-b"
+Do a hard reset and reboot to the BIOS Setup menu, for this reboot only.
+.IP "-e"
+Do a hard reset to EFI, if IPMI EFI boot is enabled, for this reboot only.
+.IP "-f"
+Do a hard reset to Floppy/Removable, for this reboot only.
+.IP "-h"
+Do a hard reset to a Hard Disk, for this reboot only.
+.IP "-i"
+Set the boot Initiator mailbox string, usually for PXE use.
+The string must be less than 78 characters.
+.IP "-j"
+Set the IANA number used for the boot Initiator mailbox string.
+.IP "-p"
+Do a hard reset and network boot to PXE server, for this reboot only.
+.IP "-s"
+Do a hard reset and reboot to the Service/Diagnostic Partition, for this
+reboot only. Reboots to the default if no service partition is configured.
+.IP "-v"
+Do a hard reset to DVD/CDROM Media, for this reboot only.
+.IP "-w"
+Wait for BMC ready after a reset before exiting the utility.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-y"
+Yes, try to persist any boot options used [\-befhprsv]. This requires the IPMI
+firmware to ask the BIOS to change boot order settings, so it may not
+be supported by all BMC firmware vendors.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) isel(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/isel.8 b/doc/isel.8
new file mode 100644
index 0000000..a765e32
--- /dev/null
+++ b/doc/isel.8
@@ -0,0 +1,137 @@
+.TH ISEL 8 "Version 1.4: 17 Feb 2010"
+.SH NAME
+ipmiutil_sel \- show firmware System Event Log records
+.SH SYNOPSIS
+.B "ipmiutil sel [-abcflswvx -N node -P/-R pswd -U user -EFJTVY]"
+
+.SH DESCRIPTION
+.I ipmiutil sel
+is a program that uses IPMI commands to
+to read and display the System Event Log (SEL) which
+is stored by the BMC firmware. IPMI commands are issued
+to read each record, and, if specified, incrementally write
+records that have not previously been read into the
+Linux syslog (/var/log/messages).
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+
+.SH OPTIONS
+Command line options are described below.
+
+.IP "-a string"
+Add a SEL record with a string of up to 13 characters. Longer strings will
+be truncated. Note that this should be used sparingly, but would be useful
+for changes made to the hardware or firmware environment, like "Fan replaced"
+or "flash FW2.1".
+
+.IP "-b bin_file"
+Interpret a file containing raw binary/hex SEL data dumped in binary form,
+such as that produced by "ipmitool sel writeraw bin_file".
+Each set of 16 bytes in the file will be interpreted as an IPMI event.
+
+.IP "-c"
+Show output in a canonical format, with a default delimiter of '|'.
+(same as \-n).
+
+.IP "-d"
+Deletes/Clears the SEL of all records.
+If the SEL becomes full (free space = 0), it no longer accepts new records,
+so the SEL should be cleared periodically (use checksel cron script).
+
+.IP "-e"
+Show Extended sensor descriptions for events if run locally.
+This option will attempt to get the full sensor description from
+/var/lib/ipmiutil/sensor_out.txt, and also use its SDR to decode any raw
+threshold values in the event, if present.
+
+.IP "-f sel_file"
+Interpret a file containing raw ascii text SEL data captured with
+ipmiutil sel \-r, or some other similar utility.
+Each line in the file should be in this
+form, with no leading spaces:
+.br
+04 00 02 76 a9 4a 47 20 00 04 10 09 6f 42 0f ff
+.br
+Lines not in this format will be ignored.
+
+.IP "-l N"
+Show last N SEL records, in reverse order (newest first).
+For some BMC implementations, this may not show all N records specified.
+.IP "-n"
+Show output in a nominal/canonical format, with a default delimiter of '|'.
+(same as \-c).
+.IP "-r"
+Show the 16 raw hex bytes for each SEL entry. The default is to display
+interpreted entries, and include relevant hex event bytes.
+.IP "-p"
+By default, all SEL records are displayed. This option
+causes only the Panic events with sensor_type = 0x20 (OS Critical Stop)
+to be displayed.
+.IP "-s N"
+Show only SEL events with severity N or greater. Severity 0=INF, 1=MIN,
+2=MAJ, 3=CRT. The default is to show all SEL events.
+.IP "-u"
+Show the SEL time as UTC and also get the SEL Time UTC offset if that
+command is supported. The default is to convert the SEL Time to local time.
+.IP "-v"
+Only show the version information. This shows: the ipmiutil sel utility
+version, the BMC version, the IPMI version, the SEL version, and the amount
+of free space in the SEL.
+.IP "-w"
+This option writes SEL records to the Linux syslog (/var/log/messages)
+or Windows Application Log. It only writes SEL records that have
+timestamps newer than the last record written to syslog.
+It saves the last timestamp in an index file named
+/usr/share/ipmiutil/sel.idx (.\\sel.idx in Windows).
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isensor(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any
+bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/iseltime.8 b/doc/iseltime.8
new file mode 100644
index 0000000..eb9a705
--- /dev/null
+++ b/doc/iseltime.8
@@ -0,0 +1,79 @@
+.TH ISELTIME 8 "Version 1.0: 01 Apr 2013"
+.SH NAME
+iseltime \- synchronize BMC SEL time with OS system time
+.SH SYNOPSIS
+.B "seltime [-sx -NUPRETVF]"
+
+.SH DESCRIPTION
+.I seltime
+is a program that uses IPMI commands to
+set the BMC SEL time from the OS system time.
+The OS system time should be in sync with the BIOS Real-Time-Clock.
+The OS system time may also be kept from drifting via an NTP server.
+Normally the BIOS will set the BMC time from the RTC during boot, but
+running this command may be necessary periodically if the system
+does not reboot for many weeks, for instance.
+Note that this command should not be run too frequently to avoid
+BMC timing issues. Once per day should be sufficient.
+
+Run with no options, this command reads the BMC SEL time without
+setting anything.
+
+This utility can use either the /dev/ipmi0 openipmi driver,
+the /dev/imb Intel driver, the /dev/ipmikcs valinux driver,
+a driverless interface, or IPMI LAN.
+
+.SH OPTIONS
+.IP "-s"
+Sets the SEL time (no more than once a day).
+.IP "-x"
+Causes eXtra debug messages to be displayed.
+
+.IP "-N nodename"
+Nodename of the remote target system. If a nodename is specified,
+IPMI LAN interface is used. Otherwise the local system management
+interface is used.
+.IP "-P/-R password"
+Remote password for the nodename given. The default is a null password.
+.IP "-U username"
+Remote username for the nodename given. The default is a null username.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 14): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are -E or -P.
+
+
+.SH "SEE ALSO"
+ipmiutil(8) isel(8) ievents(8) icmd(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2013 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/isensor.8 b/doc/isensor.8
new file mode 100644
index 0000000..dcfdd1a
--- /dev/null
+++ b/doc/isensor.8
@@ -0,0 +1,213 @@
+.TH ISENSOR 8 "Version 1.6: 09 Nov 2011"
+.SH NAME
+ipmiutil_sensor \- show Sensor Data Records
+.SH SYNOPSIS
+.B "ipmiutil sensor [-abcdefgmpqrstuvwx -i id -n snum -h tval -l tval -NUPREFJTVY]"
+
+.SH DESCRIPTION
+.I ipmiutil sensor
+is a program that uses IPMI commands to
+show and decode Sensor Data Records and current
+sensor readings for all sensors in the system.
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+
+Note that this utility by default only displays Sensor Data Records
+reported by from the Baseboard Management Controller.
+To show sensors for other controllers, see options \-b and \-m below.
+
+.SH OPTIONS
+Command line options are described below.
+.IP "-a snum"
+ReArms the sensor number for events
+.IP "-b"
+Shows SDRs for Bladed (PICMG or ATCA) systems by traversing the child MCs
+(same as \-e).
+.IP "-c"
+Show sensor list in a simpler/Canonical format without uninterpreted binary
+values. Only the user-friendly interpreted sensor information is shown.
+(same as \-s).
+.IP "-d <file>"
+Dump the SDRs to a specified binary file.
+.IP "-e"
+Show Every SDR in a bladed system by traversing the child MCs (same as \-b).
+.IP "-f <file>"
+Restore the SDRs from the specified binary File.
+This is normally only done with the initial factory provisioning.
+.IP "-g sens_type"
+Shows only those SDRs matching the given sensor type group.
+The sens_type string can be "fan", "temp", "voltage", or any string or
+substring matching those in the IPMI 2.0 Table 42-3 for Sensor Types.
+Multiple types can be listed, separated by a comma (,) but no spaces.
+.IP "-h tval"
+Highest threshold value to set for the specified sensor.
+This tval can be in decimal, or of the form 0x1a,
+to match the raw reading value shown by sensor following the " = ".
+The value passed is set as the non-critical threshold value, with the
+more critical ones set by the utility as incrementally lower.
+This simplifies the interface and ensures that the threshold values
+do not get out of order.
+This requires specifying the sensor number via \-n.
+.IP "-i ID"
+Show or set only the sensor Index corresponding to ID, where ID is the
+hex ID of the SDR as shown in the sensor output under "_ID_".
+The ID argument can be one hex number (e.g. 0x0e or 0e), or a range of
+hex numbers (e.g. 0e-1a or 1a,2a or 0x0e-0x2a).
+This is useful to repeatedly view just a few sensor readings for changes,
+or to set just one sensor quickly without reading all of the SDRs.
+.IP "-l tval"
+Lowest threshold value to set for the specified sensor.
+This tval can be in decimal, or of the form 0x1a,
+to match the raw reading value shown by sensor following the " = ".
+The value passed is set as the non-critical threshold value, with the
+more critical ones set by the utility as incrementally higher.
+This simplifies the interface and ensures that the threshold values
+do not get out of order.
+This requires specifying the sensor number via \-n.
+.IP "-m 002000s"
+Show SDRs for a specific MC (e.g. bus 00, sa 20, lun 00).
+This could be used for PICMG or ATCA blade systems.
+The trailing character, if present, indicates SMI addressing if 's',
+or IPMB addressing if 'i' or not present.
+.IP "-n snum"
+Number of the sensor to set.
+This num can be in decimal, or of the form 0x1a,
+to match the value shown by sensor following the "snum" tag.
+This is required if setting hi/lo thresholds via \-h/\-l.
+.IP "-o"
+Output the memory DIMM information from SMBIOS, including size. Not available if using IPMI LAN via \-N. Sample output:
+.br
+Memory Device (0,0): DIMM_A1 : size=2048MB
+.br
+Memory Device (0,1): DIMM_A2 : not present
+.IP "-p"
+Persist the threshold being set (as specified via \-l or \-h). This writes
+a "sensor \-i" script line to the file /usr/share/ipmiutil/thresholds.sh,
+which can then be executed at each reboot by starting the /etc/init.d/ipmi_port service for the desired runlevels. For Windows, the filename is thresholds.cmd.
+.IP "-q"
+Show any thresholds for each sensor in short format with ':' delimiters, useful as an example for setting thresholds with '\-u'.
+.IP "-r"
+Show Raw SDR bytes also.
+.IP "-s"
+Show sensor list in a simpler/canonical format without uninterpreted binary
+values. Only the user-friendly interpreted sensor information is shown.
+(same as \-c).
+.IP "-t"
+Show any Thresholds for each sensor also, in text format.
+.IP "-u"
+Set unique threshold values. The values are specified in a string of threshold values. It can be in raw hex characters or in float values. All 6 possible
+thresholds must be specified, but only the ones that are valid for this sensor
+will be applied. These values are validated for ordering. For example:
+ \-u 6:5:4:60:65:69 (float) or
+ \-u 0x0605043c4145 (raw hex)
+ would mean 0x06=noncrit_lo, 0x05=crit_lo, 0x04=nonrec_lo, 0x3c=noncrit_hi,
+0x41=crit_hi, 0x45=nonrec_hi.
+.IP "-v"
+Show Verbose output, including volatile thresholds, SDR thresholds,
+max/min, hysteresis, and BMC_TAM decoding.
+.IP "-w"
+Wrap the threshold data onto the same line as the sensor.
+This may be convenient for scripting.
+.IP "-x"
+Causes eXtra debug messages to be displayed.
+.IP "-L n"
+Loop n times. This is useful along with \-i. Default is one loop.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH "EXAMPLES"
+ipmiutil sensor sample output is below.
+.br
+ipmiutil ver 2.21
+.br
+sensor: version 2.21
+.br
+-- BMC version 0.17, IPMI version 2.0
+.br
+_ID_ SDR_Type_xx ET Own Typ S_Num Sens_Description Hex & Interp Reading
+.br
+000b SDR Full 01 01 20 a 01 snum 30 Baseboard Temp = 2e OK 46.00 degrees C
+.br
+000e SDR Full 01 01 20 m 04 snum 50 Fan 1A = 6f OK 7659.00 RPM
+.br
+0042 SDR Comp 02 6f 20 a 21 snum e0 DIMM 1A = 00 c0 04 00 Present
+.br
+004e SDR FRU 11 1b dev: 20 03 80 00 0a 01 Pwr Supply 1 FRU
+.br
+0050 SDR IPMB 12 1b dev: 20 00 bf 07 01 Basbrd Mgmt Ctlr
+.br
+0051 SDR OEM c0 09 Intel: 02 02 00 01 70 71
+.br
+0065 SDR OEM c0 11 Intel: SDR Package 17
+.br
+[...]
+.PP
+Output Columns:
+.br
+_ID_: This is an SDR ID or index number, in hex. This may vary from chassis to chassis.
+.br
+SDR_Type_xx: This shows the SDR Type and its hex representation. Some SDR types have a custom display. The OEM SDRs only show the OEM vendor by IANA number and then usually the data is listed in hex.
+.br
+ET: For Full or Comp SDRs, this shows the Event Type.
+For other SDRs, this shows the size of the SDR entry in hex (Sz).
+.br
+Own: This is the hex slave address of the SDR Owner, usually 20 if BMC.
+.br
+a/m: This indicates whether this sensor is either automatically or manually rearmed, respectively.
+.br
+Typ: This is the Sensor Type as defined in Table 42-3 of the IPMI 2.0 spec.
+(01 = Temperature, 02 = Voltage, 03 = Current, 04 = Fan, etc.)
+.br
+S_Num: This is the sensor number in hex. This remains consistent across baseboards of the same type. The output can be parsed with the "snum" delimiter to extract this value.
+.br
+Sens_Description: This is the text description of this SDR, which is stored within the SDR on the BMC.
+.br
+Hex & Interp Reading: This is the raw hex value returned by GetSensorReading, and its interpreted meaning.
+
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) iserial(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/iserial.8 b/doc/iserial.8
new file mode 100644
index 0000000..d7bbfcb
--- /dev/null
+++ b/doc/iserial.8
@@ -0,0 +1,251 @@
+.TH ISERIAL 8 "Version 2.2: 17 Feb 2010"
+.SH NAME
+ipmiutil_serial \- configure a system for Serial/EMP management functions, such as Terminal Mode, and optionally share the port with the Serial Console.
+.SH SYNOPSIS
+.B "ipmiutil serial [-bcdeflq#rsvxB -m0 -m1 -n ser_chan -u user -p passwd -NUPREFJTVY]"
+
+.SH DESCRIPTION
+.I ipmiutil serial
+is a program that uses an IPMI driver to send IPMI commands which
+configure a system to enable EMP/serial Terminal Mode management
+functions within the firmware, so that an administrator can use
+command-line character commands via the serial port to
+power cycle the system and perform other functions,
+even if the system is not running an OS.
+This level of access needs to be protected by a username/password
+login, which can be specified with this utility.
+This utility can use either the /dev/ipmi0 driver from OpenIPMI,
+the /dev/imb driver from Intel, the /dev/ipmikcs driver from valinux,
+direct user-space IOs, or the IPMI LAN interface if \-N.
+
+.SH OPTIONS
+Command line options are described below.
+.IP "-b"
+Set up and enable the Serial Port EMP parameters for Basic Mode management functions. This does not set a username or password.
+.IP "-c"
+Configure and enable the Serial Port EMP parameters for Terminal Mode management functions, shared with BIOS Console Redirection.
+Setting a new username and password for serial access via \-u and \-p is
+recommended for security.
+.IP "-d"
+Disable the serial port access for IPMI commands. The serial port is then
+only available for BIOS console and OS functions.
+A side-effect of this option is that it sets the default user (1) back to
+admin access.
+.IP "-e"
+Enable EMP Terminal Mode without shared BIOS console. The serial port is
+then only available for EMP Terminal Mode functions.
+.IP "-f"
+Specifies the Flow Control for the Serial EMP. 0 means no flow control, and
+1 means RTS/CTS flow control (default). This must match the BIOS Serial
+Console setting.
+.IP "-l"
+Show LAN Parameters. This option reads and displays the LAN Parameter
+configuration also.
+.IP "-m0"
+Switch the Serial Port MUX to Baseboard/BIOS Console operation.
+Set no other configuration parameters.
+.IP "-m1"
+Switch the Serial Port MUX to Terminal Mode management.
+Set no other configuration parameters.
+.IP "-n ser_chan"
+Sets the IPMI channel number to use for the EMP serial channel
+(often 4). Note that the IPMI channels for LAN, Serial, etc.
+are numbered differently on each platform type.
+The default is to detect the first available IPMI serial channel.
+.IP "-#"
+Same as \-q below.
+.IP "-q"
+Specify an alternate user number for the EMP Username from the \-u option.
+This is normally user number 2, 3, or 4, where 3 is the default.
+The maximum number of users is 15.
+.IP "-r"
+Read Only. This option just reads the Serial Parameter configuration
+without writing any values.
+.IP "-s"
+Set up and enable the Serial Port EMP parameters for Shared operation
+between Basic Mode management functions and Baseboard (BIOS) Remote Console.
+This option switches the Serial Port MUX to Baseboard Console operation.
+.IP "-t"
+Configure and enable the Serial Port EMP parameters for Terminal Mode management functions, shared with BIOS Console Redirection. Same as \-c, but easier to remember.
+.IP "-u username"
+This specifies a username for the EMP Terminal Mode login. It can
+be any string, up to 15 characters. If \-u is not used, the default user 1
+(null) will be assumed. The username, if specified, will be set for user 3,
+unless option \-q is specified.
+.IP "-p password"
+This specifies a password for the EMP Terminal Mode login. It can
+be any string, up to 15 characters. A null password is used if
+none is specified. This password applies to user 3 if \-u is used, to
+user 1 otherwise.
+.IP "-v priv"
+Set a specific access priVilege for this user, where priv can be:
+1=Callback, 2=User, 3=Operator, 4=Admin, 5=OEM, 15=NoAccess
+The default if not specified or specified in error, is to use 4=Admin.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-B"
+Set the Baud rate of the serial port to one of the following:
+9600, 19,2K, 38.4K, 57.6K, or 115.2K. The default is 19.2K bps.
+
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH EXAMPLES
+
+.IP "ipmiutil serial -t (or -c)"
+Enables Terminal Mode management functions, shared with BIOS Serial Console redirection. The user can switch between serial console operations and IPMI Terminal Mode commands by typing ESC ')' and ESC 'Q'.
+
+.IP "ipmiutil serial -s"
+Enables Basic Mode management functions shared with BIOS Serial Console redirection. The user can switch between serial console operations and IPMI Basic Mode management programs on the same serial port.
+
+.IP "ipmiutil serial -d"
+Disables the serial port management functions. This would be used if only the BIOS Serial Console were used and no BMC serial management functions.
+
+.P
+How to login to a Terminal Mode console:
+.br
+ESC ( (switch to Terminal mode)
+.br
+[SYS PWD \-N ] (login for default user, null psw)
+.br
+[SYS PWD \-U ROOT \-N PASSWORD] (syntax example for user 3)
+.br
+[SYS 000157 ACTIVATE] (activate advanced commands)
+.br
+[SYS HEALTH QUERY]
+.br
+[SYS HELP]
+.br
+[SYS PWD] (logoff)
+.br
+ESC Q (switch to BIOS console)
+.br
+See IPMI 1.5 Spec, Appendix E, and Intel TIGPR2U TPS for more information.
+
+.SH DEPENDENCIES
+The ipmiutil serial utility is intended to configure the EMP serial port on the
+server for shared access between BMC/IPMI functions and BIOS Console
+Redirection. Some platforms only support only Basic Mode for BMC/IPMI
+functions. Basic Mode requires a remote client application to utilize it
+(Windows ISC Console/DPC, or a special modified Linux telnet).
+There are some platforms which implement Terminal Mode via IPMI v1.5
+Appendix E to make remote management with character commands available
+on the serial port without a special remote client application.
+
+For example, Intel TSRLT2 systems would use "ipmiutil serial \-s" for Basic Mode
+shared functions, but Intel TIGPR2U systems could use "ipmiutil serial \-c" to
+configure Terminal Mode functions. On your system, run "ipmiutil serial \-r" to
+check whether Serial Param(29): "Terminal Mode Config" is supported. If
+not, configure Basic Mode via "ipmiutil serial \-s".
+
+
+.SH "PLATFORM SERIAL PORT CONFIGURATION EXAMPLES"
+
+First, enter BIOS Setup for Serial Console Redirection parameters:
+(these vary by platform)
+.br
+ Console Redirection = Serial Port B
+.br
+ ACPI Redirection = Disabled
+.br
+ Baud Rate = 115.2K
+.br
+ Flow Control = CTS/RTS
+.br
+ Terminal Type = VT100
+.br
+ Legacy Redirection = Enabled
+.br
+Note that the Baud Rate can vary, but it must match in all
+locations where it is used (BIOS, IPMI, and Linux).
+.br
+For some non-Intel platforms, the serial console would be
+COM1 instead of COM2, but should be enabled in BIOS.
+.br
+From Linux, run "ipmiutil serial \-c" for Terminal Mode shared configuration.
+.br
+Or, on older Intel TSRLT2 platforms:
+From Linux, run "ipmiutil serial \-s" for Basic Mode Shared configuration.
+
+.SH "LINUX CONFIGURATION FOR SERIAL CONSOLE"
+
+If using lilo, in /etc/lilo.conf, add
+.br
+ append="console=ttyS1,19200n8 console=tty0"
+.br
+(and comment out the "message=" line because it includes graphics)
+.br
+Note that the append line can be placed in the global section
+and removed from each kernel section if there are no other differences.
+
+.PP
+Or, if using grub, edit /boot/grub/grub.conf as follows:
+.br
+ #Omit the splashimage or gfxmenu
+.br
+ # splashimage=(hd0,0)/grub/splash.xpm.gz
+.br
+ #The serial and terminal lines are not usually needed
+.br
+ # serial \-\-unit=1 \-\-speed=19200 \-\-word=8 \-\-parity=no \-\-stop=1
+.br
+ # terminal \-\-timeout=10 serial console
+.br
+ #Add the console=ttyS* parameter to the kernel line
+.br
+ kernel (hd0,0) /vmlinuz root=/dev/sda2 console=ttyS1,19200n8
+
+.PP
+Add this line to /etc/initab, if ttyS1 is not already there:
+.br
+ co:2345:respawn:/sbin/agetty ttyS1 19200 vt100
+.PP
+Add this line to /etc/securetty, if ttyS1 is not already there:
+.br
+ ttyS1
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) isol(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/ismcoem.8 b/doc/ismcoem.8
new file mode 100644
index 0000000..7ecdbf9
--- /dev/null
+++ b/doc/ismcoem.8
@@ -0,0 +1,104 @@
+.TH ISMCOEM 8 "Version 1.0: 05 Apr 2013"
+.SH NAME
+ipmiutil_smcoem \- OEM commands for SuperMicro servers
+.SH SYNOPSIS
+.B "ipmiutil smcoem [-mx -NPRUEFJTVY] commands"
+
+.SH DESCRIPTION
+.I ipmiutil smcoem
+is a function that uses SuperMicro OEM IPMI commands to
+perform platform-specific functions.
+
+.SH OPTIONS
+
+.IP "-m 002000"
+Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00).
+This could be used for PICMG or ATCA blade systems.
+The trailing character, if present, indicates SMI addressing if 's',
+or IPMB addressing if 'i' or not present.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH COMMANDS
+.TP
+\fIintrusion\fP
+.RS
+
+This command resets any chassis intrusion condition that may have
+occurred.
+.RE
+
+.TP
+\fIbmcstatus\fP \fB[enable|disable]\fR
+.RS
+This command gets or sets the BMC service status.
+Alone, without arguments, it gets the BMC status as either enabled or
+disabled. With an argument of either enable or disable, it will
+also set the BMC status as specified.
+.RE
+
+.TP
+\fIfirmware\fP
+.RS
+
+This command gets the extra firmware version information, if available.
+
+.RE
+
+.TP
+\fIlanport\fP \fB[dedicated|lan1|failover]\fR
+.RS
+This command gets or sets the IPMI LAN interface port.
+If set to dedicated, only the dedicated IPMI NIC can be configured for
+IPMI LAN. If set to lan1, only the first onboard NIC (LAN1) can be configured
+for IPMI LAN. If set to failover, both the dedicated and onboard LAN1 port
+would be configured for IPMI LAN, with the same IP address.
+.RE
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2013 Andy Cress
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/isol.8 b/doc/isol.8
new file mode 100644
index 0000000..7048f64
--- /dev/null
+++ b/doc/isol.8
@@ -0,0 +1,133 @@
+.TH ISOL 8 "Version 1.1: 17 Feb 2010"
+.SH NAME
+ipmiutil_sol \- an IPMI Serial-Over-LAN Console application
+
+.SH SYNOPSIS
+.B "ipmiutil sol [-acdeilorsvwxz -NUPREFJTVY]
+
+.SH DESCRIPTION
+This utility starts an IPMI Serial-Over-LAN console session.
+A Serial-over-LAN console allows the client to see and modify
+functions before the OS boots, such as BIOS setup, grub, etc.
+This utility uses either the IPMI LAN 1.5 or 2.0 SOL interface.
+The 1.5 SOL interface is specific to Intel BMCs, while any IPMI 2.0
+BMC should support 2.0 SOL.
+The target system/node must first have these parameters configured
+before SOL sessions can be started:
+.br
+- [BIOS] serial console redirection parameters,
+.br
+- [IPMI] lan and SOL parameters (see ipmiutil lan or ilan), and
+.br
+- [OS] For Linux, edit grub.conf, inittab, and securetty parameters.
+.br
+Be sure that the baud rate matches in all of the above places.
+See the ipmiutil UserGuide section 4.8 for details.
+
+.SH OPTIONS
+.IP "-a"
+Activate the SOL Console session, and enter console mode.
+Use the escape sequence ('~.') to exit the session.
+.IP "-c '^'"
+Set the escape Character to '^', or another ANSI character. This changes the
+default two-character escape sequence ('~.') to the specified single escape
+character, which will end the SOL session.
+.IP "-d"
+Deactivate the SOL Console session. Use this if the previous session
+was aborted abnormally and starting a new session gives an error.
+.IP "-e"
+Turn Encryption off in negotiation when activating a session. By default,
+encryption is on for Serial-Over-LAN console sessions.
+.IP "-l"
+Use Legacy BIOS mapping for Enter key (CR+LF) instead of just LF.
+This is needed for BIOS Setup menus and DOS, but causes an extra LF to
+occur in Linux. So, only use this option if doing BIOS or DOS changes.
+This should be seldom be needed since now the default is to automatically
+detect these menus with colored backgrounds and change the mapping.
+.IP "-i input_file"
+Use this file as an input script. The input_file will be read after the
+session is established. This can be used to automate certain tasks. The
+input_file is read one line at a time. If the input_file does not
+have an escape character (~) to end the session, then the input is
+returned to the keyboard when the file ends.
+.IP "-o output_file"
+Use a Trace log. The output_file is created and all SOL screen output is
+written to the file, including VT100 escape sequences. If the output_file
+exists, the output is appended to it. This can be used to log what the
+user has done in an SOL session.
+.IP "-r"
+Use Raw terminal I/O instead of custom VT100 to ANSI translation (in Windows).
+Use this option if the server is configured in BIOS and BMC for ANSI and
+the utility is being invoked from Windows.
+.IP "-s NNN"
+For a slow link with high latency, this adds a delay of NNN microseconds
+between sending and receiving SOL packets. The default is 100 microseconds.
+.IP "-w"
+(Windows only)
+Do not use the Windows Console buffer, but use Windows stdio instead.
+This does not handle cursor positioning correctly in some cases, however.
+.IP "-v log_file"
+Causes debug messages to be displayed to the specified debug log_file.
+The default log_file is isoldbg.log in the current directory.
+.IP "-x"
+Causes debug messages to be displayed to the debug log file.
+.IP "-z"
+Causes more verbose debug messages to be displayed to the debug log file.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any supported driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH "EXAMPLES"
+ipmiutil sol \-a \-N nodename \-U username \-P password
+.br
+Starts an SOL console session to the nodename. Detect the lan protocol.
+.PP
+ipmiutil sol \-a \-N nodename \-U username \-P password \-Flan2
+.br
+Starts an SOL console session to the nodename. Force lan protocol to 2.0.
+.PP
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/isunoem.8 b/doc/isunoem.8
new file mode 100644
index 0000000..366ed7d
--- /dev/null
+++ b/doc/isunoem.8
@@ -0,0 +1,135 @@
+.TH ISUNOEM 8 "Version 1.0: 09 Sep 2010"
+.SH NAME
+ipmiutil_sunoem \- OEM commands for Sun servers
+.SH SYNOPSIS
+.B "ipmiutil sunoem [-mx -NPRUEFJTVY] commands"
+
+.SH DESCRIPTION
+.I ipmiutil sunoem commands
+is a program that uses Sun OEM IPMI commands to
+perform platform-specific functions.
+
+.SH OPTIONS
+
+.IP "-m 002000"
+Show FRU for a specific MC (e.g. bus 00, sa 20, lun 00).
+This could be used for PICMG or ATCA blade systems.
+The trailing character, if present, indicates SMI addressing if 's',
+or IPMB addressing if 'i' or not present.
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+.SH COMMANDS
+.TP
+\fIled\fP
+.RS
+
+These commands provide a way to get and set the status of LEDs
+on a Sun Microsystems server. Use 'sdr list generic' to get a
+list of devices that are controllable LEDs. The \fIledtype\fP
+parameter is optional and not necessary to provide on the command
+line unless it is required by hardware.
+.TP
+\fIget\fP \fBsensorid\fR [\fBledtype\fR]
+
+Get status of a particular LED described by a Generic Device Locator
+record in the SDR. A sensorid of \fIall\fP will get the status
+of all available LEDS.
+.TP
+\fIset\fP \fBsensorid\fR \fBledmode\fR [\fBledtype\fR]
+
+Set status of a particular LED described by a Generic Device Locator
+record in the SDR. A sensorid of \fIall\fP will set the status
+of all available LEDS to the specified \fIledmode\fP and \fIledtype\fP.
+.TP
+LED Mode is required for set operations:
+.br
+\fIOFF\fP Off
+.br
+\fION\fP Steady On
+.br
+\fISTANDBY\fP 100ms on 2900ms off blink rate
+.br
+\fISLOW\fP 1HZ blink rate
+.br
+\fIFAST\fP 4HZ blink rate
+.TP
+LED Type is optional:
+.br
+\fIOK2RM\fP Ok to Remove
+.br
+\fISERVICE\fP Service Required
+.br
+\fIACT\fP Activity
+.br
+\fILOCATE\fP Locate
+
+.RE
+.TP
+\fIfan\fP \fIspeed\fP 0-100
+
+Set system fan speed (PWM duty cycle).
+.RS
+.TP
+\fIsshkey\fP
+.RS
+.TP
+\fIset\fP \fBuserid\fR \fBkeyfile\fR
+
+This command will allow you to specify an SSH key to use for a particular
+user on the Service Processor. This key will be used for CLI logins to
+the SP and not for IPMI sessions. View available users and their userids
+with the 'user list' command.
+.TP
+\fIdel\fP \fBuserid\fR
+
+This command will delete the SSH key for a specified userid.
+.RE
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/itsol.8 b/doc/itsol.8
new file mode 100644
index 0000000..a7a3d0a
--- /dev/null
+++ b/doc/itsol.8
@@ -0,0 +1,66 @@
+.TH ITSOL 8 "Version 1.0: 03 Feb 2012"
+.SH NAME
+ipmiutil_tsol \- Tyan IPMIv1.5 Serial-Over-LAN Console application
+
+.SH SYNOPSIS
+.B "ipmiutil tsol [recvip] [port=NUM] [ro|rw] [rows=NUM] [cols=NUM] [altterm]
+
+.SH DESCRIPTION
+This command allows Serial-over-LAN sessions to be established
+with Tyan IPMIv1.5 SMDC such as the M3289 or M3290. The default
+command run with no arguments will establish default SOL session
+back to local IP address. Optional arguments may be supplied in
+any order.
+
+.SH OPTIONS
+
+.IP "<recv ipaddr>"
+Send receiver IP address to SMDC which it will use to
+send serial traffic to. By default this detects the
+local IP address and establishes two-way session. Format
+of ipaddr is XX.XX.XX.XX
+
+.IP "port"
+Configure UDP port to receive serial traffic on.
+By default this is 6230.
+
+.IP "ro|rw"
+Confiure SOL session as read-only or read-write.
+Sessions are read-write by default.
+
+.IP "rows"
+Set terminal rows [default: rows=24]
+
+.IP "cols"
+Set terminal columns [default: cols=80]
+
+.IP "altterm"
+Alternate terminal setup [default is off]
+
+
+.SH "EXAMPLES"
+ipmiutil tsol 192.168.1.1
+.br
+Starts a Tyan SOL console session to the IP address.
+.PP
+
+.SH "SEE ALSO"
+ipmiutil(8) ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifru(8) igetevent(8) ihealth(8) ilan(8) ireset(8) isel(8) isensor(8) iserial(8) iwdt(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2012 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/iwdt.8 b/doc/iwdt.8
new file mode 100644
index 0000000..2fa4642
--- /dev/null
+++ b/doc/iwdt.8
@@ -0,0 +1,113 @@
+.TH IWDT 8 "Version 1.3: 26 Apr 2010"
+.SH NAME
+ipmiutil_wdt\- display and set WatchDog Timer parameters
+.SH SYNOPSIS
+.B "ipmiutil wdt [-acdelrtx -N node -P/-R pswd -U user -EFJTVY]"
+
+.SH DESCRIPTION
+.I ipmiutil wdt
+is a program that uses IPMI commands to
+display and set WatchDog Timer parameters.
+
+This utility can use either any available IPMI driver, or direct
+user-space IOs, or the IPMI LAN interface if \-N.
+
+This utility is an example of how to access the IPMI watchdog parameters
+directly, which allows changing the timer configuration.
+
+There is an init script provided with ipmiutil to automate the task of
+managing the watchdog timer in user-space.
+.br
+# chkconfig \-\-add ipmiutil_wdt (skip this if no chkconfig)
+.br
+# /etc/init.d/ipmiutil_wdt start
+.br
+This sets the watchdog timer to reset the system if the wdt is not
+restarted within 90 seconds. It creates an /etc/cron.d/wdt file to
+restart wdt every 60 seconds.
+See also ipmiutil UserGuide section 4.4 for more information.
+
+.SH OPTIONS
+Command line options are described below.
+.IP "-a N"
+Set watchdog event Action to N. Values:
+0 = No action, 1 = Hard Reset(default), 2 = Power down, 3 = Power cycle.
+.IP "-c"
+Show watchdog output in a canonical format, with a default delimiter of '|'.
+.IP "-d"
+Disables the watchdog timer.
+.IP "-e"
+Enables the watchdog timer. The timer is not actually started, however,
+until the timer is reset. The pre-timeout action is not enabled.
+.IP "-l"
+Set the watchdog dontLog bit to not log watchdog events in the SEL.
+.IP "-p N"
+Set watchdog Pretimeout event action to N. Values:
+0 = No action(default), 1 = SMI, 2 = NMI, 3 = Messaging Interrupt.
+If this is set to an action other than 0, the pretimeout will also
+be set to 90% of the timeout. However, if the timeout is less than
+20 seconds, the pretimeout will not be enabled.
+.IP "-q S"
+Set watchdog pretimeout value to S seconds, rather than 90% of the timeout
+as in \-p. The pretimeout value must be >= 5 and at least 5 seconds less
+than the timeout value.
+.IP "-r"
+Resets the watchdog timer. This should be done every N seconds if the
+timer is running to prevent the watchdog action (usually a system reset)
+from occurring.
+.IP "-tN"
+Set the watchdog Timeout to N seconds. The default is 120 seconds (2 minutes).
+.IP "-x"
+Causes extra debug messages to be displayed.
+.IP "-N nodename"
+Nodename or IP address of the remote target system. If a nodename is
+specified, IPMI LAN interface is used. Otherwise the local system
+management interface is used.
+.IP "-P/-R rmt_pswd"
+Remote password for the nodename given. The default is a null password.
+.IP "-U rmt_user"
+Remote username for the nodename given. The default is a null username.
+.IP "-E"
+Use the remote password from Environment variable IPMI_PASSWORD.
+.IP "-F drv_t"
+Force the driver type to one of the followng:
+imb, va, open, gnu, landesk, lan, lan2, lan2i, kcs, smb.
+Note that lan2i means lan2 with intelplus.
+The default is to detect any available driver type and use it.
+.IP "-J"
+Use the specified LanPlus cipher suite (0 thru 17): 0=none/none/none,
+1=sha1/none/none, 2=sha1/sha1/none, 3=sha1/sha1/cbc128, 4=sha1/sha1/xrc4_128,
+5=sha1/sha1/xrc4_40, 6=md5/none/none, ... 14=md5/md5/xrc4_40.
+Default is 3.
+.IP "-T"
+Use a specified IPMI LAN Authentication Type: 0=None, 1=MD2, 2=MD5, 4=Straight Password, 5=OEM.
+.IP "-V"
+Use a specified IPMI LAN privilege level. 1=Callback level, 2=User level, 3=Operator level, 4=Administrator level (default), 5=OEM level.
+.IP "-Y"
+Yes, do prompt the user for the IPMI LAN remote password.
+Alternatives for the password are \-E or \-P.
+
+
+.SH "SEE ALSO"
+ialarms(8) iconfig(8) icmd(8) idiscover(8) ievents(8) ifirewall(8)
+ifru(8) ifruset(8) ifwum(8) igetevent(8) ihealth(8) ihpm(8)
+ilan(8) ipicmg(8) ireset(8) isel(8) isensor(8) iserial(8) isol(8) isunoem(8)
+iwdt(8) ipmiutil(8) ipmi_port(8)
+
+.SH WARNINGS
+See http://ipmiutil.sourceforge.net/ for the latest version of ipmiutil and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2009 Kontron America, Inc.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/doc/rh.patch b/doc/rh.patch
new file mode 100644
index 0000000..e0e691b
--- /dev/null
+++ b/doc/rh.patch
@@ -0,0 +1,111 @@
+--- ipmiutil.spec.orig 2012-06-12 12:05:50.000000000 -0400
++++ ipmiutil.spec 2012-06-12 12:07:47.000000000 -0400
+@@ -7,7 +7,7 @@
+ Release: 1%{?dist}
+ Summary: Easy-to-use IPMI server management utilities
+ License: BSD
+-Group: System/Management
++Group: System Environment/Base
+ Source: http://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.gz
+ URL: http://ipmiutil.sourceforge.net
+ BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
+@@ -15,18 +15,9 @@
+ %if 0%{?fedora} >= 15
+ Requires: systemd-units
+ %endif
+-%if 0%{?suse_version} >= 1210
+-%define req_systemd 1
+-%endif
+-%if 0%{?req_systemd}
+-BuildRequires: openssl-devel gcc gcc-c++ libtool systemd
+-%define systemd_fls %{_unitdir}
+-# Requires: %{?systemd_requires}
+-%else
+ BuildRequires: openssl-devel gcc gcc-c++ libtool
+-%define systemd_fls %{_datadir}/%{name}
+-%endif
+-%define init_dir %{_initrddir}
++%global systemd_fls %{_datadir}/%{name}
++%global init_dir %{_initrddir}
+
+ %description
+ The ipmiutil package provides easy-to-use utilities to view the SEL,
+@@ -53,12 +44,8 @@
+ %setup -q
+
+ %build
+-%if 0%{?req_systemd}
+-%configure --enable-systemd
+-%else
+ %configure
+-%endif
+-make
++make %{?_smp_mflags}
+
+ %install
+ rm -rf %{buildroot}
+@@ -146,11 +133,6 @@
+ %{_libdir}/libipmiutil.a
+
+
+-%pre
+-%if 0%{?req_systemd}
+-%service_add_pre ipmi_port.service ipmiutil_evt.service ipmiutil_asy.service ipmiutil_wdt.service
+-%endif
+-
+ %post
+ # POST_INSTALL, $1 = 1 if rpm -i, $1 = 2 if rpm -U
+
+@@ -160,9 +142,6 @@
+ vardir=%{_var}/lib/%{name}
+ scr_dir=%{_datadir}/%{name}
+
+-%if 0%{?req_systemd}
+-%service_add_post ipmi_port.service ipmiutil_evt.service ipmiutil_asy.service ipmiutil_wdt.service
+-%else
+ if [ -x /bin/systemctl ]; then
+ systemd_dir=%{_unitdir}
+ echo "IINITDIR=%{init_dir}" >>%{_datadir}/%{name}/ipmiutil.env
+@@ -177,7 +156,6 @@
+ cp -f ${scr_dir}/ipmiutil_evt %{init_dir}
+ cp -f ${scr_dir}/ipmi_port %{init_dir}
+ fi
+-%endif
+
+ # Run some ipmiutil command to see if any IPMI interface works.
+ %{_bindir}/ipmiutil sel -v >/dev/null 2>&1
+@@ -213,9 +191,6 @@
+ # before uninstall, $1 = 1 if rpm -U, $1 = 0 if rpm -e
+ if [ "$1" = "0" ]
+ then
+-%if 0%{?req_systemd}
+-%service_del_preun ipmi_port.service ipmiutil_evt.service ipmiutil_asy.service ipmiutil_wdt.service
+-%else
+ if [ -x /bin/systemctl ]; then
+ systemd_dir=%{_unitdir}
+ if [ -f ${systemd_dir}/ipmiutil_evt.service ]; then
+@@ -250,16 +225,12 @@
+ rm -f %{init_dir}/ipmiutil_evt 2>/dev/null
+ rm -f %{init_dir}/ipmi_port 2>/dev/null
+ fi
+-%endif
+ if [ -f %{_sysconfdir}/cron.daily/checksel ]; then
+ rm -f %{_sysconfdir}/cron.daily/checksel
+ fi
+ fi
+
+ %postun
+-%if 0%{?req_systemd}
+-%service_del_postun ipmi_port.service ipmiutil_evt.service ipmiutil_asy.service ipmiutil_wdt.service
+-%else
+ if [ -x /bin/systemctl ]; then
+ systemctl daemon-reload || :
+ if [ $1 -ge 1 ] ; then
+@@ -267,7 +238,6 @@
+ systemctl try-restart ipmi_port.service || :
+ fi
+ fi
+-%endif
+
+ %changelog
+ * Fri May 04 2012 Andrew Cress <arcress at users.sourceforge.net> 2.8.4-1
diff --git a/doc/rh_spec.patch b/doc/rh_spec.patch
new file mode 100644
index 0000000..e0e691b
--- /dev/null
+++ b/doc/rh_spec.patch
@@ -0,0 +1,111 @@
+--- ipmiutil.spec.orig 2012-06-12 12:05:50.000000000 -0400
++++ ipmiutil.spec 2012-06-12 12:07:47.000000000 -0400
+@@ -7,7 +7,7 @@
+ Release: 1%{?dist}
+ Summary: Easy-to-use IPMI server management utilities
+ License: BSD
+-Group: System/Management
++Group: System Environment/Base
+ Source: http://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.gz
+ URL: http://ipmiutil.sourceforge.net
+ BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
+@@ -15,18 +15,9 @@
+ %if 0%{?fedora} >= 15
+ Requires: systemd-units
+ %endif
+-%if 0%{?suse_version} >= 1210
+-%define req_systemd 1
+-%endif
+-%if 0%{?req_systemd}
+-BuildRequires: openssl-devel gcc gcc-c++ libtool systemd
+-%define systemd_fls %{_unitdir}
+-# Requires: %{?systemd_requires}
+-%else
+ BuildRequires: openssl-devel gcc gcc-c++ libtool
+-%define systemd_fls %{_datadir}/%{name}
+-%endif
+-%define init_dir %{_initrddir}
++%global systemd_fls %{_datadir}/%{name}
++%global init_dir %{_initrddir}
+
+ %description
+ The ipmiutil package provides easy-to-use utilities to view the SEL,
+@@ -53,12 +44,8 @@
+ %setup -q
+
+ %build
+-%if 0%{?req_systemd}
+-%configure --enable-systemd
+-%else
+ %configure
+-%endif
+-make
++make %{?_smp_mflags}
+
+ %install
+ rm -rf %{buildroot}
+@@ -146,11 +133,6 @@
+ %{_libdir}/libipmiutil.a
+
+
+-%pre
+-%if 0%{?req_systemd}
+-%service_add_pre ipmi_port.service ipmiutil_evt.service ipmiutil_asy.service ipmiutil_wdt.service
+-%endif
+-
+ %post
+ # POST_INSTALL, $1 = 1 if rpm -i, $1 = 2 if rpm -U
+
+@@ -160,9 +142,6 @@
+ vardir=%{_var}/lib/%{name}
+ scr_dir=%{_datadir}/%{name}
+
+-%if 0%{?req_systemd}
+-%service_add_post ipmi_port.service ipmiutil_evt.service ipmiutil_asy.service ipmiutil_wdt.service
+-%else
+ if [ -x /bin/systemctl ]; then
+ systemd_dir=%{_unitdir}
+ echo "IINITDIR=%{init_dir}" >>%{_datadir}/%{name}/ipmiutil.env
+@@ -177,7 +156,6 @@
+ cp -f ${scr_dir}/ipmiutil_evt %{init_dir}
+ cp -f ${scr_dir}/ipmi_port %{init_dir}
+ fi
+-%endif
+
+ # Run some ipmiutil command to see if any IPMI interface works.
+ %{_bindir}/ipmiutil sel -v >/dev/null 2>&1
+@@ -213,9 +191,6 @@
+ # before uninstall, $1 = 1 if rpm -U, $1 = 0 if rpm -e
+ if [ "$1" = "0" ]
+ then
+-%if 0%{?req_systemd}
+-%service_del_preun ipmi_port.service ipmiutil_evt.service ipmiutil_asy.service ipmiutil_wdt.service
+-%else
+ if [ -x /bin/systemctl ]; then
+ systemd_dir=%{_unitdir}
+ if [ -f ${systemd_dir}/ipmiutil_evt.service ]; then
+@@ -250,16 +225,12 @@
+ rm -f %{init_dir}/ipmiutil_evt 2>/dev/null
+ rm -f %{init_dir}/ipmi_port 2>/dev/null
+ fi
+-%endif
+ if [ -f %{_sysconfdir}/cron.daily/checksel ]; then
+ rm -f %{_sysconfdir}/cron.daily/checksel
+ fi
+ fi
+
+ %postun
+-%if 0%{?req_systemd}
+-%service_del_postun ipmi_port.service ipmiutil_evt.service ipmiutil_asy.service ipmiutil_wdt.service
+-%else
+ if [ -x /bin/systemctl ]; then
+ systemctl daemon-reload || :
+ if [ $1 -ge 1 ] ; then
+@@ -267,7 +238,6 @@
+ systemctl try-restart ipmi_port.service || :
+ fi
+ fi
+-%endif
+
+ %changelog
+ * Fri May 04 2012 Andrew Cress <arcress at users.sourceforge.net> 2.8.4-1
diff --git a/doc/winsockerr.txt b/doc/winsockerr.txt
new file mode 100644
index 0000000..5c81edb
--- /dev/null
+++ b/doc/winsockerr.txt
@@ -0,0 +1,301 @@
+(from http://msdn2.microsoft.com/en-us/library/ms740668.aspx)
+
+Windows Sockets Error Codes
+The following list describes the possible error codes returned by the WSAGetLastError function. Errors are listed in alphabetical order by error macro. Some error codes defined in Winsock2.h are not returned from any functionthese are not included in this list.
+
+Return code/value Description
+WSA_INVALID_HANDLE 6
+Specified event object handle is invalid.
+An application attempts to use an event object, but the specified handle is not valid. Note that this error is returned by the operating system, so the error number may change in future releases of Windows.
+WSA_NOT_ENOUGH_MEMORY 8
+Insufficient memory available.
+An application used a Windows Sockets function that directly maps to a Windows function. The Windows function is indicating a lack of required memory resources. Note that this error is returned by the operating system, so the error number may change in future releases of Windows.
+WSA_INVALID_PARAMETER 87
+One or more parameters are invalid.
+An application used a Windows Sockets function which directly maps to a Windows function. The Windows function is indicating a problem with one or more parameters. Note that this error is returned by the operating system, so the error number may change in future releases of Windows.
+WSA_OPERATION_ABORTED 995
+Overlapped operation aborted.
+An overlapped operation was canceled due to the closure of the socket, or the execution of the SIO_FLUSH command in WSAIoctl. Note that this error is returned by the operating system, so the error number may change in future releases of Windows.
+WSA_IO_INCOMPLETE 996
+Overlapped I/O event object not in signaled state.
+The application has tried to determine the status of an overlapped operation which is not yet completed. Applications that use WSAGetOverlappedResult (with the fWait flag set to FALSE) in a polling mode to determine when an overlapped operation has completed, get this error code until the operation is complete. Note that this error is returned by the operating system, so the error number may change in future releases of Windows.
+WSA_IO_PENDING 997
+Overlapped operations will complete later.
+The application has initiated an overlapped operation that cannot be completed immediately. A completion indication will be given later when the operation has been completed. Note that this error is returned by the operating system, so the error number may change in future releases of Windows.
+WSAEINTR 10004
+Interrupted function call.
+A blocking operation was interrupted by a call to WSACancelBlockingCall.
+WSAEBADF 10009
+File handle is not valid.
+The file handle supplied is not valid.
+WSAEACCES 10013
+Permission denied.
+An attempt was made to access a socket in a way forbidden by its access permissions. An example is using a broadcast address for sendto without broadcast permission being set using setsockopt(SO_BROADCAST).
+Another possible reason for the WSAEACCES error is that when the bind function is called (on Windows NT 4 SP4 or later), another application, service, or kernel mode driver is bound to the same address with exclusive access. Such exclusive access is a new feature of Windows NT 4 SP4 and later, and is implemented by using the SO_EXCLUSIVEADDRUSE option.
+
+WSAEFAULT 10014
+Bad address.
+The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error occurs if an application passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an argument, which is a sockaddr structure, is smaller than the sizeof(sockaddr).
+WSAEINVAL 10022
+Invalid argument.
+Some invalid argument was supplied (for example, specifying an invalid level to the setsockopt function). In some instances, it also refers to the current state of the socketfor instance, calling accept on a socket that is not listening.
+WSAEMFILE 10024
+Too many open files.
+Too many open sockets. Each implementation may have a maximum number of socket handles available, either globally, per process, or per thread.
+WSAEWOULDBLOCK 10035
+Resource temporarily unavailable.
+This error is returned from operations on nonblocking sockets that cannot be completed immediately, for example recv when no data is queued to be read from the socket. It is a nonfatal error, and the operation should be retried later. It is normal for WSAEWOULDBLOCK to be reported as the result from calling connect on a nonblocking SOCK_STREAM socket, since some time must elapse for the connection to be established.
+WSAEINPROGRESS 10036
+Operation now in progress.
+A blocking operation is currently executing. Windows Sockets only allows a single blocking operationper- task or threadto be outstanding, and if any other function call is made (whether or not it references that or any other socket) the function fails with the WSAEINPROGRESS error.
+WSAEALREADY 10037
+Operation already in progress.
+An operation was attempted on a nonblocking socket with an operation already in progressthat is, calling connect a second time on a nonblocking socket that is already connecting, or canceling an asynchronous request (WSAAsyncGetXbyY) that has already been canceled or completed.
+WSAENOTSOCK 10038
+Socket operation on nonsocket.
+An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket, or for select, a member of an fd_set was not valid.
+WSAEDESTADDRREQ 10039
+Destination address required.
+A required address was omitted from an operation on a socket. For example, this error is returned if sendto is called with the remote address of ADDR_ANY.
+WSAEMSGSIZE 10040
+Message too long.
+A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram was smaller than the datagram itself.
+WSAEPROTOTYPE 10041
+Protocol wrong type for socket.
+A protocol was specified in the socket function call that does not support the semantics of the socket type requested. For example, the ARPA Internet UDP protocol cannot be specified with a socket type of SOCK_STREAM.
+WSAENOPROTOOPT 10042
+Bad protocol option.
+An unknown, invalid or unsupported option or level was specified in a getsockopt or setsockopt call.
+WSAEPROTONOSUPPORT 10043
+Protocol not supported.
+The requested protocol has not been configured into the system, or no implementation for it exists. For example, a socket call requests a SOCK_DGRAM socket, but specifies a stream protocol.
+WSAESOCKTNOSUPPORT 10044
+Socket type not supported.
+The support for the specified socket type does not exist in this address family. For example, the optional type SOCK_RAW might be selected in a socket call, and the implementation does not support SOCK_RAW sockets at all.
+WSAEOPNOTSUPP 10045
+Operation not supported.
+The attempted operation is not supported for the type of object referenced. Usually this occurs when a socket descriptor to a socket that cannot support this operation is trying to accept a connection on a datagram socket.
+WSAEPFNOSUPPORT 10046
+Protocol family not supported.
+The protocol family has not been configured into the system or no implementation for it exists. This message has a slightly different meaning from WSAEAFNOSUPPORT. However, it is interchangeable in most cases, and all Windows Sockets functions that return one of these messages also specify WSAEAFNOSUPPORT.
+WSAEAFNOSUPPORT 10047
+Address family not supported by protocol family.
+An address incompatible with the requested protocol was used. All sockets are created with an associated address family (that is, AF_INET for Internet Protocols) and a generic protocol type (that is, SOCK_STREAM). This error is returned if an incorrect protocol is explicitly requested in the socket call, or if an address of the wrong family is used for a socket, for example, in sendto.
+WSAEADDRINUSE 10048
+Address already in use.
+Typically, only one usage of each socket address (protocol/IP address/port) is permitted. This error occurs if an application attempts to bind a socket to an IP address/port that has already been used for an existing socket, or a socket that was not closed properly, or one that is still in the process of closing. For server applications that need to bind multiple sockets to the same port number, consider using setsockopt (SO_REUSEADDR). Client applications usually need not call bind at all connect chooses
+an unused port automatically. When bind is called with a wildcard address (involving ADDR_ANY), a WSAEADDRINUSE error could be delayed until the specific address is committed. This could happen with a call to another function later, including connect, listen, WSAConnect, or WSAJoinLeaf.
+WSAEADDRNOTAVAIL 10049
+Cannot assign requested address.
+The requested address is not valid in its context. This normally results from an attempt to bind to an address that is not valid for the local computer. This can also result from connect, sendto, WSAConnect, WSAJoinLeaf, or WSASendTo when the remote address or port is not valid for a remote computer (for example, address or port 0).
+WSAENETDOWN 10050
+Network is down.
+A socket operation encountered a dead network. This could indicate a serious failure of the network system (that is, the protocol stack that the Windows Sockets DLL runs over), the network interface, or the local network itself.
+WSAENETUNREACH 10051
+Network is unreachable.
+A socket operation was attempted to an unreachable network. This usually means the local software knows no route to reach the remote host.
+WSAENETRESET 10052
+Network dropped connection on reset.
+The connection has been broken due to keep-alive activity detecting a failure while the operation was in progress. It can also be returned by setsockopt if an attempt is made to set SO_KEEPALIVE on a connection that has already failed.
+WSAECONNABORTED 10053
+Software caused connection abort.
+An established connection was aborted by the software in your host computer, possibly due to a data transmission time-out or protocol error.
+WSAECONNRESET 10054
+Connection reset by peer.
+An existing connection was forcibly closed by the remote host. This normally results if the peer application on the remote host is suddenly stopped, the host is rebooted, the host or remote network interface is disabled, or the remote host uses a hard close (see setsockopt for more information on the SO_LINGER option on the remote socket). This error may also result if a connection was broken due to keep-alive activity detecting a failure while one or more operations are in progress. Operations that were i
+n progress fail with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.
+WSAENOBUFS 10055
+No buffer space available.
+An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
+WSAEISCONN 10056
+Socket is already connected.
+A connect request was made on an already-connected socket. Some implementations also return this error if sendto is called on a connected SOCK_DGRAM socket (for SOCK_STREAM sockets, the to parameter in sendto is ignored) although other implementations treat this as a legal occurrence.
+WSAENOTCONN 10057
+Socket is not connected.
+A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using sendto) no address was supplied. Any other type of operation might also return this errorfor example, setsockopt setting SO_KEEPALIVE if the connection has been reset.
+WSAESHUTDOWN 10058
+Cannot send after socket shutdown.
+A request to send or receive data was disallowed because the socket had already been shut down in that direction with a previous shutdown call. By calling shutdown a partial close of a socket is requested, which is a signal that sending or receiving, or both have been discontinued.
+WSAETOOMANYREFS 10059
+Too many references.
+Too many references to some kernel object.
+WSAETIMEDOUT 10060
+Connection timed out.
+A connection attempt failed because the connected party did not properly respond after a period of time, or the established connection failed because the connected host has failed to respond.
+WSAECONNREFUSED 10061
+Connection refused.
+No connection could be made because the target computer actively refused it. This usually results from trying to connect to a service that is inactive on the foreign hostthat is, one with no server application running.
+WSAELOOP 10062
+Cannot translate name.
+Cannot translate a name.
+WSAENAMETOOLONG 10063
+Name too long.
+A name component or a name was too long.
+WSAEHOSTDOWN 10064
+Host is down.
+A socket operation failed because the destination host is down. A socket operation encountered a dead host. Networking activity on the local host has not been initiated. These conditions are more likely to be indicated by the error WSAETIMEDOUT.
+WSAEHOSTUNREACH 10065
+No route to host.
+A socket operation was attempted to an unreachable host. See WSAENETUNREACH.
+WSAENOTEMPTY 10066
+Directory not empty.
+Cannot remove a directory that is not empty.
+WSAEPROCLIM 10067
+Too many processes.
+A Windows Sockets implementation may have a limit on the number of applications that can use it simultaneously.WSAStartup may fail with this error if the limit has been reached.
+WSAEUSERS 10068
+User quota exceeded.
+Ran out of user quota.
+WSAEDQUOT 10069
+Disk quota exceeded.
+Ran out of disk quota.
+WSAESTALE 10070
+Stale file handle reference.
+The file handle reference is no longer available.
+WSAEREMOTE 10071
+Item is remote.
+The item is not available locally.
+WSASYSNOTREADY 10091
+Network subsystem is unavailable.
+This error is returned by WSAStartup if the Windows Sockets implementation cannot function at this time because the underlying system it uses to provide network services is currently unavailable. Users should check:
+That the appropriate Windows Sockets DLL file is in the current path.
+That they are not trying to use more than one Windows Sockets implementation simultaneously. If there is more than one Winsock DLL on your system, be sure the first one in the path is appropriate for the network subsystem currently loaded.
+The Windows Sockets implementation documentation to be sure all necessary components are currently installed and configured correctly.
+WSAVERNOTSUPPORTED 10092
+Winsock.dll version out of range.
+The current Windows Sockets implementation does not support the Windows Sockets specification version requested by the application. Check that no old Windows Sockets DLL files are being accessed.
+WSANOTINITIALISED 10093
+Successful WSAStartup not yet performed.
+Either the application has not called WSAStartup or WSAStartup failed. The application may be accessing a socket that the current active task does not own (that is, trying to share a socket between tasks), or WSACleanup has been called too many times.
+WSAEDISCON 10101
+Graceful shutdown in progress.
+Returned by WSARecv and WSARecvFrom to indicate that the remote party has initiated a graceful shutdown sequence.
+WSAENOMORE 10102
+No more results.
+No more results can be returned by the WSALookupServiceNext function.
+WSAECANCELLED 10103
+Call has been canceled.
+A call to the WSALookupServiceEnd function was made while this call was still processing. The call has been canceled.
+WSAEINVALIDPROCTABLE 10104
+Procedure call table is invalid.
+The service provider procedure call table is invalid. A service provider returned a bogus procedure table to Ws2_32.dll. This is usually caused by one or more of the function pointers being NULL.
+WSAEINVALIDPROVIDER 10105
+Service provider is invalid.
+The requested service provider is invalid. This error is returned by the WSCGetProviderInfo and WSCGetProviderInfo32 functions if the protocol entry specified could not be found. This error is also returned if the service provider returned a version number other than 2.0.
+WSAEPROVIDERFAILEDINIT 10106
+Service provider failed to initialize.
+The requested service provider could not be loaded or initialized. This error is returned if either a service provider's DLL could not be loaded (LoadLibrary failed) or the provider's WSPStartup or NSPStartup function failed.
+WSASYSCALLFAILURE 10107
+System call failure.
+A system call that should never fail has failed. This is a generic error code, returned under various conditions.
+Returned when a system call that should never fail does fail. For example, if a call to WaitForMultipleEvents fails or one of the registry functions fails trying to manipulate the protocol/namespace catalogs.
+Returned when a provider does not return SUCCESS and does not provide an extended error code. Can indicate a service provider implementation error.
+WSASERVICE_NOT_FOUND 10108
+Service not found.
+No such service is known. The service cannot be found in the specified name space.
+WSATYPE_NOT_FOUND 10109
+Class type not found.
+The specified class was not found.
+WSA_E_NO_MORE 10110
+No more results.
+No more results can be returned by the WSALookupServiceNext function.
+WSA_E_CANCELLED 10111
+Call was canceled.
+A call to the WSALookupServiceEnd function was made while this call was still processing. The call has been canceled.
+WSAEREFUSED 10112
+Database query was refused.
+A database query failed because it was actively refused.
+WSAHOST_NOT_FOUND 11001
+Host not found.
+No such host is known. The name is not an official host name or alias, or it cannot be found in the database(s) being queried. This error may also be returned for protocol and service queries, and means that the specified name could not be found in the relevant database.
+WSATRY_AGAIN 11002
+Nonauthoritative host not found.
+This is usually a temporary error during host name resolution and means that the local server did not receive a response from an authoritative server. A retry at some time later may be successful.
+WSANO_RECOVERY 11003
+This is a nonrecoverable error.
+This indicates that some sort of nonrecoverable error occurred during a database lookup. This may be because the database files (for example, BSD-compatible HOSTS, SERVICES, or PROTOCOLS files) could not be found, or a DNS request was returned by the server with a severe error.
+WSANO_DATA 11004
+Valid name, no data record of requested type.
+The requested name is valid and was found in the database, but it does not have the correct associated data being resolved for. The usual example for this is a host name-to-address translation attempt (using gethostbyname or WSAAsyncGetHostByName) which uses the DNS (Domain Name Server). An MX record is returned but no A recordindicating the host itself exists, but is not directly reachable.
+WSA_QOS_RECEIVERS 11005
+QOS receivers.
+At least one QOS reserve has arrived.
+WSA_QOS_SENDERS 11006
+QOS senders.
+At least one QOS send path has arrived.
+WSA_QOS_NO_SENDERS 11007
+No QOS senders.
+There are no QOS senders.
+WSA_QOS_NO_RECEIVERS 11008
+QOS no receivers.
+There are no QOS receivers.
+WSA_QOS_REQUEST_CONFIRMED 11009
+QOS request confirmed.
+The QOS reserve request has been confirmed.
+WSA_QOS_ADMISSION_FAILURE 11010
+QOS admission error.
+A QOS error occurred due to lack of resources.
+WSA_QOS_POLICY_FAILURE 11011
+QOS policy failure.
+The QOS request was rejected because the policy system couldnt allocate the requested resource within the existing policy.
+WSA_QOS_BAD_STYLE 11012
+QOS bad style.
+An unknown or conflicting QOS style was encountered.
+WSA_QOS_BAD_OBJECT 11013
+QOS bad object.
+A problem was encountered with some part of the filterspec or the provider-specific buffer in general.
+WSA_QOS_TRAFFIC_CTRL_ERROR 11014
+QOS traffic control error.
+An error with the underlying traffic control (TC) API as the generic QOS request was converted for local enforcement by the TC API. This could be due to an out of memory error or to an internal QOS provider error.
+WSA_QOS_GENERIC_ERROR 11015
+QOS generic error.
+A general QOS error.
+WSA_QOS_ESERVICETYPE 11016
+QOS service type error.
+An invalid or unrecognized service type was found in the QOS flowspec.
+WSA_QOS_EFLOWSPEC 11017
+QOS flowspec error.
+An invalid or inconsistent flowspec was found in the QOS structure.
+WSA_QOS_EPROVSPECBUF 11018
+Invalid QOS provider buffer.
+An invalid QOS provider-specific buffer.
+WSA_QOS_EFILTERSTYLE 11019
+Invalid QOS filter style.
+An invalid QOS filter style was used.
+WSA_QOS_EFILTERTYPE 11020
+Invalid QOS filter type.
+An invalid QOS filter type was used.
+WSA_QOS_EFILTERCOUNT 11021
+Incorrect QOS filter count.
+An incorrect number of QOS FILTERSPECs were specified in the FLOWDESCRIPTOR.
+WSA_QOS_EOBJLENGTH 11022
+Invalid QOS object length.
+An object with an invalid ObjectLength field was specified in the QOS provider-specific buffer.
+WSA_QOS_EFLOWCOUNT 11023
+Incorrect QOS flow count.
+An incorrect number of flow descriptors was specified in the QOS structure.
+WSA_QOS_EUNKOWNPSOBJ 11024
+Unrecognized QOS object.
+An unrecognized object was found in the QOS provider-specific buffer.
+WSA_QOS_EPOLICYOBJ 11025
+Invalid QOS policy object.
+An invalid policy object was found in the QOS provider-specific buffer.
+WSA_QOS_EFLOWDESC 11026
+Invalid QOS flow descriptor.
+An invalid QOS flow descriptor was found in the flow descriptor list.
+WSA_QOS_EPSFLOWSPEC 11027
+Invalid QOS provider-specific flowspec.
+An invalid or inconsistent flowspec was found in the QOS provider-specific buffer.
+WSA_QOS_EPSFILTERSPEC 11028
+Invalid QOS provider-specific filterspec.
+An invalid FILTERSPEC was found in the QOS provider-specific buffer.
+WSA_QOS_ESDMODEOBJ 11029
+Invalid QOS shape discard mode object.
+An invalid shape discard mode object was found in the QOS provider-specific buffer.
+WSA_QOS_ESHAPERATEOBJ 11030
+Invalid QOS shaping rate object.
+An invalid shaping rate object was found in the QOS provider-specific buffer.
+WSA_QOS_RESERVED_PETYPE 11031
+Reserved policy QOS element type.
+A reserved policy element was found in the QOS provider-specific buffer.
+
diff --git a/hpiutil/COPYING b/hpiutil/COPYING
new file mode 100644
index 0000000..1a27065
--- /dev/null
+++ b/hpiutil/COPYING
@@ -0,0 +1,28 @@
+The BSD License
+
+Copyright (c) 2003, 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.
+
diff --git a/hpiutil/ChangeLog b/hpiutil/ChangeLog
new file mode 100644
index 0000000..755db47
--- /dev/null
+++ b/hpiutil/ChangeLog
@@ -0,0 +1,106 @@
+06/20/03 hpiutil 1.0.0 ARCress - initial release, includes:
+ hpisensor
+ hpisel
+ hpifru
+ hpireset
+ hpiwdt
+ hpialarmpanel
+ SpiLibd
+ libSpi*.so
+06/26/03 hpiutil 1.0.1 ARCress
+ SpiLibd code: disabled RestoreDefault functions,
+ fixed Entity path root truncation,
+ tweaked EventTranslation for event data
+ hpisel: changed event data logic
+ hpisensor: added -t for thresholds
+ hpireset: cut out functions not supported in HPI 1.0
+06/27/03 hpiutil 1.0.2 ARCress
+ hpiutil.spec: check for ipmidrvr rpm, since no /dev/imb until reboot
+ Build MV CGE 2.1 rpm (gcc 2)
+ README: change test suite contact, added Test Notes
+ env.hpi: increased log level to 5 for errors only
+ hpiinit.sh: increased log level to 5 for errors only
+07/08/03 hpiutil 1.0.3 ARCress
+ README: added list of APIs
+07/22/03 hpiutil 1.0.4 ARCress
+ Makefile: added changes for OpenHPI
+ INSTALL: created build/install instructions
+ env.openhpi: created
+ hpisel.c: added BUGGY section for OpenHPI Discover workaround
+ hpisensor.c: added BUGGY section for OpenHPI Discover workaround
+08/12/03 hpiutil 1.0.4-2 ARCress
+ built rh80open rpm with everything for OpenIPMI
+09/25/03 hpiutil 1.0.5 ARCress
+ don't include libraries in rpms
+11/12/03 hpiutil 1.0.6 ARCress
+ hpisel.c: check for CAPABLITY_SEL in RPT
+02/19/04 hpiutil 1.1.0 ARCress
+ hpifru.c: added IsBmcTag() to generalize tag parsing
+ hpiinit.sh: added LD_ASSUME_KERNEL to avoid RH EL 3 NPTL
+ hpiutil.spec: changed /etc/init.d name to just "hpi"
+ hpisensor.c: recognize common errors for Compact & mBMC sensors.
+ SpiLibd: rebuilt lib objects with Gold Intel HPI 1.0 libraries
+ README updated for new OSs, etc.
+02/23/04 hpiutil 1.1.1 ARCress
+ hpialarmpanel: added checking/setting disk LEDs
+ SpiLibd: fixed disk LEDs for mBMC
+ fixed IPMI timeout for mBMC
+03/16/04 hpiutil 1.1.2 ARCress
+ hpievent 0.8: added general search for any Fan sensor
+ hpisel 1.2: use better free space logic now
+ hpiwdt 1.0: use description strings for use and action values,
+ fixed another 0xcc error w pretimeout byte.
+ SpiLibd: recognize special Watchdog sensor for mBMC
+ recognize System Boot records in domain SEL
+ skip Hysteresis if mBMC (caused ThresholdsGet error)
+ special code to allow mBMC ThresholdsSet
+03/18/04 hpiutil 1.1.3 ARCress
+ SpiLibd: Check for bad SdrLock at init if mBMC
+ fix to mBMC ThresholdsSet
+ fix to not abort if SEL delete timestamp changes
+ hpievent 1.0: changed general search to a Temp sensor (has Low Major)
+03/26/04 hpiutil 1.1.4 ARCress
+ hpiutil.spec - changes for kill scripts
+ hpiinit.sh - changes for chkconfig
+ SpiLibd: Changed timeouts for GetEvent, etc.
+06/24/04 hpiutil 1.1.5 ARCress
+ SpiLibd: Fixed GetIpmiEvent for fast events, more than 1 per second.
+ test/hpieventloop.c Created for testing fast events, not in rpm
+ spi-lib.conf: Changed SpiLibHlpResponseTimeout from 9000 to 11000
+ for "hpifru -a" client timeout error.
+09/02/04 hpiutil 1.1.6 ARCress
+ SpiLibd: Changed saHpiInitialize to report version 0x010101 (A.01.01)
+ rather than 0x000101 (pre HPI 1.0)
+09/15/04 hpiutil 1.1.7 ARCress
+ SpiLibd: fixed uninitialized pointer in debug printf for GetEvent
+01/12/05 hpiutil 1.1.8 ARCress
+ SpiLibd: fixed spiCpsRptInfoGetRspCodec for 32bit UpdateCount
+ SaHpi.h-A: new file, include file for HPI A.01.01 spec
+ (SaHpi.h is the working copy)
+ SaHpi.h-B: new file, include file for HPI B.01.01 spec
+ hpialarmpanel.c: added HPI_A/HPI_B logic, misc changes
+ hpisel.c: added HPI_A/HPI_B logic
+ hpisensor.c: added HPI_A/HPI_B logic, misc changes
+ hpiwdt v1.1 - fixed RPT loop, added more decoding,
+ added flags for HPI_A/HPI_B.
+ hpireset v1.1 - added HPI_A/B flags
+ hpifru v1.3 - added HPI_A/B flags,
+ increased buffer sizes, check null ptr in fixstr
+ hpifrub.c new file, fully ported to HPI B
+ hpifrua.c new file, changed to skip read errors
+ hpievent.c - added HPI_A/B flags
+ Makefile - added a common HPI_A/B compile option
+
+03/16/05 hpiutil 1.1.9 ARCress
+ SpiLibd: various changes for new TIGI2U platform
+ hpifrub.c - added FieldSet for asset tag, Changed IsTagBmc usage
+ hpifrua.c - only write asset tag if IsTagBmc
+ hpisel.c - decode more of the record for IPMI sensor events
+
+04/07/05 hpiutil 1.1.10 ARCress
+ hpievent.c - set UpMajor if not Fan threshold
+ hpisel.c - add logic to show domain event log if HPI_B
+
+08/30/11 hpiutil 1.1.11 ARCress
+ hpiutil.spec - updated Version, syntax of header
+ hpiinit.sh - use /var/run if /var/lock/subsys is not present.
diff --git a/hpiutil/INSTALL b/hpiutil/INSTALL
new file mode 100644
index 0000000..ef5790f
--- /dev/null
+++ b/hpiutil/INSTALL
@@ -0,0 +1,27 @@
+hpiutil
+
+BUILD & INSTALL INSTRUCTIONS
+
+This package uses the Intel HPI library implementation (closed source),
+but there is also an OpenHPI library implementation that could also be
+linked with these utilities. There are comments in the Makefile to show
+how this can be done.
+
+How to make the utilities:
+1) If OpenHPI, edit the makefile to uncomment the 2 lines indicated.
+2) do ". env.hpi" or ". env.openhpi" to set the environment variables
+3) make clean
+4) make
+
+How to make the rpms:
+(Only valid for Intel HPI at this time.)
+mkrpm $OS
+ where OS = rh80 | as21 | mv21 | mv30 | mv30wv | el3 | mv31
+
+How to install the rpms:
+(Only valid for Intel HPI at this time.)
+rpm -i hpiutil-1.0.3-as21.i386.rpm
+ The hpi utilities will be in /usr/bin.
+ The SaHpi libraries will be in /usr/lib.
+ The *.conf files will be in /etc/hpi.
+
diff --git a/hpiutil/Makefile b/hpiutil/Makefile
new file mode 100644
index 0000000..e1faa35
--- /dev/null
+++ b/hpiutil/Makefile
@@ -0,0 +1,77 @@
+################################################################################
+#
+# Makefile for hpiutils
+#
+################################################################################
+
+# All items listed will be linked. By default, each has a dependency of the corresponding .o file.
+# Each .o file has a default dependency of the correspoonding .c file.
+TARGETS = hpialarmpanel hpisensor hpisel hpireset hpiwdt hpifru hpievent
+
+ifeq ($(DEBUG),y)
+DEBFLAGS = -O -g3 -DDEBUG
+else
+DEBFLAGS = -O2
+endif
+CFLAGS = $(DEBFLAGS) -Wall -D_REENTRANT -DLINUX -DUNIX -DUWSVR4
+INCLUDES =
+
+# Intel HPI parameters
+LIBDIR = /root/hpi/lib
+#LIBDIR = /usr/lib
+#LIBDIR = ./rpm/usr/lib
+LIBHPI = SaHpi
+HPIA = -DHPI_A
+# OpenHPI parameters (uncomment the next 3 lines)
+#LIBDIR = /usr/local/lib
+#LIBHPI = openhpi
+#HPIA =
+# (If openhpi is less than version 2.0.0, don't uncomment #HPIA.)
+
+# Additional compile flags
+CC = gcc
+CFLAGS +=
+LIBHPIF = $(LIBDIR)/lib$(LIBHPI).so
+
+# Link flags
+LDFLAGS = -pthread
+LDFLAGS += -lc
+LDFLAGS += -lm
+LDFLAGS += -L $(LIBDIR)
+LD_LIBRARY_PATH = $(LIBDIR)
+
+all: $(TARGETS)
+
+hpialarmpanel: hpialarmpanel.o $(LIBHPIF)
+ $(CC) $(LDFLAGS) -l$(LIBHPI) -o hpialarmpanel hpialarmpanel.o
+
+hpisensor: hpisensor.o $(LIBHPIF)
+ $(CC) $(LDFLAGS) -l$(LIBHPI) -o hpisensor hpisensor.o
+
+hpisel: hpisel.o $(LIBHPIF)
+ $(CC) $(LDFLAGS) -l$(LIBHPI) -o hpisel hpisel.o
+
+hpifru: hpifru.o $(LIBHPIF)
+ $(CC) $(LDFLAGS) -l$(LIBHPI) -o hpifru hpifru.o
+
+hpireset: hpireset.o $(LIBHPIF)
+ $(CC) $(LDFLAGS) -l$(LIBHPI) -o hpireset hpireset.o
+
+hpiwdt: hpiwdt.o $(LIBHPIF)
+ $(CC) $(LDFLAGS) -l$(LIBHPI) -o hpiwdt hpiwdt.o
+
+hpievent: hpievent.o $(LIBHPIF)
+ $(CC) $(LDFLAGS) -l$(LIBHPI) -o hpievent hpievent.o
+
+hpieventloop: hpieventloop.o $(LIBHPIF)
+ $(CC) $(LDFLAGS) -l$(LIBHPI) -o hpieventloop hpieventloop.o
+
+clean:
+ rm -f *.o *.i *.s $(TARGETS)
+
+distclean: clean
+ rm -f Makefile.deps
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) $(INCLUDES) $(HPIA) -o $@ $<
+
diff --git a/hpiutil/README b/hpiutil/README
new file mode 100644
index 0000000..75594f0
--- /dev/null
+++ b/hpiutil/README
@@ -0,0 +1,249 @@
+hpiutil
+
+OVERVIEW
+
+The HPI utilities package provides system management utilities that
+conform to the SA Forum's Hardware Platform Interface specification, and
+as such are hardware-independent across platforms that have an HPI
+library implementation. The HPI library on Intel platforms requires
+an IPMI driver. An IPMI driver can be provided by either the Intel
+IPMI driver (/dev/imb) or the OpenIPMI driver (/dev/ipmi0) in Linux
+kernel versions 2.4.20 and greater.
+
+This Intel HPI library is currently configured to use the /dev/imb
+interface, since that will coexist well with Intel Server Management
+software. The hpiutil rpms default to the /dev/imb interface.
+Note that the OpenIPMI driver also has imb emulation
+as an option.
+
+To switch to using the OpenIPMI driver's /dev/ipmi0 interface with
+this hpiutil package, do this after installing the rpm:
+ cp /usr/lib/libSpiModIpmi.so /usr/lib/libSpiModIpmi.so-imb
+ cp /usr/lib/libSpiModIpmi.so-open /usr/lib/libSpiModIpmi.so
+ sed -e 's/imb/ipmi0/' /etc/hpi/spi-daemon.conf >/tmp/spi
+ cp /tmp/spi /etc/hpi/spi-daemon.conf
+
+This package includes the Intel HPI binary libraries and the
+following HPI utilities.
+ hpialarmpanel
+ hpisel
+ hpifru
+ hpisensor
+ hpireset
+ hpiwdt
+
+NOTES
+This package uses the Intel HPI library implementation, but there
+is also an OpenHPI library implementation that could also be linked
+with these utilities. There are comments in the Makefile to show
+how this can be done.
+The hpiutil utilities are included in OpenHPI 1.0.0 and greater
+as openhpi-clients.
+The openhpi-2.6.3 and greater releases with the ipmidirect plugin
+have been tested to work well on IPMI systems.
+
+Variations from HPI 1.0 spec:
+
+- SystemGUID added. Implemented as a FRU Product Custom field.
+ The IPMI SystemGUID was not supported in the HPI FRU fields.
+ This library implementation shows SystemGUID as part of FRU, but
+ does not try to write GUID as part of FRU.
+ See HPI 1.0 spec errata #66
+
+- Power down added to Chassis/Cold Reset RDR via ControlStateSet(OFF)
+ There was no mechanism defined in the HPI 1.0 spec to support chassis
+ power down. Here is the way this was implemented with this library.
+ Doing ControlStateSet(ON) with the Reset RDR causes a hard reset.
+ Doing ControlStateSet(OFF) with the Reset RDR causes a power down.
+ See HPI 1.0 spec errata #30
+
+- Alarm LED RDRs were not differentiated.
+ This variation is required to implement ControlStateSet for Alarm LEDs.
+ See also HPI 1.0 spec errata #75
+ The oem field values are used to do this according to the following schema.
+
+ Control.Type Control.OutputType Control.Oem Meaning
+ Digital (=0) LED (=1) 0x10 Alarm panel Power LED
+ Digital (=0) LED (=1) 0x11 Alarm panel Critical LED
+ Digital (=0) LED (=1) 0x12 Alarm panel Major LED
+ Digital (=0) LED (=1) 0x13 Alarm panel Minor LED
+ Digital (=0) LED (=1) 0x14 - 0x1F Alarm panel other LEDs
+ Digital (=0) LED (=1) 0x20 - 0x2F Disk LEDs (if used)
+ Digital (=0) LED (=1) 0x30 - 0x3F NIC LEDs (if used)
+ Analog (=2) LED (=1) 0x60 Chassis Identify LED
+ Analog (=2) LED (=1) 0x61 - 0x6F Other Analog LEDs (if used)
+ Digital (=0) Generic (=0) 0x70 - 0x7F Chassis Reset Control
+
+
+SUPPORT
+
+The following error codes are returned by HPI APIs and are defined in SaHpi.h.
+ 0 SA_OK
+-1001 SA_ERR_HPI_ERROR
+-1002 SA_ERR_HPI_UNSUPPORTED_API
+-1003 SA_ERR_HPI_BUSY
+-1004 SA_ERR_HPI_INVALID
+-1005 SA_ERR_HPI_INVALID_CMD
+-1006 SA_ERR_HPI_TIMEOUT
+-1007 SA_ERR_HPI_OUT_OF_SPACE
+-1008 SA_ERR_HPI_DATA_TRUNCATED
+-1009 SA_ERR_HPI_DATA_LEN_INVALID
+-1010 SA_ERR_HPI_DATA_EX_LIMITS
+-1011 SA_ERR_HPI_INVALID_PARAMS
+-1012 SA_ERR_HPI_INVALID_DATA
+-1013 SA_ERR_HPI_NOT_PRESENT
+-1014 SA_ERR_HPI_INVALID_DATA_FIELD
+-1015 SA_ERR_HPI_INVALID_SENSOR_CMD
+-1016 SA_ERR_HPI_NO_RESPONSE
+-1017 SA_ERR_HPI_DUPLICATE
+-1018 SA_ERR_HPI_UPDATING
+-1019 SA_ERR_HPI_INITIALIZING
+-1020 SA_ERR_HPI_UNKNOWN
+-1021 SA_ERR_HPI_INVALID_SESSION
+-1022 SA_ERR_HPI_INVALID_DOMAIN
+-1023 SA_ERR_HPI_INVALID_RESOURCE
+-1024 SA_ERR_HPI_INVALID_REQUEST
+-1025 SA_ERR_HPI_ENTITY_NOT_PRESENT
+-1026 SA_ERR_HPI_UNINITIALIZED
+
+If problems occur, additional debug information can be obtained by
+editing the SPI_DAEMON_LOG_LEVEL variable in the /etc/rc.d/init.d/hpi
+script to change the log level.
+SPI_DAEMON_LOG_LEVEL - Level at which to log debug information. The
+ following list describes each of the logging
+ switches. Multiple switches may be used at once.
+ -l<num>: Logs data at a given level. Where num...
+ 1 = Logs debug low through fatal errors.
+ 2 = Logs debug high through fatal errors.
+ 3 = Logs informational through fatal errors.
+ 4 = Logs warnings through fatal errors.
+ 5 = Log non-fatal errors and fatal errors.
+ 6 = Logs fatal errors only.
+ -lf: Logs function entrance and exit.*
+ -lm: Logs memory usage.*
+ -ls: Logs semaphore usage.*
+ * = In order to use these options, the -l<num>
+ option must also be set.
+
+Support for the hpiutil rpm is provided on a best-effort basis via
+ tltsupport@linux.intel.com
+
+
+REFERENCES
+
+IPMI 1.5 specification: http://www.intel.com/design/servers/ipmi/
+Open source IPMI utilities: http://panicsel.sourceforge.net
+SA Forum HPI 1.0 spec: http://www.saforum.org/specification/HPI_Specification
+Intel HPI 1.0 compliance test suite: Contact Keith.L.Perrin@Intel.com
+OpenHPI project: http://openhpi.sourceforge.net
+
+TESTING
+
+ The binary HPI libraries included in this package have been tested to be
+ HPI 1.0 compliant via the Intel HPI 1.0 compliance test suite.
+
+ This package has been tested and is supported on the following Intel
+ servers: TSRLT2, TSRMT2, TIGPR2U, TIGPT1U.
+ See also http://www.saforum.org for platform support information.
+ Most of the utilities (except hpialarmpanel) should work on other
+ platforms as well, if they have IPMI 1.5 support.
+ Note that mBMC platforms, such as TIGPT1U, do not support the
+ Power On Hours function, which is optional in IPMI 1.5.
+
+ This hpiutil package is not inherently dependent on any OS variance,
+ as long as there is an IPMI driver. However, the version of glibc/gcc
+ does matter, since the library includes shared object files.
+ This HPI library and the HPI utilities have been tested on the
+ following Linux OSs.
+ RedHat EL 3 (gcc 3.2.3, glibc 2.3.2)
+ RedHat AS 2.1 (gcc 2.96, glibc 2.2.4)
+ RedHat 8.0 (gcc 3.2, glibc 2.2.93)
+ MontaVista CGE 2.1 (gcc 2.95.3, glibc 2.2.3 )
+ MontaVista CGE 3.0 (gcc 3.2.1, glibc 2.2.5)
+ MontaVista CGE 3.1 (gcc 3.2.1, glibc 2.2.5)
+ Other Linux OSs should work fine using an rpm with similar gcc/glibc.
+
+ SA-HPI Release 1.0 Library APIs
+ The following APIs are supported in this release:
+
+Initialization and Cleanup
+saHpiInitialize()
+saHpiFinalize()
+Session Management
+saHpiSessionOpen()
+saHpiSessionClose()
+
+Discovery of Resources
+saHpiResourcesDiscover()
+saHpiRptInfoGet()
+saHpiRptEntryGet()
+saHpiRptEntryGetByResourceId()
+saHpiResourceSeveritySet()
+saHpiResourceTagSet()
+saHpiResourceIdGet()
+saHpiEntitySchemaGet()
+
+Event Log Management
+saHpiEventLogInfoGet()
+saHpiEventLogEntryGet()
+saHpiEventLogEntryAdd()
+saHpiEventLogEntryDelete ()
+saHpiEventLogClear()
+saHpiEventLogTimeGet()
+saHpiEventLogTimeSet()
+saHpiEventLogStateGet()
+saHpiEventLogStateSet()
+
+Events
+saHpiSubscribe()
+saHpiUnsubscribe()
+saHpiEventGet()
+
+RDR Repository Management
+saHpiRdrGet()
+
+Sensor Functions
+saHpiSensorReadingGet()
+saHpiSensorReadingConvert()
+saHpiSensorThresholdsGet()
+saHpiSensorThresholdsSet()
+saHpiSensorTypeGet()
+saHpiSensorEventEnablesGet()
+saHpiSensorEventEnablesSet()
+
+Controls
+saHpiControlTypeGet()
+saHpiControlStateGet()
+saHpiControlStateSet()
+
+Entity Inventory Data
+saHpiEntityInventoryDataRead()
+saHpiEntityInventoryDataWrite()
+
+Watchdog Timer
+saHpiWatchdogTimerGet()
+saHpiWatchdogTimerSet()
+saHpiWatchdogTimerReset()
+
+Reset
+saHpiResourceResetStateGet()
+saHpiResourceResetStateSet()
+
+Hot Swap Routines
+saHpiHotSwapControlRequest()
+saHpiResourceActiveSet()
+saHpiResourceInactiveSet()
+saHpiAutoInsertTimeoutGet()
+saHpiAutoInsertTimeoutSet()
+saHpiAutoExtractTimeoutGet()
+saHpiAutoExtractTimeoutSet()
+saHpiHotSwapStateGet()
+saHpiHotSwapActionRequest()
+saHpiResourcePowerStateGet()
+saHpiResourcePowerStateSet()
+saHpiHotSwapIndicatorStateGet()
+saHpiHotSwapIndicatorStateSet()
+
+Configuration
+saHpiParmControl() - disabled for this library by design
+
diff --git a/hpiutil/SaHpi.h b/hpiutil/SaHpi.h
new file mode 100644
index 0000000..6efd5e9
--- /dev/null
+++ b/hpiutil/SaHpi.h
@@ -0,0 +1,4509 @@
+/*******************************************************************************
+**
+** FILE:
+** SaHpi.h
+**
+** DESCRIPTION:
+** This file provides the C language binding for the Service
+** Availability(TM) Forum Platform Interface. It contains all of
+** the prototypes and type definitions. Note, this file was
+** generated from the Platform Interface specification document.
+**
+** SPECIFICATION VERSION:
+** SAI-HPI-A.01.01
+**
+** DATE:
+** Thu Oct 3 14:48:41 2002
+**
+** LEGAL:
+** OWNERSHIP OF SPECIFICATION AND COPYRIGHTS.
+** The Specification and all worldwide copyrights therein are
+** the exclusive property of Licensor. You may not remove, obscure, or
+** alter any copyright or other proprietary rights notices that are in or
+** on the copy of the Specification you download. You must reproduce all
+** such notices on all copies of the Specification you make. Licensor
+** may make changes to the Specification, or to items referenced therein,
+** at any time without notice. Licensor is not obligated to support or
+** update the Specification.
+**
+** Copyright(c) 2002, Service Availability(TM) Forum. All rights
+** reserved.
+**
+*******************************************************************************/
+
+#ifndef __SAHPI_H
+#define __SAHPI_H
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Basic Data Types and Values **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* General Types - need to be specified correctly for the host architecture */
+typedef unsigned char SaHpiUint8T;
+typedef unsigned short SaHpiUint16T;
+typedef unsigned int SaHpiUint32T;
+typedef char SaHpiInt8T;
+typedef short SaHpiInt16T;
+typedef int SaHpiInt32T;
+typedef long long SaHpiInt64T;
+typedef float SaHpiFloat32T;
+typedef double SaHpiFloat64T;
+
+typedef SaHpiUint8T SaHpiBoolT;
+#define SAHPI_TRUE 1
+#define SAHPI_FALSE 0
+
+/* Platform, O/S, or Vendor dependent */
+#define SAHPI_API
+#define SAHPI_IN
+#define SAHPI_OUT
+#define SAHPI_INOUT
+
+/*
+** Identifier for the manufacturer
+**
+** This is the IANA-assigned private enterprise number for the
+** manufacturer of the resource or FRU, or of the manufacturer
+** defining an OEM control or event type. A list of current
+** IANA-assigned private enterprise numbers may be obtained at
+**
+** http://www.iana.org/assignments/enterprise-numbers
+**
+** If a manufacturer does not currently have an assigned number, one
+** may be obtained by following the instructions located at
+**
+** http://www.iana.org/cgi-bin/enterprise.pl
+*/
+typedef SaHpiUint32T SaHpiManufacturerIdT;
+#define SAHPI_MANUFACTURER_ID_UNSPECIFIED (SaHpiManufacturerIdT)0
+
+/* Version Types */
+typedef SaHpiUint32T SaHpiVersionT;
+
+/*
+** Interface Version
+**
+** The interface version is the version of the actual interface and not the
+** version of the implementation. It is a 24 bit value where
+** the most significant 8 bits represent the compatibility level
+** (with letters represented as the corresponding numbers);
+** the next 8 bits represent the major version number; and
+** the least significant 8 bits represent the minor version number.
+*/
+#define SAHPI_INTERFACE_VERSION (SaHpiVersionT)0x010101 /* A.01.01 */
+
+/*
+** Return Codes
+**
+** SaErrorT is defined in the HPI specification. In the future a
+** common SAF types definition may be created to contain this type. At
+** that time, this typedef should be removed.
+*/
+typedef SaHpiInt32T SaErrorT; /* Return code */
+
+/*
+** SA_OK: This code indicates that a command completed successfully.
+*/
+#define SA_OK (SaErrorT)0x0000
+
+/* This value is the base for all HPI-specific error codes. */
+#define SA_HPI_ERR_BASE -1000
+
+/*
+** SA_ERR_HPI_ERROR: An unspecified error occurred. This code should
+** be returned only as a last resort; eg. if the cause of an error
+** cannot be determined.
+*/
+#define SA_ERR_HPI_ERROR (SaErrorT)(SA_HPI_ERR_BASE - 1)
+
+/*
+** SA_ERR_HPI_UNSUPPORTED_API: The HPI implementation does not support
+** this API. This code is appropriate, for example, if invoking the
+** Hot Swap functions on an HPI implementation which has no hot swap
+** support. Note that such an implementation would not report any hot
+** swap capabilities via its RDRs.
+*/
+#define SA_ERR_HPI_UNSUPPORTED_API (SaErrorT)(SA_HPI_ERR_BASE - 2)
+
+/*
+** SA_ERR_HPI_BUSY: The command cannot be performed because the
+** targeted device is busy.
+*/
+#define SA_ERR_HPI_BUSY (SaErrorT)(SA_HPI_ERR_BASE - 3)
+
+/*
+** SA_ERR_HPI_INVALID: The request is fundamentally invalid.
+*/
+#define SA_ERR_HPI_INVALID (SaErrorT)(SA_HPI_ERR_BASE - 4)
+
+/*
+** SA_ERR_HPI_INVALID_CMD: The specific object to which a command was
+** directed does not support that command (which was otherwise valid).
+*/
+#define SA_ERR_HPI_INVALID_CMD (SaErrorT)(SA_HPI_ERR_BASE - 5)
+
+/*
+** SA_ERR_HPI_TIMEOUT: The requested operation, which had a timeout
+** value specified, timed out. For example, when reading input with a
+** timeout value, if no input arrives within the timeout interval,
+** this code should be returned. This should only be returned in
+** cases where a timeout is anticipated as a valid consequence of the
+** operation; if the addressed entity is not responding due to a
+** fault, use SA_ERR_HPI_NO_RESPONSE (qv).
+*/
+#define SA_ERR_HPI_TIMEOUT (SaErrorT)(SA_HPI_ERR_BASE - 6)
+
+/*
+** SA_ERR_HPI_OUT_OF_SPACE: The requested command failed due to
+** resource limits.
+*/
+#define SA_ERR_HPI_OUT_OF_SPACE (SaErrorT)(SA_HPI_ERR_BASE - 7)
+
+/*
+** SA_ERR_HPI_DATA_TRUNCATED: The returned data was truncated. For
+** example, when reading data into a fixed-size buffer, if the data is
+** larger than the buffer, this code should be returned.
+*/
+#define SA_ERR_HPI_DATA_TRUNCATED (SaErrorT)(SA_HPI_ERR_BASE - 8)
+
+/*
+** SA_ERR_HPI_DATA_LEN_INVALID: The specified data length is invalid.
+*/
+#define SA_ERR_HPI_DATA_LEN_INVALID (SaErrorT)(SA_HPI_ERR_BASE - 9)
+
+/*
+** SA_ERR_HPI_DATA_EX_LIMITS: The supplied data exceeds limits.
+*/
+#define SA_ERR_HPI_DATA_EX_LIMITS (SaErrorT)(SA_HPI_ERR_BASE - 10)
+
+/*
+** SA_ERR_HPI_INVALID_PARAMS: One or more parameters to the command
+** were invalid.
+*/
+#define SA_ERR_HPI_INVALID_PARAMS (SaErrorT)(SA_HPI_ERR_BASE - 11)
+
+/*
+** SA_ERR_HPI_INVALID_DATA: Cannot return requested data; eg. the
+** specific object to which a command was directed does not support
+** the data required by the command.
+*/
+#define SA_ERR_HPI_INVALID_DATA (SaErrorT)(SA_HPI_ERR_BASE - 12)
+
+/*
+** SA_ERR_HPI_NOT_PRESENT: The requested object was not present. For
+** example, this code would be returned when attempting to access an
+** entry in a RPT or RDR which is not present. As another example, this
+** code would also be returned when accessing an invalid management
+** instrument on a valid resource.
+*/
+#define SA_ERR_HPI_NOT_PRESENT (SaErrorT)(SA_HPI_ERR_BASE - 13)
+
+/*
+** SA_ERR_HPI_INVALID_DATA_FIELD: Invalid data field.
+*/
+#define SA_ERR_HPI_INVALID_DATA_FIELD (SaErrorT)(SA_HPI_ERR_BASE - 14)
+
+/*
+** SA_ERR_HPI_INVALID_SENSOR_CMD: Invalid sensor command.
+*/
+#define SA_ERR_HPI_INVALID_SENSOR_CMD (SaErrorT)(SA_HPI_ERR_BASE - 15)
+
+/*
+** SA_ERR_HPI_NO_RESPONSE: There was no response from the domain or
+** object targeted by the command, due to some fault. This code
+** indicates an un-anticipated failure to respond; compare with
+** SA_ERR_HPI_TIMEOUT.
+*/
+#define SA_ERR_HPI_NO_RESPONSE (SaErrorT)(SA_HPI_ERR_BASE - 16)
+
+/*
+** SA_ERR_HPI_DUPLICATE: Duplicate request -- such as attempting to
+** initialize something which has already been initialized (and which
+** cannot be initialized twice).
+*/
+#define SA_ERR_HPI_DUPLICATE (SaErrorT)(SA_HPI_ERR_BASE - 17)
+
+/*
+** SA_ERR_HPI_UPDATING: The command could not be completed because
+** the targeted object is in update mode.
+*/
+#define SA_ERR_HPI_UPDATING (SaErrorT)(SA_HPI_ERR_BASE - 18)
+
+/*
+** SA_ERR_HPI_INITIALIZING: The command could not be completed because
+** the targeted object is initializing.
+*/
+#define SA_ERR_HPI_INITIALIZING (SaErrorT)(SA_HPI_ERR_BASE - 19)
+
+/*
+** SA_ERR_HPI_UNKNOWN: This code should be returned if, for some
+** reason, the HPI implementation cannot determine the proper response
+** to a command. For example, there may be a proper value to return
+** for a given call, but the implementation may be unable to determine
+** which one it is.
+*/
+#define SA_ERR_HPI_UNKNOWN (SaErrorT)(SA_HPI_ERR_BASE - 20)
+
+/*
+** SA_ERR_HPI_INVALID_SESSION: An invalid session ID was specified in
+** the command.
+*/
+#define SA_ERR_HPI_INVALID_SESSION (SaErrorT)(SA_HPI_ERR_BASE - 21)
+
+/*
+** SA_ERR_HPI_INVALID_DOMAIN: Invalid domain ID specified -- ie. a
+** domain ID which does not correspond to any real domain was
+** specified in the command.
+*/
+#define SA_ERR_HPI_INVALID_DOMAIN (SaErrorT)(SA_HPI_ERR_BASE - 22)
+
+/*
+** SA_ERR_HPI_INVALID_RESOURCE: Invalid resource ID specified -- ie. a
+** resource ID which does not correspond to a resource in the addressed
+** domain was specified in the command.
+*/
+#define SA_ERR_HPI_INVALID_RESOURCE (SaErrorT)(SA_HPI_ERR_BASE - 23)
+
+/*
+** SA_ERR_HPI_INVALID_REQUEST: The request is invalid in the current
+** context. An example would be attempting to unsubscribe for events,
+** when the caller has not subscribed to events.
+*/
+#define SA_ERR_HPI_INVALID_REQUEST (SaErrorT)(SA_HPI_ERR_BASE - 24)
+
+/*
+** SA_ERR_HPI_ENTITY_NOT_PRESENT: The addressed management instrument is not active
+** because the entity with which it is associated is not present. This
+** condition could occur, for instance, when an alarm module is managing a
+** fan tray FRU. The alarm module would contain management instruments (sensors,
+** etc) for the fan tray. The fan tray may be removed, even though the
+** management instruments are still represented in the alarm module. In this
+** case, SA_ERR_HPI_ENTITY_NOT_PRESENT would be returned if a management instrument
+** associated with a removed entity is accessed.
+*/
+#define SA_ERR_HPI_ENTITY_NOT_PRESENT (SaErrorT)(SA_HPI_ERR_BASE - 25)
+
+/*
+** SA_ERR_HPI_UNINITIALIZED: This code is returned when a request is
+** made, and the HPI has not, yet, been initialized via saHpiInitialize().
+*/
+#define SA_ERR_HPI_UNINITIALIZED (SaErrorT)(SA_HPI_ERR_BASE - 26)
+
+
+/*
+** Domain, Session and Resource Type Definitions
+*/
+
+/* Domain ID. */
+typedef SaHpiUint32T SaHpiDomainIdT;
+#define SAHPI_DEFAULT_DOMAIN_ID (SaHpiDomainIdT)0
+
+/* The SAHPI_UNSPECIFIED_DOMAIN_ID value may be used by an implementation
+** when populating the ResourceId value for an RPT entry that is a
+** domain only.
+*/
+#define SAHPI_UNSPECIFIED_DOMAIN_ID (SaHpiDomainIdT) 0xFFFFFFFF
+
+/* Session ID. */
+typedef SaHpiUint32T SaHpiSessionIdT;
+
+/* Resource identifier. */
+typedef SaHpiUint32T SaHpiResourceIdT;
+
+/* The SAHPI_UNSPECIFIED_RESOURCE_ID value may be used by an implementation
+** when populating the DomainId value for an RPT entry that is a
+** resource only. Note that this reserved value (0xFFFFFFFF) is also used
+** to designate the domain controller, for domain-based event log access.
+*/
+#define SAHPI_UNSPECIFIED_RESOURCE_ID (SaHpiResourceIdT) 0xFFFFFFFF
+
+/* The SAHPI_DOMAIN_CONTROLLER_ID value is a reserved resource ID
+** value which is used to select the domain controller's event log
+** (as opposed to a real resource's event log) when accessing logs.
+** This value must not be used as the ID of any real resource.
+*/
+#define SAHPI_DOMAIN_CONTROLLER_ID (SaHpiResourceIdT) 0xFFFFFFFE
+
+/* Table Related Type Definitions */
+typedef SaHpiUint32T SaHpiEntryIdT;
+#define SAHPI_FIRST_ENTRY (SaHpiEntryIdT)0x00000000
+#define SAHPI_LAST_ENTRY (SaHpiEntryIdT)0xFFFFFFFF
+
+/*
+** Time Related Type Definitions
+**
+** An HPI time value represents the local time as the number of nanoseconds
+** from 00:00:00, January 1, 1970, in a 64-bit signed integer. This format
+** is sufficient to represent times with nano-second resolution from the
+** year 1678 to 2262. Every API which deals with time values must define
+** the timezone used.
+**
+** It should be noted that although nano-second resolution is supported
+** in the data type, the actual resolution provided by an implementation
+** may be more limited than this.
+**
+** The value -2**63, which is 0x8000000000000000, is used to indicate
+** "unknown/unspecified time".
+**
+** Conversion to/from POSIX and other common time representations is
+** relatively straightforward. The following code framgment converts
+** between SaHpiTimeT and time_t:
+**
+** time_t tt1, tt2;
+** SaHpiTimeT saHpiTime;
+**
+** time(&tt1);
+** saHpiTime = (SaHpiTimeT) tt1 * 1000000000;
+** tt2 = saHpiTime / 1000000000;
+**
+** The following fragment converts between SaHpiTimeT and a struct timeval:
+**
+** struct timeval tv1, tv2;
+** SaHpiTimeT saHpiTime;
+**
+** gettimeofday(&tv1, NULL);
+** saHpiTime = (SaHpiTimeT) tv1.tv_sec * 1000000000 + tv1.tv_usec * 1000;
+** tv2.tv_sec = saHpiTime / 1000000000;
+** tv2.tv_usec = saHpiTime % 1000000000 / 1000;
+**
+** The following fragment converts between SaHpiTimeT and a struct timespec:
+**
+** struct timespec ts1, ts2;
+** SaHpiTimeT saHpiTime;
+**
+** clock_gettime(CLOCK_REALTIME, &ts1);
+** saHpiTime = (SaHpiTimeT) ts1.tv_sec * 1000000000 + ts1.tv_nsec;
+** ts2.tv_sec = saHpiTime / 1000000000;
+** ts2.tv_nsec = saHpiTime % 1000000000;
+**
+** Note, however, that since time_t is (effectively) universally 32 bits,
+** all of these conversions will cease to work on January 18, 2038.
+**
+** Some subsystems may need the flexibility to report either absolute or
+** relative (eg. to system boot) times. This will typically be in the
+** case of a board which may or may not, depending on the system setup,
+** have an idea of absolute time. For example, some boards may have
+** "time of day" clocks which start at zero, and never get set to the
+** time of day.
+**
+** In these cases, times which represent "current" time (in events, for
+** example) can be reported based on the clock value, whether it has been
+** set to the actual date/time, or whether it represents the elapsed time
+** since boot. If it is the time since boot, the value will be (for 27
+** years) less than 0x0C00000000000000, which is Mon May 26 16:58:48 1997.
+** If the value is greater than this, then it can be assumed to be an
+** absolute time.
+**
+** Every API which can report either absolute or relative times must
+** state this rule clearly in its interface specification.
+*/
+typedef SaHpiInt64T SaHpiTimeT; /* Time in nanoseconds */
+
+/* Unspecified or unknown time */
+#define SAHPI_TIME_UNSPECIFIED (SaHpiTimeT) 0x8000000000000000
+
+/* Maximum time that can be specified as relative */
+#define SAHPI_TIME_MAX_RELATIVE (SaHpiTimeT) 0x0C00000000000000
+typedef SaHpiInt64T SaHpiTimeoutT; /* Timeout in nanoseconds */
+
+/* Non-blocking call */
+#define SAHPI_TIMEOUT_IMMEDIATE (SaHpiTimeoutT) 0x0000000000000000
+
+/* Blocking call, wait indefinitely for call to complete */
+#define SAHPI_TIMEOUT_BLOCK (SaHpiTimeoutT) -1
+
+/*
+** Language
+**
+** This enumeration lists all of the languages that can be associated with text.
+**
+** SAHPI_LANG_UNDEF indicates that the language is unspecified or
+** unknown.
+*/
+typedef enum {
+ SAHPI_LANG_UNDEF = 0, SAHPI_LANG_AFAR, SAHPI_LANG_ABKHAZIAN,
+ SAHPI_LANG_AFRIKAANS, SAHPI_LANG_AMHARIC, SAHPI_LANG_ARABIC,
+ SAHPI_LANG_ASSAMESE, SAHPI_LANG_AYMARA, SAHPI_LANG_AZERBAIJANI,
+ SAHPI_LANG_BASHKIR, SAHPI_LANG_BYELORUSSIAN, SAHPI_LANG_BULGARIAN,
+ SAHPI_LANG_BIHARI, SAHPI_LANG_BISLAMA, SAHPI_LANG_BENGALI,
+ SAHPI_LANG_TIBETAN, SAHPI_LANG_BRETON, SAHPI_LANG_CATALAN,
+ SAHPI_LANG_CORSICAN, SAHPI_LANG_CZECH, SAHPI_LANG_WELSH,
+ SAHPI_LANG_DANISH, SAHPI_LANG_GERMAN, SAHPI_LANG_BHUTANI,
+ SAHPI_LANG_GREEK, SAHPI_LANG_ENGLISH, SAHPI_LANG_ESPERANTO,
+ SAHPI_LANG_SPANISH, SAHPI_LANG_ESTONIAN, SAHPI_LANG_BASQUE,
+ SAHPI_LANG_PERSIAN, SAHPI_LANG_FINNISH, SAHPI_LANG_FIJI,
+ SAHPI_LANG_FAEROESE, SAHPI_LANG_FRENCH, SAHPI_LANG_FRISIAN,
+ SAHPI_LANG_IRISH, SAHPI_LANG_SCOTSGAELIC, SAHPI_LANG_GALICIAN,
+ SAHPI_LANG_GUARANI, SAHPI_LANG_GUJARATI, SAHPI_LANG_HAUSA,
+ SAHPI_LANG_HINDI, SAHPI_LANG_CROATIAN, SAHPI_LANG_HUNGARIAN,
+ SAHPI_LANG_ARMENIAN, SAHPI_LANG_INTERLINGUA, SAHPI_LANG_INTERLINGUE,
+ SAHPI_LANG_INUPIAK, SAHPI_LANG_INDONESIAN, SAHPI_LANG_ICELANDIC,
+ SAHPI_LANG_ITALIAN, SAHPI_LANG_HEBREW, SAHPI_LANG_JAPANESE,
+ SAHPI_LANG_YIDDISH, SAHPI_LANG_JAVANESE, SAHPI_LANG_GEORGIAN,
+ SAHPI_LANG_KAZAKH, SAHPI_LANG_GREENLANDIC, SAHPI_LANG_CAMBODIAN,
+ SAHPI_LANG_KANNADA, SAHPI_LANG_KOREAN, SAHPI_LANG_KASHMIRI,
+ SAHPI_LANG_KURDISH, SAHPI_LANG_KIRGHIZ, SAHPI_LANG_LATIN,
+ SAHPI_LANG_LINGALA, SAHPI_LANG_LAOTHIAN, SAHPI_LANG_LITHUANIAN,
+ SAHPI_LANG_LATVIANLETTISH, SAHPI_LANG_MALAGASY, SAHPI_LANG_MAORI,
+ SAHPI_LANG_MACEDONIAN, SAHPI_LANG_MALAYALAM, SAHPI_LANG_MONGOLIAN,
+ SAHPI_LANG_MOLDAVIAN, SAHPI_LANG_MARATHI, SAHPI_LANG_MALAY,
+ SAHPI_LANG_MALTESE, SAHPI_LANG_BURMESE, SAHPI_LANG_NAURU,
+ SAHPI_LANG_NEPALI, SAHPI_LANG_DUTCH, SAHPI_LANG_NORWEGIAN,
+ SAHPI_LANG_OCCITAN, SAHPI_LANG_AFANOROMO, SAHPI_LANG_ORIYA,
+ SAHPI_LANG_PUNJABI, SAHPI_LANG_POLISH, SAHPI_LANG_PASHTOPUSHTO,
+ SAHPI_LANG_PORTUGUESE, SAHPI_LANG_QUECHUA, SAHPI_LANG_RHAETOROMANCE,
+ SAHPI_LANG_KIRUNDI, SAHPI_LANG_ROMANIAN, SAHPI_LANG_RUSSIAN,
+ SAHPI_LANG_KINYARWANDA, SAHPI_LANG_SANSKRIT, SAHPI_LANG_SINDHI,
+ SAHPI_LANG_SANGRO, SAHPI_LANG_SERBOCROATIAN, SAHPI_LANG_SINGHALESE,
+ SAHPI_LANG_SLOVAK, SAHPI_LANG_SLOVENIAN, SAHPI_LANG_SAMOAN,
+ SAHPI_LANG_SHONA, SAHPI_LANG_SOMALI, SAHPI_LANG_ALBANIAN,
+ SAHPI_LANG_SERBIAN, SAHPI_LANG_SISWATI, SAHPI_LANG_SESOTHO,
+ SAHPI_LANG_SUDANESE, SAHPI_LANG_SWEDISH, SAHPI_LANG_SWAHILI,
+ SAHPI_LANG_TAMIL, SAHPI_LANG_TELUGU, SAHPI_LANG_TAJIK,
+ SAHPI_LANG_THAI, SAHPI_LANG_TIGRINYA, SAHPI_LANG_TURKMEN,
+ SAHPI_LANG_TAGALOG, SAHPI_LANG_SETSWANA, SAHPI_LANG_TONGA,
+ SAHPI_LANG_TURKISH, SAHPI_LANG_TSONGA, SAHPI_LANG_TATAR,
+ SAHPI_LANG_TWI, SAHPI_LANG_UKRAINIAN, SAHPI_LANG_URDU,
+ SAHPI_LANG_UZBEK, SAHPI_LANG_VIETNAMESE, SAHPI_LANG_VOLAPUK,
+ SAHPI_LANG_WOLOF, SAHPI_LANG_XHOSA, SAHPI_LANG_YORUBA,
+ SAHPI_LANG_CHINESE, SAHPI_LANG_ZULU
+} SaHpiLanguageT;
+
+/*
+** Text Buffers
+**
+** These structures are used for defining the type of data in the text buffer
+** and the length of the buffer. Text buffers are used in the inventory data,
+** RDR, RPT, etc. for variable length strings of data.
+*/
+
+#define SAHPI_MAX_TEXT_BUFFER_LENGTH 255
+
+typedef enum {
+ SAHPI_TL_TYPE_BINARY = 0, /* String of bytes, any values legal */
+ SAHPI_TL_TYPE_BCDPLUS, /* String of 0-9, space, dash, period ONLY */
+ SAHPI_TL_TYPE_ASCII6, /* Reduced ASCII character set: 0x20-0x5F
+ ONLY */
+ SAHPI_TL_TYPE_LANGUAGE /* ASCII or UNICODE depending on language */
+} SaHpiTextTypeT;
+
+typedef struct {
+ SaHpiTextTypeT DataType;
+ SaHpiLanguageT Language; /* Language the text is in. */
+ SaHpiUint8T DataLength; /* Bytes used in Data buffer */
+ SaHpiUint8T Data[SAHPI_MAX_TEXT_BUFFER_LENGTH]; /* Data buffer */
+} SaHpiTextBufferT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Entities **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+/*
+** Entity Types
+**
+** Entities are used to associate specific hardware components with sensors,
+** controls, watchdogs, or resources. Entities are defined with an entity
+** type enumeration, and an entity instance number (to distinguish between
+** multiple instances of a particular type of entity; e.g., multiple power
+** supplies in a system).
+**
+** Entities are uniquely identified in a system with an ordered series of
+** Entity Type / Entity Instance pairs called an "Entity Path". Each subsequent
+** Entity Type/Entity Instance in the path is the next higher "containing"
+** entity. The "root" of the Entity Path (the outermost level of containment)
+** is designated with an Entity Type of SAHPI_ENT_ROOT if the entire Entity Path
+** is fewer than SAHPI_MAX_ENTITY_PATH entries in length.
+**
+** Enumerated Entity Types include those types enumerated by the IPMI Consortium
+** for IPMI-managed entities, as well as additional types defined by the
+** HPI specification. Room is left in the enumeration for the inclusion of
+** Entity Types taken from other lists, if needed in the future.
+*/
+/* Base values for entity types from various sources. */
+#define SAHPI_ENT_IPMI_GROUP 0
+#define SAHPI_ENT_SAFHPI_GROUP 0x10000
+#define SAHPI_ENT_ROOT_VALUE 0xFFFF
+typedef enum
+{
+ SAHPI_ENT_UNSPECIFIED = SAHPI_ENT_IPMI_GROUP,
+ SAHPI_ENT_OTHER,
+ SAHPI_ENT_UNKNOWN,
+ SAHPI_ENT_PROCESSOR,
+ SAHPI_ENT_DISK_BAY, /* Disk or disk bay */
+ SAHPI_ENT_PERIPHERAL_BAY,
+ SAHPI_ENT_SYS_MGMNT_MODULE, /* System management module */
+ SAHPI_ENT_SYSTEM_BOARD, /* Main system board, may also be
+ processor board and/or internal
+ expansion board */
+ SAHPI_ENT_MEMORY_MODULE, /* Board holding memory devices */
+ SAHPI_ENT_PROCESSOR_MODULE, /* Holds processors, use this
+ designation when processors are not
+ mounted on system board */
+ SAHPI_ENT_POWER_SUPPLY, /* Main power supply (supplies) for the
+ system */
+ SAHPI_ENT_ADD_IN_CARD,
+ SAHPI_ENT_FRONT_PANEL_BOARD, /* Control panel */
+ SAHPI_ENT_BACK_PANEL_BOARD,
+ SAHPI_ENT_POWER_SYSTEM_BOARD,
+ SAHPI_ENT_DRIVE_BACKPLANE,
+ SAHPI_ENT_SYS_EXPANSION_BOARD, /* System internal expansion board
+ (contains expansion slots). */
+ SAHPI_ENT_OTHER_SYSTEM_BOARD, /* Part of board set */
+ SAHPI_ENT_PROCESSOR_BOARD, /* Holds 1 or more processors. Includes
+ boards that hold SECC modules) */
+ SAHPI_ENT_POWER_UNIT, /* Power unit / power domain (typically
+ used as a pre-defined logical entity
+ for grouping power supplies)*/
+ SAHPI_ENT_POWER_MODULE, /* Power module / DC-to-DC converter.
+ Use this value for internal
+ converters. Note: You should use
+ entity ID (power supply) for the
+ main power supply even if the main
+ supply is a DC-to-DC converter */
+ SAHPI_ENT_POWER_MGMNT, /* Power management/distribution
+ board */
+ SAHPI_ENT_CHASSIS_BACK_PANEL_BOARD,
+ SAHPI_ENT_SYSTEM_CHASSIS,
+ SAHPI_ENT_SUB_CHASSIS,
+ SAHPI_ENT_OTHER_CHASSIS_BOARD,
+ SAHPI_ENT_DISK_DRIVE_BAY,
+ SAHPI_ENT_PERIPHERAL_BAY_2,
+ SAHPI_ENT_DEVICE_BAY,
+ SAHPI_ENT_COOLING_DEVICE, /* Fan/cooling device */
+ SAHPI_ENT_COOLING_UNIT, /* Can be used as a pre-defined logical
+ entity for grouping fans or other
+ cooling devices. */
+ SAHPI_ENT_INTERCONNECT, /* Cable / interconnect */
+ SAHPI_ENT_MEMORY_DEVICE, /* This Entity ID should be used for
+ replaceable memory devices, e.g.
+ DIMM/SIMM. It is recommended that
+ Entity IDs not be used for
+ individual non-replaceable memory
+ devices. Rather, monitoring and
+ error reporting should be associated
+ with the FRU [e.g. memory card]
+ holding the memory. */
+ SAHPI_ENT_SYS_MGMNT_SOFTWARE, /* System Management Software */
+ SAHPI_ENT_BIOS,
+ SAHPI_ENT_OPERATING_SYSTEM,
+ SAHPI_ENT_SYSTEM_BUS,
+ SAHPI_ENT_GROUP, /* This is a logical entity for use with
+ Entity Association records. It is
+ provided to allow a sensor data
+ record to point to an entity-
+ association record when there is no
+ appropriate pre-defined logical
+ entity for the entity grouping.
+ This Entity should not be used as a
+ physical entity. */
+ SAHPI_ENT_REMOTE, /* Out of band management communication
+ device */
+ SAHPI_ENT_EXTERNAL_ENVIRONMENT,
+ SAHPI_ENT_BATTERY,
+ SAHPI_ENT_CHASSIS_SPECIFIC = SAHPI_ENT_IPMI_GROUP + 0x90,
+ SAHPI_ENT_BOARD_SET_SPECIFIC = SAHPI_ENT_IPMI_GROUP + 0xB0,
+ SAHPI_ENT_OEM_SYSINT_SPECIFIC = SAHPI_ENT_IPMI_GROUP + 0xD0,
+ SAHPI_ENT_ROOT = SAHPI_ENT_ROOT_VALUE,
+ SAHPI_ENT_RACK = SAHPI_ENT_SAFHPI_GROUP,
+ SAHPI_ENT_SUBRACK,
+ SAHPI_ENT_COMPACTPCI_CHASSIS,
+ SAHPI_ENT_ADVANCEDTCA_CHASSIS,
+ SAHPI_ENT_SYSTEM_SLOT,
+ SAHPI_ENT_SBC_BLADE,
+ SAHPI_ENT_IO_BLADE,
+ SAHPI_ENT_DISK_BLADE,
+ SAHPI_ENT_DISK_DRIVE,
+ SAHPI_ENT_FAN,
+ SAHPI_ENT_POWER_DISTRIBUTION_UNIT,
+ SAHPI_ENT_SPEC_PROC_BLADE, /* Special Processing Blade,
+ including DSP */
+ SAHPI_ENT_IO_SUBBOARD, /* I/O Sub-Board, including
+ PMC I/O board */
+ SAHPI_ENT_SBC_SUBBOARD, /* SBC Sub-Board, including PMC
+ SBC board */
+ SAHPI_ENT_ALARM_MANAGER, /* Chassis alarm manager board */
+ SAHPI_ENT_ALARM_MANAGER_BLADE, /* Blade-based alarm manager */
+ SAHPI_ENT_SUBBOARD_CARRIER_BLADE /* Includes PMC Carrier Blade --
+ Use only if "carrier" is only
+ function of blade. Else use
+ primary function (SBC_BLADE,
+ DSP_BLADE, etc.). */
+ } SaHpiEntityTypeT;
+
+typedef SaHpiUint32T SaHpiEntityInstanceT;
+
+typedef struct {
+ SaHpiEntityTypeT EntityType;
+ SaHpiEntityInstanceT EntityInstance;
+} SaHpiEntityT;
+
+#define SAHPI_MAX_ENTITY_PATH 16
+
+typedef struct {
+ SaHpiEntityT Entry[SAHPI_MAX_ENTITY_PATH];
+} SaHpiEntityPathT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Events, part 1 **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** Category
+**
+** Sensor events contain an event category and event state. Depending on the
+** event category, the event states take on different meanings for events
+** generated by specific sensors.
+**
+** The SAHPI_EC_GENERIC category can be used for discrete sensors which have
+** state meanings other than those identified with other event categories.
+*/
+typedef SaHpiUint8T SaHpiEventCategoryT;
+
+#define SAHPI_EC_UNSPECIFIED (SaHpiEventCategoryT)0x00 /* Unspecified */
+#define SAHPI_EC_THRESHOLD (SaHpiEventCategoryT)0x01 /* Threshold
+ events */
+#define SAHPI_EC_USAGE (SaHpiEventCategoryT)0x02 /* Usage state
+ events */
+#define SAHPI_EC_STATE (SaHpiEventCategoryT)0x03 /* Generic state
+ events */
+#define SAHPI_EC_PRED_FAIL (SaHpiEventCategoryT)0x04 /* Predictive fail
+ events */
+#define SAHPI_EC_LIMIT (SaHpiEventCategoryT)0x05 /* Limit events */
+#define SAHPI_EC_PERFORMANCE (SaHpiEventCategoryT)0x06 /* Performance
+ events */
+#define SAHPI_EC_SEVERITY (SaHpiEventCategoryT)0x07 /* Severity
+ indicating
+ events */
+#define SAHPI_EC_PRESENCE (SaHpiEventCategoryT)0x08 /* Device presence
+ events */
+#define SAHPI_EC_ENABLE (SaHpiEventCategoryT)0x09 /* Device enabled
+ events */
+#define SAHPI_EC_AVAILABILITY (SaHpiEventCategoryT)0x0A /* Availability
+ state events */
+
+#define SAHPI_EC_REDUNDANCY (SaHpiEventCategoryT)0x0B /* Redundancy
+ state events */
+#define SAHPI_EC_USER (SaHpiEventCategoryT)0x7E /* User defined
+ events */
+#define SAHPI_EC_GENERIC (SaHpiEventCategoryT)0x7F /* OEM defined
+ events */
+
+/*
+** Event States
+**
+** The following event states are specified relative to the categories listed
+** above. The event types are only valid for their given category. Each set of
+** events is labeled as to which category it belongs to.
+** Each event will have only one event state associated with it. When retrieving
+** the event status or event enabled status a bit mask of all applicable event
+** states is used. Similarly, when setting the event enabled status a bit mask
+** of all applicable event states is used.
+*/
+typedef SaHpiUint16T SaHpiEventStateT;
+
+/*
+** SaHpiEventCategoryT == <any>
+*/
+#define SAHPI_ES_UNSPECIFIED (SaHpiEventStateT)0x0000
+
+/*
+** SaHpiEventCategoryT == SAHPI_EC_THRESHOLD
+** When using these event states, the event state should match
+** the event severity (for example SAHPI_ES_LOWER_MINOR should have an
+** event severity of SAHPI_MINOR).
+*/
+#define SAHPI_ES_LOWER_MINOR (SaHpiEventStateT)0x0001
+#define SAHPI_ES_LOWER_MAJOR (SaHpiEventStateT)0x0002
+#define SAHPI_ES_LOWER_CRIT (SaHpiEventStateT)0x0004
+#define SAHPI_ES_UPPER_MINOR (SaHpiEventStateT)0x0008
+#define SAHPI_ES_UPPER_MAJOR (SaHpiEventStateT)0x0010
+#define SAHPI_ES_UPPER_CRIT (SaHpiEventStateT)0x0020
+
+/* SaHpiEventCategoryT == SAHPI_EC_USAGE */
+#define SAHPI_ES_IDLE (SaHpiEventStateT)0x0001
+#define SAHPI_ES_ACTIVE (SaHpiEventStateT)0x0002
+#define SAHPI_ES_BUSY (SaHpiEventStateT)0x0004
+
+/* SaHpiEventCategoryT == SAHPI_EC_STATE */
+#define SAHPI_ES_STATE_DEASSERTED (SaHpiEventStateT)0x0001
+#define SAHPI_ES_STATE_ASSERTED (SaHpiEventStateT)0x0002
+
+/* SaHpiEventCategoryT == SAHPI_EC_PRED_FAIL */
+#define SAHPI_ES_PRED_FAILURE_DEASSERT (SaHpiEventStateT)0x0001
+#define SAHPI_ES_PRED_FAILURE_ASSERT (SaHpiEventStateT)0x0002
+
+/* SaHpiEventCategoryT == SAHPI_EC_LIMIT */
+#define SAHPI_ES_LIMIT_NOT_EXCEEDED (SaHpiEventStateT)0x0001
+#define SAHPI_ES_LIMIT_EXCEEDED (SaHpiEventStateT)0x0002
+
+/* SaHpiEventCategoryT == SAHPI_EC_PERFORMANCE */
+#define SAHPI_ES_PERFORMANCE_MET (SaHpiEventStateT)0x0001
+#define SAHPI_ES_PERFORMANCE_LAGS (SaHpiEventStateT)0x0002
+
+/*
+** SaHpiEventCategoryT == SAHPI_EC_SEVERITY
+** When using these event states, the event state should match
+** the event severity
+*/
+#define SAHPI_ES_OK (SaHpiEventStateT)0x0001
+#define SAHPI_ES_MINOR_FROM_OK (SaHpiEventStateT)0x0002
+#define SAHPI_ES_MAJOR_FROM_LESS (SaHpiEventStateT)0x0004
+#define SAHPI_ES_CRITICAL_FROM_LESS (SaHpiEventStateT)0x0008
+#define SAHPI_ES_MINOR_FROM_MORE (SaHpiEventStateT)0x0010
+#define SAHPI_ES_MAJOR_FROM_CRITICAL (SaHpiEventStateT)0x0020
+#define SAHPI_ES_CRITICAL (SaHpiEventStateT)0x0040
+#define SAHPI_ES_MONITOR (SaHpiEventStateT)0x0080
+#define SAHPI_ES_INFORMATIONAL (SaHpiEventStateT)0x0100
+
+/* SaHpiEventCategoryT == SAHPI_EC_PRESENCE */
+#define SAHPI_ES_ABSENT (SaHpiEventStateT)0x0001
+#define SAHPI_ES_PRESENT (SaHpiEventStateT)0x0002
+
+/* SaHpiEventCategoryT == SAHPI_EC_ENABLE */
+#define SAHPI_ES_DISABLED (SaHpiEventStateT)0x0001
+#define SAHPI_ES_ENABLED (SaHpiEventStateT)0x0002
+
+/* SaHpiEventCategoryT == SAHPI_EC_AVAILABILITY */
+#define SAHPI_ES_RUNNING (SaHpiEventStateT)0x0001
+#define SAHPI_ES_TEST (SaHpiEventStateT)0x0002
+#define SAHPI_ES_POWER_OFF (SaHpiEventStateT)0x0004
+#define SAHPI_ES_ON_LINE (SaHpiEventStateT)0x0008
+#define SAHPI_ES_OFF_LINE (SaHpiEventStateT)0x0010
+#define SAHPI_ES_OFF_DUTY (SaHpiEventStateT)0x0020
+#define SAHPI_ES_DEGRADED (SaHpiEventStateT)0x0040
+#define SAHPI_ES_POWER_SAVE (SaHpiEventStateT)0x0080
+#define SAHPI_ES_INSTALL_ERROR (SaHpiEventStateT)0x0100
+
+/* SaHpiEventCategoryT == SAHPI_EC_REDUNDANCY */
+#define SAHPI_ES_FULLY_REDUNDANT (SaHpiEventStateT)0x0001
+#define SAHPI_ES_REDUNDANCY_LOST (SaHpiEventStateT)0x0002
+#define SAHPI_ES_REDUNDANCY_DEGRADED (SaHpiEventStateT)0x0004
+#define SAHPI_ES_REDUNDANCY_LOST_SUFFICIENT_RESOURCES \
+ (SaHpiEventStateT)0x0008
+#define SAHPI_ES_NON_REDUNDANT_SUFFICIENT_RESOURCES \
+ (SaHpiEventStateT)0x0010
+#define SAHPI_ES_NON_REDUNDANT_INSUFFICIENT_RESOURCES \
+ (SaHpiEventStateT)0x0020
+#define SAHPI_ES_REDUNDANCY_DEGRADED_FROM_FULL (SaHpiEventStateT)0x0040
+#define SAHPI_ES_REDUNDANCY_DEGRADED_FROM_NON (SaHpiEventStateT)0x0080
+
+/*
+** SaHpiEventCategoryT == SAHPI_EC_GENERIC || SAHPI_EC_USER
+** These event states are defined by the OEM or the user of the
+** implementation.
+*/
+#define SAHPI_ES_STATE_00 (SaHpiEventStateT)0x0001
+#define SAHPI_ES_STATE_01 (SaHpiEventStateT)0x0002
+#define SAHPI_ES_STATE_02 (SaHpiEventStateT)0x0004
+#define SAHPI_ES_STATE_03 (SaHpiEventStateT)0x0008
+#define SAHPI_ES_STATE_04 (SaHpiEventStateT)0x0010
+#define SAHPI_ES_STATE_05 (SaHpiEventStateT)0x0020
+#define SAHPI_ES_STATE_06 (SaHpiEventStateT)0x0040
+#define SAHPI_ES_STATE_07 (SaHpiEventStateT)0x0080
+#define SAHPI_ES_STATE_08 (SaHpiEventStateT)0x0100
+#define SAHPI_ES_STATE_09 (SaHpiEventStateT)0x0200
+#define SAHPI_ES_STATE_10 (SaHpiEventStateT)0x0400
+#define SAHPI_ES_STATE_11 (SaHpiEventStateT)0x0800
+#define SAHPI_ES_STATE_12 (SaHpiEventStateT)0x1000
+#define SAHPI_ES_STATE_13 (SaHpiEventStateT)0x2000
+#define SAHPI_ES_STATE_14 (SaHpiEventStateT)0x4000
+
+
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Sensors **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* Sensor Number */
+typedef SaHpiUint8T SaHpiSensorNumT;
+
+/* Type of Sensor */
+typedef enum {
+ SAHPI_TEMPERATURE = 0x01,
+ SAHPI_VOLTAGE,
+ SAHPI_CURRENT,
+ SAHPI_FAN,
+ SAHPI_PHYSICAL_SECURITY,
+ SAHPI_PLATFORM_VIOLATION,
+ SAHPI_PROCESSOR,
+ SAHPI_POWER_SUPPLY,
+ SAHPI_POWER_UNIT,
+ SAHPI_COOLING_DEVICE,
+ SAHPI_OTHER_UNITS_BASED_SENSOR,
+ SAHPI_MEMORY,
+ SAHPI_DRIVE_SLOT,
+ SAHPI_POST_MEMORY_RESIZE,
+ SAHPI_SYSTEM_FW_PROGRESS,
+ SAHPI_EVENT_LOGGING_DISABLED,
+ SAHPI_RESERVED1,
+ SAHPI_SYSTEM_EVENT,
+ SAHPI_CRITICAL_INTERRUPT,
+ SAHPI_BUTTON,
+ SAHPI_MODULE_BOARD,
+ SAHPI_MICROCONTROLLER_COPROCESSOR,
+ SAHPI_ADDIN_CARD,
+ SAHPI_CHASSIS,
+ SAHPI_CHIP_SET,
+ SAHPI_OTHER_FRU,
+ SAHPI_CABLE_INTERCONNECT,
+ SAHPI_TERMINATOR,
+ SAHPI_SYSTEM_BOOT_INITIATED,
+ SAHPI_BOOT_ERROR,
+ SAHPI_OS_BOOT,
+ SAHPI_OS_CRITICAL_STOP,
+ SAHPI_SLOT_CONNECTOR,
+ SAHPI_SYSTEM_ACPI_POWER_STATE,
+ SAHPI_RESERVED2,
+ SAHPI_PLATFORM_ALERT,
+ SAHPI_ENTITY_PRESENCE,
+ SAHPI_MONITOR_ASIC_IC,
+ SAHPI_LAN,
+ SAHPI_MANAGEMENT_SUBSYSTEM_HEALTH,
+ SAHPI_BATTERY,
+ SAHPI_OPERATIONAL = 0xA0,
+ SAHPI_OEM_SENSOR=0xC0
+} SaHpiSensorTypeT;
+
+/*
+** Interpreted Sensor Reading Type
+**
+** These definitions list the available data types that can be
+** used for interpreted sensor readings. Interpreted sensor readings are provided
+** because typically sensors measure their associated entities in a way that is
+** not human readable/understandable. For example a fan sensor may measure the
+** number of ticks that it takes a fan blade to move passed a sensor. The human
+** readable reading type would be revolutions per minute (RPM).
+*/
+
+#define SAHPI_SENSOR_BUFFER_LENGTH 32
+
+typedef enum {
+ SAHPI_SENSOR_INTERPRETED_TYPE_UINT8,
+ SAHPI_SENSOR_INTERPRETED_TYPE_UINT16,
+ SAHPI_SENSOR_INTERPRETED_TYPE_UINT32,
+ SAHPI_SENSOR_INTERPRETED_TYPE_INT8,
+ SAHPI_SENSOR_INTERPRETED_TYPE_INT16,
+ SAHPI_SENSOR_INTERPRETED_TYPE_INT32,
+ SAHPI_SENSOR_INTERPRETED_TYPE_FLOAT32,
+ SAHPI_SENSOR_INTERPRETED_TYPE_BUFFER /* 32 byte array */
+} SaHpiSensorInterpretedTypeT;
+
+typedef union {
+ SaHpiUint8T SensorUint8;
+ SaHpiUint16T SensorUint16;
+ SaHpiUint32T SensorUint32;
+ SaHpiInt8T SensorInt8;
+ SaHpiInt16T SensorInt16;
+ SaHpiInt32T SensorInt32;
+ SaHpiFloat32T SensorFloat32;
+ SaHpiUint8T SensorBuffer[SAHPI_SENSOR_BUFFER_LENGTH];
+} SaHpiSensorInterpretedUnionT;
+
+typedef struct {
+ SaHpiSensorInterpretedTypeT Type;
+ SaHpiSensorInterpretedUnionT Value;
+} SaHpiSensorInterpretedT;
+
+/*
+** Sensor Status
+**
+** The sensor status structure is used to determine if sensor scanning is
+** enabled and if events are enabled. If events are enabled, the structure will
+** have valid data for the outstanding sensor event states.
+*/
+typedef SaHpiUint8T SaHpiSensorStatusT;
+#define SAHPI_SENSTAT_EVENTS_ENABLED (SaHpiSensorStatusT)0x80
+#define SAHPI_SENSTAT_SCAN_ENABLED (SaHpiSensorStatusT)0x40
+#define SAHPI_SENSTAT_BUSY (SaHpiSensorStatusT)0x20
+
+typedef struct {
+ SaHpiSensorStatusT SensorStatus;
+ SaHpiEventStateT EventStatus;
+} SaHpiSensorEvtStatusT;
+
+/* Sensor Event Enables */
+typedef struct {
+ SaHpiSensorStatusT SensorStatus;
+ SaHpiEventStateT AssertEvents;
+ SaHpiEventStateT DeassertEvents;
+} SaHpiSensorEvtEnablesT;
+
+/*
+** Sensor Reading
+**
+** The sensor reading type is the data structure returned from a call to get
+** sensor reading. The structure is also used when setting and getting sensor
+** threshold values and reporting sensor ranges.
+** Each sensor may support one or more of raw, interpreted, or event status
+** representations of the sensor data. For analog sensors the raw value is the
+** raw value from the sensor (such as ticks per fan blade) and the interpreted
+** value is the raw value converted in to a usable format (such as RPM). The
+** interpreted value can be calculated by the HPI implementation using the
+** sensor factors or by another OEM means.
+*/
+typedef SaHpiUint8T SaHpiSensorReadingFormatsT;
+#define SAHPI_SRF_RAW (SaHpiSensorReadingFormatsT)0x01
+#define SAHPI_SRF_INTERPRETED (SaHpiSensorReadingFormatsT)0x02
+#define SAHPI_SRF_EVENT_STATE (SaHpiSensorReadingFormatsT)0x04
+
+typedef struct {
+ SaHpiSensorReadingFormatsT ValuesPresent;
+ SaHpiUint32T Raw;
+ SaHpiSensorInterpretedT Interpreted;
+ SaHpiSensorEvtStatusT EventStatus;
+} SaHpiSensorReadingT;
+
+/*
+** Threshold Values
+** This structure encompasses all of the thresholds that can be set.
+*/
+typedef struct {
+ SaHpiSensorReadingT LowCritical; /* Lower Critical Threshold */
+ SaHpiSensorReadingT LowMajor; /* Lower Major Threshold */
+ SaHpiSensorReadingT LowMinor; /* Lower Minor Threshold */
+ SaHpiSensorReadingT UpCritical; /* Upper critical Threshold */
+ SaHpiSensorReadingT UpMajor; /* Upper major Threshold */
+ SaHpiSensorReadingT UpMinor; /* Upper minor Threshold */
+ SaHpiSensorReadingT PosThdHysteresis; /* Positive Threshold Hysteresis */
+ SaHpiSensorReadingT NegThdHysteresis; /* Negative Threshold Hysteresis */
+}SaHpiSensorThresholdsT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Sensor Resource Data Records **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** Sensor Factors
+**
+** The sensor factors structure defines the conversion factors for linear and
+** linearized sensors.
+** The SaHpiSensorLinearizationT enumeration coupled with the various other
+** sensor factors define a formula that can be applied to raw sensor data to
+** convert it to appropriate engineering units. If linearization is
+** SAHPI_SL_NONLINEAR, SAHPI_SL_UNSPECIFIED, or SAHPI_SL_OEM then there is no
+** predefined conversion from raw to interpreted and the sensor factors may or
+** may not be meaningful depending on the implementation.
+** For other linearization values, raw readings may be converted to interpreted
+** values using the formula:
+**Interpreted = L [( M*raw + B*10^ExpB )*10^ExpR ]
+**where "L[x]" is the indicated linearization function
+** (for SAHPI_SL_LINEAR, L[x]=x).
+** The Tolerance Factor is given as +/- 1/2 raw counts, so tolerance in
+** interpreted values can be calculated as:
+** L[ M * ToleranceFactor/2 * 10^ExpR ]
+** The Accuracy Factor is given as 1/100 of a percent, scaled up by ExpA. Thus
+** the accuracy is:
+**( ( AccuracyFactor/100 ) / 10^ExpA )%
+*/
+typedef enum {
+ SAHPI_SL_LINEAR = 0, /* Already linear */
+ SAHPI_SL_LN,
+ SAHPI_SL_LOG10,
+ SAHPI_SL_LOG2,
+ SAHPI_SL_E,
+ SAHPI_SL_EXP10,
+ SAHPI_SL_EXP2,
+ SAHPI_SL_1OVERX,
+ SAHPI_SL_SQRX,
+ SAHPI_SL_CUBEX,
+ SAHPI_SL_SQRTX,
+ SAHPI_SL_CUBERTX,
+ SAHPI_SL_NONLINEAR = 0x70, /* Cannot be linearized with a predefind formula*/
+ SAHPI_SL_OEM,
+ SAHPI_SL_UNSPECIFIED = 0xFF
+} SaHpiSensorLinearizationT;
+
+typedef struct {
+ SaHpiInt16T M_Factor; /* M Factor */
+ SaHpiInt16T B_Factor; /* B Factor */
+ SaHpiUint16T AccuracyFactor; /* Accuracy */
+ SaHpiUint8T ToleranceFactor; /* Tolerance */
+ SaHpiUint8T ExpA; /* Accuracy Exp */
+ SaHpiInt8T ExpR; /* Result Exp */
+ SaHpiInt8T ExpB; /* B Exp */
+ SaHpiSensorLinearizationT Linearization;
+} SaHpiSensorFactorsT;
+
+/*
+** Sensor Range
+** Sensor range values can include minimum, maximum, normal minimum, normal
+** maximum, and nominal values.
+*/
+typedef SaHpiUint8T SaHpiSensorRangeFlagsT;
+#define SAHPI_SRF_MIN (SaHpiSensorRangeFlagsT)0x10
+#define SAHPI_SRF_MAX (SaHpiSensorRangeFlagsT)0x08
+#define SAHPI_SRF_NORMAL_MIN (SaHpiSensorRangeFlagsT)0x04
+#define SAHPI_SRF_NORMAL_MAX (SaHpiSensorRangeFlagsT)0x02
+#define SAHPI_SRF_NOMINAL (SaHpiSensorRangeFlagsT)0x01
+
+typedef struct {
+ SaHpiSensorRangeFlagsT Flags;
+ SaHpiSensorReadingT Max;
+ SaHpiSensorReadingT Min;
+ SaHpiSensorReadingT Nominal;
+ SaHpiSensorReadingT NormalMax;
+ SaHpiSensorReadingT NormalMin;
+} SaHpiSensorRangeT;
+
+/*
+** Sensor Units
+** This is a list of all the sensor units supported by HPI.
+*/
+typedef enum {
+ SAHPI_SU_UNSPECIFIED = 0, SAHPI_SU_DEGREES_C, SAHPI_SU_DEGREES_F,
+ SAHPI_SU_DEGREES_K, SAHPI_SU_VOLTS, SAHPI_SU_AMPS,
+ SAHPI_SU_WATTS, SAHPI_SU_JOULES, SAHPI_SU_COULOMBS,
+ SAHPI_SU_VA, SAHPI_SU_NITS, SAHPI_SU_LUMEN,
+ SAHPI_SU_LUX, SAHPI_SU_CANDELA, SAHPI_SU_KPA,
+ SAHPI_SU_PSI, SAHPI_SU_NEWTON, SAHPI_SU_CFM,
+ SAHPI_SU_RPM, SAHPI_SU_HZ, SAHPI_SU_MICROSECOND,
+ SAHPI_SU_MILLISECOND, SAHPI_SU_SECOND, SAHPI_SU_MINUTE,
+ SAHPI_SU_HOUR, SAHPI_SU_DAY, SAHPI_SU_WEEK,
+ SAHPI_SU_MIL, SAHPI_SU_INCHES, SAHPI_SU_FEET,
+ SAHPI_SU_CU_IN, SAHPI_SU_CU_FEET, SAHPI_SU_MM,
+ SAHPI_SU_CM, SAHPI_SU_M, SAHPI_SU_CU_CM,
+ SAHPI_SU_CU_M, SAHPI_SU_LITERS, SAHPI_SU_FLUID_OUNCE,
+ SAHPI_SU_RADIANS, SAHPI_SU_STERADIANS, SAHPI_SU_REVOLUTIONS,
+ SAHPI_SU_CYCLES, SAHPI_SU_GRAVITIES, SAHPI_SU_OUNCE,
+ SAHPI_SU_POUND, SAHPI_SU_FT_LB, SAHPI_SU_OZ_IN,
+ SAHPI_SU_GAUSS, SAHPI_SU_GILBERTS, SAHPI_SU_HENRY,
+ SAHPI_SU_MILLIHENRY, SAHPI_SU_FARAD, SAHPI_SU_MICROFARAD,
+ SAHPI_SU_OHMS, SAHPI_SU_SIEMENS, SAHPI_SU_MOLE,
+ SAHPI_SU_BECQUEREL, SAHPI_SU_PPM, SAHPI_SU_RESERVED,
+ SAHPI_SU_DECIBELS, SAHPI_SU_DBA, SAHPI_SU_DBC,
+ SAHPI_SU_GRAY, SAHPI_SU_SIEVERT, SAHPI_SU_COLOR_TEMP_DEG_K,
+ SAHPI_SU_BIT, SAHPI_SU_KILOBIT, SAHPI_SU_MEGABIT,
+ SAHPI_SU_GIGABIT, SAHPI_SU_BYTE, SAHPI_SU_KILOBYTE,
+ SAHPI_SU_MEGABYTE, SAHPI_SU_GIGABYTE, SAHPI_SU_WORD,
+ SAHPI_SU_DWORD, SAHPI_SU_QWORD, SAHPI_SU_LINE,
+ SAHPI_SU_HIT, SAHPI_SU_MISS, SAHPI_SU_RETRY,
+ SAHPI_SU_RESET, SAHPI_SU_OVERRUN, SAHPI_SU_UNDERRUN,
+ SAHPI_SU_COLLISION, SAHPI_SU_PACKETS, SAHPI_SU_MESSAGES,
+ SAHPI_SU_CHARACTERS, SAHPI_SU_ERRORS, SAHPI_SU_CORRECTABLE_ERRORS,
+ SAHPI_SU_UNCORRECTABLE_ERRORS
+} SaHpiSensorUnitsT;
+
+/*
+** Modifier Unit Use
+** This type defines how the modifier unit is used. For example: base unit ==
+** meter, modifier unit == seconds, and modifier unit use ==
+** SAHPI_SMUU_BASIC_OVER_MODIFIER. The resulting unit would be meters per second.
+*/
+typedef enum {
+ SAHPI_SMUU_NONE = 0,
+ SAHPI_SMUU_BASIC_OVER_MODIFIER, /* Basic Unit / Modifier Unit */
+ SAHPI_SMUU_BASIC_TIMES_MODIFIER /* Basic Unit * Modifier Unit */
+} SaHpiSensorModUnitUseT;
+
+/*
+** Sign Format
+** This type defines what the sign format of the sensor's raw value is (1's
+** complement, unsigned, etc.).
+*/
+typedef enum {
+ SAHPI_SDF_UNSIGNED = 0,
+ SAHPI_SDF_1S_COMPLEMENT,
+ SAHPI_SDF_2S_COMPLEMENT
+} SaHpiSensorSignFormatT;
+
+/*
+** Data Format
+** This structure encapsulates all of the various types that make up the
+** definition of sensor data.
+*/
+typedef struct {
+ SaHpiSensorReadingFormatsT ReadingFormats; /* Indicates if sensor supports
+ readings in raw, interpreted,
+ and/or event status formats */
+ SaHpiBoolT IsNumeric; /* If FALSE, rest of this
+ structure is not
+ meaningful */
+ SaHpiSensorSignFormatT SignFormat; /* Signed format */
+ SaHpiSensorUnitsT BaseUnits; /* Base units (meters, etc.) */
+ SaHpiSensorUnitsT ModifierUnits; /* Modifier unit (second, etc.) */
+ SaHpiSensorModUnitUseT ModifierUse; /* Modifier use(m/sec, etc.) */
+ SaHpiBoolT FactorsStatic; /* True if the sensor factors
+ are static. If false
+ factors vary over sensor
+ range, and are not
+ accessible through HPI */
+ SaHpiSensorFactorsT Factors;
+ SaHpiBoolT Percentage; /* Is value a percentage */
+ SaHpiSensorRangeT Range; /* Valid range of sensor */
+} SaHpiSensorDataFormatT;
+
+/*
+** Threshold Support
+**
+** These types define what threshold values are readable, writable, and fixed.
+** It also defines how the threshold values are read and written.
+*/
+typedef SaHpiUint8T SaHpiSensorThdMaskT;
+#define SAHPI_STM_LOW_MINOR (SaHpiSensorThdMaskT)0x01
+#define SAHPI_STM_LOW_MAJOR (SaHpiSensorThdMaskT)0x02
+#define SAHPI_STM_LOW_CRIT (SaHpiSensorThdMaskT)0x04
+#define SAHPI_STM_UP_MINOR (SaHpiSensorThdMaskT)0x08
+#define SAHPI_STM_UP_MAJOR (SaHpiSensorThdMaskT)0x10
+#define SAHPI_STM_UP_CRIT (SaHpiSensorThdMaskT)0x20
+#define SAHPI_STM_UP_HYSTERESIS (SaHpiSensorThdMaskT)0x40
+#define SAHPI_STM_LOW_HYSTERESIS (SaHpiSensorThdMaskT)0x80
+
+typedef SaHpiUint8T SaHpiSensorThdCapT;
+#define SAHPI_STC_RAW (SaHpiSensorThdMaskT)0x01 /* read/write as
+ raw counts */
+#define SAHPI_STC_INTERPRETED (SaHpiSensorThdMaskT)0x02 /* read/write as
+ interpreted */
+
+typedef struct {
+ SaHpiBoolT IsThreshold; /* True if the sensor
+ supports thresholds. If false,
+ rest of structure is not
+ meaningful. */
+ SaHpiSensorThdCapT TholdCapabilities;
+ SaHpiSensorThdMaskT ReadThold; /* Readable thresholds */
+ SaHpiSensorThdMaskT WriteThold; /* Writable thresholds */
+ SaHpiSensorThdMaskT FixedThold; /* Fixed thresholds */
+} SaHpiSensorThdDefnT;
+
+/*
+** Event Control
+**
+** This type defines how sensor event messages can be controlled (can be turned
+** off and on for each type of event, etc.).
+*/
+typedef enum {
+ SAHPI_SEC_PER_EVENT = 0, /* Event message control per event */
+ SAHPI_SEC_ENTIRE_SENSOR, /* Control for entire sensor only */
+ SAHPI_SEC_GLOBAL_DISABLE, /* Global disable of events only */
+ SAHPI_SEC_NO_EVENTS /* Events not supported */
+} SaHpiSensorEventCtrlT;
+
+/*
+** Record
+**
+** This is the sensor resource data record which describes all of the static
+** data associated with a sensor.
+*/
+typedef struct {
+ SaHpiSensorNumT Num; /* Sensor Number/Index */
+ SaHpiSensorTypeT Type; /* General Sensor Type */
+ SaHpiEventCategoryT Category; /* Event category */
+ SaHpiSensorEventCtrlT EventCtrl; /* How events can be controlled */
+ SaHpiEventStateT Events; /* Bit mask of event states
+ supported */
+ SaHpiBoolT Ignore; /* Ignore sensor (entity not
+ present, disabled, etc.) */
+ SaHpiSensorDataFormatT DataFormat; /* Format of the data */
+ SaHpiSensorThdDefnT ThresholdDefn; /* Threshold Definition */
+ SaHpiUint32T Oem; /* Reserved for OEM use */
+} SaHpiSensorRecT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Aggregate Status **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* These are the default sensor numbers for aggregate status. */
+#define SAHPI_DEFAGSENS_OPER (SaHpiSensorNumT)0xFE
+#define SAHPI_DEFAGSENS_PWR (SaHpiSensorNumT)0xFD
+#define SAHPI_DEFAGSENS_TEMP (SaHpiSensorNumT)0xFC
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Controls **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* Control Number */
+typedef SaHpiUint8T SaHpiCtrlNumT;
+
+/*
+** Type of Control
+**
+** This enumerated type defines the different types of generic controls.
+*/
+typedef enum {
+ SAHPI_CTRL_TYPE_DIGITAL = 0x00,
+ SAHPI_CTRL_TYPE_DISCRETE,
+ SAHPI_CTRL_TYPE_ANALOG,
+ SAHPI_CTRL_TYPE_STREAM,
+ SAHPI_CTRL_TYPE_TEXT,
+ SAHPI_CTRL_TYPE_OEM = 0xC0
+} SaHpiCtrlTypeT;
+
+/*
+** Control State Type Definitions
+**
+** Defines the types of control states.
+*/
+typedef enum {
+ SAHPI_CTRL_STATE_OFF = 0,
+ SAHPI_CTRL_STATE_ON,
+ SAHPI_CTRL_STATE_PULSE_OFF,
+ SAHPI_CTRL_STATE_PULSE_ON,
+ SAHPI_CTRL_STATE_AUTO = 0xFF
+} SaHpiCtrlStateDigitalT;
+
+typedef SaHpiUint32T SaHpiCtrlStateDiscreteT;
+
+typedef SaHpiInt32T SaHpiCtrlStateAnalogT;
+
+#define SAHPI_CTRL_MAX_STREAM_LENGTH 4
+typedef struct {
+ SaHpiBoolT Repeat; /* Repeat flag */
+ SaHpiUint32T StreamLength; /* Length of the data, in bytes,
+ ** stored in the stream. */
+ SaHpiUint8T Stream[SAHPI_CTRL_MAX_STREAM_LENGTH];
+} SaHpiCtrlStateStreamT;
+
+typedef SaHpiUint8T SaHpiTxtLineNumT;
+
+/* Reserved number for sending output to all lines */
+#define SAHPI_TLN_ALL_LINES (SaHpiTxtLineNumT)0xFF
+
+typedef struct {
+ SaHpiTxtLineNumT Line; /* Operate on line # */
+ SaHpiTextBufferT Text; /* Text to display */
+} SaHpiCtrlStateTextT;
+
+#define SAHPI_CTRL_MAX_OEM_BODY_LENGTH 255
+typedef struct {
+ SaHpiManufacturerIdT MId;
+ SaHpiUint8T BodyLength;
+ SaHpiUint8T Body[SAHPI_CTRL_MAX_OEM_BODY_LENGTH]; /* OEM Specific */
+} SaHpiCtrlStateOemT;
+
+typedef union {
+ SaHpiCtrlStateDigitalT Digital;
+ SaHpiCtrlStateDiscreteT Discrete;
+ SaHpiCtrlStateAnalogT Analog;
+ SaHpiCtrlStateStreamT Stream;
+ SaHpiCtrlStateTextT Text;
+ SaHpiCtrlStateOemT Oem;
+} SaHpiCtrlStateUnionT;
+
+typedef struct {
+ SaHpiCtrlTypeT Type; /* Type of control */
+ SaHpiCtrlStateUnionT StateUnion; /* Data for control type */
+} SaHpiCtrlStateT;
+
+
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Control Resource Data Records **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** Output Type
+**
+** This enumeration defines the what the control's output will be.
+*/
+typedef enum {
+ SAHPI_CTRL_GENERIC = 0,
+ SAHPI_CTRL_LED,
+ SAHPI_CTRL_FAN_SPEED,
+ SAHPI_CTRL_DRY_CONTACT_CLOSURE,
+ SAHPI_CTRL_POWER_SUPPLY_INHIBIT,
+ SAHPI_CTRL_AUDIBLE,
+ SAHPI_CTRL_FRONT_PANEL_LOCKOUT,
+ SAHPI_CTRL_POWER_INTERLOCK,
+ SAHPI_CTRL_POWER_STATE,
+ SAHPI_CTRL_LCD_DISPLAY,
+ SAHPI_CTRL_OEM
+} SaHpiCtrlOutputTypeT;
+
+/*
+** Specific Record Types
+** These types represent the specific types of control resource data records.
+*/
+typedef struct {
+ SaHpiCtrlStateDigitalT Default;
+} SaHpiCtrlRecDigitalT;
+
+typedef struct {
+ SaHpiCtrlStateDiscreteT Default;
+} SaHpiCtrlRecDiscreteT;
+
+typedef struct {
+ SaHpiCtrlStateAnalogT Min; /* Minimum Value */
+ SaHpiCtrlStateAnalogT Max; /* Maximum Value */
+ SaHpiCtrlStateAnalogT Default;
+} SaHpiCtrlRecAnalogT;
+
+typedef struct {
+ SaHpiCtrlStateStreamT Default;
+} SaHpiCtrlRecStreamT;
+
+typedef struct {
+ SaHpiUint8T MaxChars; /* Maximum chars per line */
+ SaHpiUint8T MaxLines; /* Maximum # of lines */
+ SaHpiLanguageT Language; /* Language Code */
+ SaHpiTextTypeT DataType; /* Permitted Data */
+ SaHpiCtrlStateTextT Default;
+} SaHpiCtrlRecTextT;
+
+#define SAHPI_CTRL_OEM_CONFIG_LENGTH 10
+typedef struct {
+ SaHpiManufacturerIdT MId;
+ SaHpiUint8T ConfigData[SAHPI_CTRL_OEM_CONFIG_LENGTH];
+ SaHpiCtrlStateOemT Default;
+} SaHpiCtrlRecOemT;
+
+typedef union {
+ SaHpiCtrlRecDigitalT Digital;
+ SaHpiCtrlRecDiscreteT Discrete;
+ SaHpiCtrlRecAnalogT Analog;
+ SaHpiCtrlRecStreamT Stream;
+ SaHpiCtrlRecTextT Text;
+ SaHpiCtrlRecOemT Oem;
+} SaHpiCtrlRecUnionT;
+
+/*
+** Record Definition
+** Definition of the control resource data record.
+*/
+typedef struct {
+ SaHpiCtrlNumT Num; /* Control Number/Index */
+ SaHpiBoolT Ignore; /* Ignore control (entity
+ not present, disabled, etc.) */
+ SaHpiCtrlOutputTypeT OutputType;
+ SaHpiCtrlTypeT Type; /* Type of control */
+ SaHpiCtrlRecUnionT TypeUnion; /* Specific control record */
+ SaHpiUint32T Oem; /* Reserved for OEM use */
+} SaHpiCtrlRecT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Entity Inventory Data **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+/*
+** These structures are used to read and write inventory data to entity inventory
+** repositories within a resource.
+*/
+/*
+** Entity Inventory Repository ID
+** Identifier for an entity inventory repository.
+*/
+typedef SaHpiUint8T SaHpiEirIdT;
+#define SAHPI_DEFAULT_INVENTORY_ID (SaHpiEirIdT)0x00
+
+/* Data Validity */
+typedef enum {
+ SAHPI_INVENT_DATA_VALID,
+ SAHPI_INVENT_DATA_INVALID,
+ SAHPI_INVENT_DATA_OVERFLOW
+} SaHpiInventDataValidityT;
+
+/* Inventory Record definitions */
+typedef enum {
+ SAHPI_INVENT_RECTYPE_INTERNAL_USE = 0xB0,
+ SAHPI_INVENT_RECTYPE_CHASSIS_INFO,
+ SAHPI_INVENT_RECTYPE_BOARD_INFO,
+ SAHPI_INVENT_RECTYPE_PRODUCT_INFO,
+ SAHPI_INVENT_RECTYPE_OEM = 0xC0
+} SaHpiInventDataRecordTypeT;
+
+typedef enum {
+ SAHPI_INVENT_CTYP_OTHER = 1,
+ SAHPI_INVENT_CTYP_UNKNOWN,
+ SAHPI_INVENT_CTYP_DESKTOP,
+ SAHPI_INVENT_CTYP_LOW_PROFILE_DESKTOP,
+ SAHPI_INVENT_CTYP_PIZZA_BOX,
+ SAHPI_INVENT_CTYP_MINI_TOWER,
+ SAHPI_INVENT_CTYP_TOWER,
+ SAHPI_INVENT_CTYP_PORTABLE,
+ SAHPI_INVENT_CTYP_LAPTOP,
+ SAHPI_INVENT_CTYP_NOTEBOOK,
+ SAHPI_INVENT_CTYP_HANDHELD,
+ SAHPI_INVENT_CTYP_DOCKING_STATION,
+ SAHPI_INVENT_CTYP_ALLINONE,
+ SAHPI_INVENT_CTYP_SUBNOTEBOOK,
+ SAHPI_INVENT_CTYP_SPACE_SAVING,
+ SAHPI_INVENT_CTYP_LUNCH_BOX,
+ SAHPI_INVENT_CTYP_MAIN_SERVER,
+ SAHPI_INVENT_CTYP_EXPANSION,
+ SAHPI_INVENT_CTYP_SUBCHASSIS,
+ SAHPI_INVENT_CTYP_BUS_EXPANSION_CHASSIS,
+ SAHPI_INVENT_CTYP_PERIPHERAL_CHASSIS,
+ SAHPI_INVENT_CTYP_RAID_CHASSIS,
+ SAHPI_INVENT_CTYP_RACKMOUNT
+} SaHpiInventChassisTypeT;
+
+typedef struct {
+ SaHpiUint8T Data[1]; /* Variable length opaque data */
+} SaHpiInventInternalUseDataT;
+
+typedef struct {
+ SaHpiTimeT MfgDateTime; /* May be set to
+ SAHPI_TIME_UNSPECIFIED
+ if manufacturing
+ date/time not available */
+ SaHpiTextBufferT *Manufacturer;
+ SaHpiTextBufferT *ProductName;
+ SaHpiTextBufferT *ProductVersion;
+ SaHpiTextBufferT *ModelNumber;
+ SaHpiTextBufferT *SerialNumber;
+ SaHpiTextBufferT *PartNumber;
+ SaHpiTextBufferT *FileId;
+ SaHpiTextBufferT *AssetTag;
+ SaHpiTextBufferT *CustomField[1]; /* Variable number of fields,
+ last is NULL */
+} SaHpiInventGeneralDataT;
+
+typedef struct {
+ SaHpiInventChassisTypeT Type; /* Type of chassis */
+ SaHpiInventGeneralDataT GeneralData;
+} SaHpiInventChassisDataT;
+
+typedef struct {
+ SaHpiManufacturerIdT MId;/* OEM Manuf. ID */
+ SaHpiUint8T Data[1]; /* Variable length data, defined by OEM,
+ Length derived from DataLength in
+ SaHpiInventDataRecordT structure:
+ DataLength - 4(because DataLength
+ includes the MId) */
+} SaHpiInventOemDataT;
+
+typedef union {
+ SaHpiInventInternalUseDataT InternalUse;
+ SaHpiInventChassisDataT ChassisInfo;
+ SaHpiInventGeneralDataT BoardInfo;
+ SaHpiInventGeneralDataT ProductInfo;
+ SaHpiInventOemDataT OemData;
+} SaHpiInventDataUnionT;
+
+typedef struct {
+ SaHpiInventDataRecordTypeT RecordType;
+ SaHpiUint32T DataLength; /* Length of Data field for
+ this record */
+ SaHpiInventDataUnionT RecordData; /* Variable length data */
+} SaHpiInventDataRecordT;
+
+typedef struct {
+ SaHpiInventDataValidityT Validity; /* Indication as to whether data
+ Returned by
+ saHpiEntityInventoryDataRead() is
+ complete and valid. Unless this
+ flag indicates valid data,
+ saHpiEntityInventoryDataWrite() will
+ not take any actions except to
+ return an error.*/
+ SaHpiInventDataRecordT *DataRecords[1]; /* Array of pointers to inventory
+ Data Records. Variable
+ number of entries. Last
+ entry is NULL. */
+} SaHpiInventoryDataT;
+
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Inventory Resource Data Records **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** All inventory data contained in an entity inventory repository
+** must be represented in the RDR repository
+** with an SaHpiInventoryRecT.
+*/
+typedef struct {
+ SaHpiEirIdT EirId;
+ SaHpiUint32T Oem;
+} SaHpiInventoryRecT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Watchdogs **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** This section defines all of the data types associated with watchdog timers.
+*/
+
+/* Watchdog Number - Identifier for a watchdog timer. */
+typedef SaHpiUint8T SaHpiWatchdogNumT;
+#define SAHPI_DEFAULT_WATCHDOG_NUM (SaHpiWatchdogNumT)0x00
+
+/*
+** Watchdog Timer Action
+**
+** These enumerations represent the possible actions to be taken upon watchdog
+** timer timeout and the events that are generated for watchdog actions.
+*/
+typedef enum {
+ SAHPI_WA_NO_ACTION = 0,
+ SAHPI_WA_RESET,
+ SAHPI_WA_POWER_DOWN,
+ SAHPI_WA_POWER_CYCLE
+} SaHpiWatchdogActionT;
+
+typedef enum {
+ SAHPI_WAE_NO_ACTION = 0,
+ SAHPI_WAE_RESET,
+ SAHPI_WAE_POWER_DOWN,
+ SAHPI_WAE_POWER_CYCLE,
+ SAHPI_WAE_TIMER_INT=0x08 /* Used if Timer Preinterrupt only */
+} SaHpiWatchdogActionEventT;
+
+/*
+** Watchdog Pre-timer Interrupt
+**
+** These enumerations represent the possible types of interrupts that may be
+** triggered by a watchdog pre-timer event. The actual meaning of these
+** operations may differ depending on the hardware architecture.
+*/
+typedef enum {
+ SAHPI_WPI_NONE = 0,
+ SAHPI_WPI_SMI,
+ SAHPI_WPI_NMI,
+ SAHPI_WPI_MESSAGE_INTERRUPT,
+ SAHPI_WPI_OEM = 0x0F
+} SaHpiWatchdogPretimerInterruptT;
+
+/*
+** Watchdog Timer Use
+**
+** These enumerations represent the possible watchdog users that may have caused
+** the watchdog to expire. For instance, if watchdog is being used during power
+** on self test (POST), and it expires, the SAHPI_WTU_BIOS_POST expiration type
+** will be set. Most specific uses for Watchdog timer by users of HPI should
+** indicate SAHPI_WTU_SMS_OS if the use is to provide an OS-healthy heartbeat,
+** or SAHPI_WTU_OEM if it is used for some other purpose.
+*/
+typedef enum {
+ SAHPI_WTU_NONE = 0,
+ SAHPI_WTU_BIOS_FRB2,
+ SAHPI_WTU_BIOS_POST,
+ SAHPI_WTU_OS_LOAD,
+ SAHPI_WTU_SMS_OS, /* System Management System providing
+ heartbeat for OS */
+ SAHPI_WTU_OEM,
+ SAHPI_WTU_UNSPECIFIED = 0x0F
+} SaHpiWatchdogTimerUseT;
+
+/*
+** Timer Use Expiration Flags
+** These values are used for the Watchdog Timer Use Expiration flags in the
+** SaHpiWatchdogT structure.
+*/
+typedef SaHpiUint8T SaHpiWatchdogExpFlagsT;
+#define SAHPI_WATCHDOG_EXP_BIOS_FRB2 (SaHpiWatchdogExpFlagsT)0x02
+#define SAHPI_WATCHDOG_EXP_BIOS_POST (SaHpiWatchdogExpFlagsT)0x04
+#define SAHPI_WATCHDOG_EXP_OS_LOAD (SaHpiWatchdogExpFlagsT)0x08
+#define SAHPI_WATCHDOG_EXP_SMS_OS (SaHpiWatchdogExpFlagsT)0x10
+#define SAHPI_WATCHDOG_EXP_OEM (SaHpiWatchdogExpFlagsT)0x20
+
+/*
+** Watchdog Structure
+**
+** This structure is used by the saHpiWatchdogTimerGet() and
+** saHpiWatchdogTimerSet() functions. The use of the structure varies slightly by
+** each function.
+**
+** For saHpiWatchdogTimerGet() :
+**
+** Log - indicates whether or not the Watchdog is configured to
+** issue an event when it next times out. TRUE=event will
+** be issued on timeout.
+** Running - indicates whether or not the Watchdog is currently
+** running or stopped. TRUE=Watchdog is running.
+** TimerUse - indicates the current use of the timer; one of five
+** preset uses which was included on the last
+** saHpiWatchdogTimerSet() function call, or through some
+** other implementation-dependent means to start the
+** Watchdog timer.
+** TimerAction - indicates what action will be taken when the Watchdog
+** times out.
+** PretimerInterrupt - indicates which action will be taken
+** "PreTimeoutInterval" seconds prior to Watchdog timer
+** expiration.
+** PreTimeoutInterval - indicates how many milliseconds prior to timer time
+** out the PretimerInterrupt action will be taken. If
+** "PreTimeoutInterval" = 0, the PretimerInterrupt action
+** will occur concurrently with "TimerAction." HPI
+** implementations may not be able to support millisecond
+** resolution and may have a maximum value restriction.
+** These restrictions should be documented by the
+** provider of the HPI interface.
+** TimerUseExpFlags - set of five bit flags which indicate that a Watchdog
+** timer timeout has occurred while the corresponding
+** TimerUse value was set. Once set, these flags stay
+** set until specifically cleared with a
+** saHpiWatchdogTimerSet() call, or by some other
+** implementation-dependent means.
+** InitialCount - The time, in milliseconds, before the timer will time
+** out after a saHpiWatchdogTimerReset() function call is
+** made, or some other implementation-dependent strobe is
+** sent to the Watchdog. HPI implementations may not be
+** able to support millisecond resolution and may have a
+** maximum value restriction. These restrictions should
+** be documented by the provider of the HPI interface.
+** PresentCount - The remaining time in milliseconds before the timer
+** will time out unless a saHpiWatchdogTimerReset()
+** function call is made, or some other implementation-
+** dependent strobe is sent to the Watchdog.
+** HPI implementations may not be able to support
+** millisecond resolution on watchdog timers, but will
+** return the number of clock ticks remaining times the
+** number of milliseconds between each tick.
+**
+** For saHpiWatchdogTimerSet():
+**
+** Log - indicates whether or not the Watchdog should issue
+** an event when it next times out. TRUE=event will be
+** issued on timeout.
+** Running - indicates whether or not the Watchdog should be
+** stopped before updating.
+** TRUE = Watchdog is not stopped. If it is already
+** stopped, it will remain stopped, but if it is
+** running, it will continue to run, with the
+** countdown timer reset to the new InitialCount.
+** Note that there is a race condition possible
+** with this setting, so it should be used with
+** care.
+** FALSE = Watchdog is stopped. After
+** saHpiWatchdogTimerSet() is called, a subsequent
+** call to saHpiWatchdogTimerReset() is required to
+** start the timer.
+** TimerUse - indicates the current use of the timer. Will control
+** which TimerUseExpFlag is set if the timer expires.
+** TimerAction - indicates what action will be taken when the Watchdog
+** times out.
+** PretimerInterrupt - indicates which action will be taken
+** "PreTimeoutInterval" seconds prior to Watchdog timer
+** expiration.
+** PreTimeoutInterval - indicates how many milliseconds prior to timer time
+** out the PretimerInterrupt action will be taken. If
+** "PreTimeoutInterval" = 0, the PretimerInterrupt action
+** will occur concurrently with "TimerAction." HPI
+** implementations may not be able to support millisecond
+** resolution and may have a maximum value restriction.
+** These restrictions should be documented by the
+** provider of the HPI interface.
+** TimerUseExpFlags - Set of five bit flags corresponding to the five
+** TimerUse values. For each bit set, the corresponding
+** Timer Use Expiration Flag will be CLEARED. Generally,
+** a program should only clear the Timer Use Expiration
+** Flag corresponding to its own TimerUse, so that other
+** software, which may have used the timer for another
+** purpose in the past can still read its TimerUseExpFlag
+** to determine whether or not the timer expired during
+** that use.
+** InitialCount - The time, in milliseconds, before the timer will time
+** out after a saHpiWatchdogTimerReset() function call is
+** made, or some other implementation-dependent strobe is
+** sent to the Watchdog. HPI implementations may not be
+** able to support millisecond resolution and may have a
+** maximum value restriction. These restrictions should
+** be documented by the provider of the HPI interface.
+** PresentCount - Not used on saHpiWatchdogTimerSet() function. Ignored.
+**
+*/
+
+typedef struct {
+ SaHpiBoolT Log;
+ SaHpiBoolT Running;
+ SaHpiWatchdogTimerUseT TimerUse;
+ SaHpiWatchdogActionT TimerAction;
+ SaHpiWatchdogPretimerInterruptT PretimerInterrupt;
+ SaHpiUint32T PreTimeoutInterval;
+ SaHpiWatchdogExpFlagsT TimerUseExpFlags;
+ SaHpiUint32T InitialCount;
+ SaHpiUint32T PresentCount;
+} SaHpiWatchdogT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Watchdog Resource Data Records **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** When the "Watchdog" capability is set in a resource, a watchdog with an
+** identifier of SAHPI_DEFAULT_WATCHDOG_NUM is required. All watchdogs must be
+** represented in the RDR repository with an SaHpiWatchdogRecT, including the
+** watchdog with an identifier of SAHPI_DEFAULT_WATCHDOG_NUM.
+*/
+typedef struct {
+ SaHpiWatchdogNumT WatchdogNum;
+ SaHpiUint32T Oem;
+} SaHpiWatchdogRecT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Resource Data Record **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** The following describes the different types of records that exist within a
+** RDR repository and the RDR super-structure to all of the specific RDR types
+** (sensor, inventory data, watchdog, etc.).
+*/
+typedef enum {
+ SAHPI_NO_RECORD,
+ SAHPI_CTRL_RDR,
+ SAHPI_SENSOR_RDR,
+ SAHPI_INVENTORY_RDR,
+ SAHPI_WATCHDOG_RDR
+} SaHpiRdrTypeT;
+
+typedef union {
+ SaHpiCtrlRecT CtrlRec;
+ SaHpiSensorRecT SensorRec;
+ SaHpiInventoryRecT InventoryRec;
+ SaHpiWatchdogRecT WatchdogRec;
+} SaHpiRdrTypeUnionT;
+
+typedef struct {
+ SaHpiEntryIdT RecordId;
+ SaHpiRdrTypeT RdrType;
+ SaHpiEntityPathT Entity; /* Entity to which this RDR relates. */
+ SaHpiRdrTypeUnionT RdrTypeUnion;
+ SaHpiTextBufferT IdString;
+} SaHpiRdrT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Hot Swap **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* Power State */
+typedef enum {
+ SAHPI_HS_POWER_OFF = 0,
+ SAHPI_HS_POWER_ON,
+ SAHPI_HS_POWER_CYCLE
+} SaHpiHsPowerStateT;
+
+/* Hot Swap Indicator State */
+typedef enum {
+ SAHPI_HS_INDICATOR_OFF = 0,
+ SAHPI_HS_INDICATOR_ON
+} SaHpiHsIndicatorStateT;
+
+/* Hot Swap Action */
+typedef enum {
+ SAHPI_HS_ACTION_INSERTION = 0,
+ SAHPI_HS_ACTION_EXTRACTION
+} SaHpiHsActionT;
+
+/* Hot Swap State */
+typedef enum {
+ SAHPI_HS_STATE_INACTIVE = 0,
+ SAHPI_HS_STATE_INSERTION_PENDING,
+ SAHPI_HS_STATE_ACTIVE_HEALTHY,
+ SAHPI_HS_STATE_ACTIVE_UNHEALTHY,
+ SAHPI_HS_STATE_EXTRACTION_PENDING,
+ SAHPI_HS_STATE_NOT_PRESENT
+} SaHpiHsStateT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Events, Part 2 **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* Event Data Structures */
+
+/*
+** Sensor Optional Data
+**
+** Sensor events may contain optional data items passed and stored with the
+** event. If these optional data items are present, they will be included with
+** the event data returned in response to a saHpiEventGet() or
+** saHpiEventLogEntryGet() function call. Also, the optional data items may be
+** included with the event data passed to the saHpiEventLogEntryAdd() function.
+**
+** Specific implementations of HPI may have restrictions on how much data may
+** be passed to saHpiEventLogEntryAdd(). These restrictions should be documented
+** by the provider of the HPI interface.
+*/
+typedef enum {
+ SAHPI_CRITICAL = 0,
+ SAHPI_MAJOR,
+ SAHPI_MINOR,
+ SAHPI_INFORMATIONAL,
+ SAHPI_OK,
+ SAHPI_DEBUG = 0xF0
+} SaHpiSeverityT;
+
+typedef SaHpiUint8T SaHpiSensorOptionalDataT;
+
+#define SAHPI_SOD_TRIGGER_READING (SaHpiSensorOptionalDataT)0x01
+#define SAHPI_SOD_TRIGGER_THRESHOLD (SaHpiSensorOptionalDataT)0x02
+#define SAHPI_SOD_OEM (SaHpiSensorOptionalDataT)0x04
+#define SAHPI_SOD_PREVIOUS_STATE (SaHpiSensorOptionalDataT)0x08
+#define SAHPI_SOD_SENSOR_SPECIFIC (SaHpiSensorOptionalDataT)0x10
+
+typedef struct {
+ SaHpiSensorNumT SensorNum;
+ SaHpiSensorTypeT SensorType;
+ SaHpiEventCategoryT EventCategory;
+ SaHpiBoolT Assertion; /* TRUE = Event State asserted
+ FALSE = deasserted */
+ SaHpiEventStateT EventState; /* State being asserted
+ deasserted */
+ SaHpiSensorOptionalDataT OptionalDataPresent;
+ SaHpiSensorReadingT TriggerReading; /* Reading that triggered
+ the event */
+ SaHpiSensorReadingT TriggerThreshold;
+ SaHpiEventStateT PreviousState;
+ SaHpiUint32T Oem;
+ SaHpiUint32T SensorSpecific;
+} SaHpiSensorEventT;
+
+typedef struct {
+ SaHpiHsStateT HotSwapState;
+ SaHpiHsStateT PreviousHotSwapState;
+} SaHpiHotSwapEventT;
+
+typedef struct {
+ SaHpiWatchdogNumT WatchdogNum;
+ SaHpiWatchdogActionEventT WatchdogAction;
+ SaHpiWatchdogPretimerInterruptT WatchdogPreTimerAction;
+ SaHpiWatchdogTimerUseT WatchdogUse;
+} SaHpiWatchdogEventT;
+
+#define SAHPI_OEM_EVENT_DATA_SIZE 32
+typedef struct {
+ SaHpiManufacturerIdT MId;
+ SaHpiUint8T OemEventData[SAHPI_OEM_EVENT_DATA_SIZE];
+} SaHpiOemEventT;
+
+/*
+** User events may be used for storing custom events created by the application / middleware;
+** eg. when injecting events into the event log using saHpiEventLogEntryAdd().
+*/
+#define SAHPI_USER_EVENT_DATA_SIZE 32
+typedef struct {
+ SaHpiUint8T UserEventData[SAHPI_USER_EVENT_DATA_SIZE];
+} SaHpiUserEventT;
+
+typedef enum {
+ SAHPI_ET_SENSOR,
+ SAHPI_ET_HOTSWAP,
+ SAHPI_ET_WATCHDOG,
+ SAHPI_ET_OEM,
+ SAHPI_ET_USER
+} SaHpiEventTypeT;
+
+typedef union {
+ SaHpiSensorEventT SensorEvent;
+ SaHpiHotSwapEventT HotSwapEvent;
+ SaHpiWatchdogEventT WatchdogEvent;
+ SaHpiOemEventT OemEvent;
+ SaHpiUserEventT UserEvent;
+} SaHpiEventUnionT;
+
+typedef struct {
+ SaHpiResourceIdT Source;
+ SaHpiEventTypeT EventType;
+ SaHpiTimeT Timestamp;
+ SaHpiSeverityT Severity;
+ SaHpiEventUnionT EventDataUnion;
+} SaHpiEventT;
+
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Parameter Control **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+typedef enum {
+ SAHPI_DEFAULT_PARM = 0,
+ SAHPI_SAVE_PARM,
+ SAHPI_RESTORE_PARM
+} SaHpiParmActionT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Reset **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+typedef enum {
+ SAHPI_COLD_RESET = 0,
+ SAHPI_WARM_RESET,
+ SAHPI_RESET_ASSERT,
+ SAHPI_RESET_DEASSERT
+} SaHpiResetActionT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Resource Presence Table **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* This section defines the types associated with the RPT. */
+
+typedef struct {
+ SaHpiUint32T UpdateCount; /* This count is incremented any time the table
+ is changed. It rolls over to zero when the
+ maximum value is reached */
+ SaHpiTimeT UpdateTimestamp; /* This time is set any time the table is
+ changed. If the implementation cannot
+ supply an absolute timestamp, then it may
+ supply a timestamp relative to some system-
+ defined epoch, such as system boot. The
+ value SAHPI_TIME_UNSPECIFIED indicates that
+ the time of the update cannot be determined.
+ Otherwise, If the value is less than or
+ equal to SAHPI_TIME_MAX_RELATIVE, then it
+ is relative; if it is greater than
+ SAHPI_TIME_MAX_RELATIVE, then it is absolute. */
+} SaHpiRptInfoT;
+
+/*
+** Resource Info Type Definitions
+**
+**
+** SaHpiResourceInfoT contains static configuration data concerning the
+** management controller associated with the resource, or the resource itself.
+** Note this information is used to describe the resource; that is, the piece of
+** infrastructure which manages an entity (or multiple entities) - NOT the entities
+** for which the resource provides management. The purpose of the
+** SaHpiResourceInfoT structure is to provide information that the HPI user may
+** need in order to interact correctly with the resource (e.g., recognize a
+** specific management controller which may have defined OEM fields in sensors,
+** OEM controls, etc.).
+**
+** All of the fields in the following structure may or may not be used by a
+** given resource.
+*/
+typedef struct {
+ SaHpiUint8T ResourceRev;
+ SaHpiUint8T SpecificVer;
+ SaHpiUint8T DeviceSupport;
+ SaHpiManufacturerIdT ManufacturerId;
+ SaHpiUint16T ProductId;
+ SaHpiUint8T FirmwareMajorRev;
+ SaHpiUint8T FirmwareMinorRev;
+ SaHpiUint8T AuxFirmwareRev;
+} SaHpiResourceInfoT;
+
+/*
+** Resource Capabilities
+**
+** This definition defines the capabilities of a given resource. One resource
+** may support any number of capabilities using the bit mask. Every resource
+** must set at least one of these capabilities; ie. zero is not a valid value
+** for a resource's capabilities.
+**
+** SAHPI_CAPABILITY_DOMAIN
+** SAHPI_CAPABILITY_RESOURCE
+** SAHPI_CAPABILITY_EVT_DEASSERTS
+** Indicates that all sensors on the resource have the property that their
+** Assertion and Deassertion event enable flags are the same. That is,
+** for all event states whose assertion triggers an event, it is
+** guaranteed that the deassertion of that event will also
+** trigger an event. Thus, the user may track the state of sensors on the
+** resource by monitoring events rather than polling for state changes.
+** SAHPI_CAPABILITY_AGGREGATE_STATUS
+** SAHPI_CAPABILITY_CONFIGURATION
+** SAHPI_CAPABILITY_MANAGED_HOTSWAP
+** Indicates that the resource supports managed hotswap. Since hotswap only
+** makes sense for field-replaceable units, the SAHPI_CAPABILITY_FRU
+** capability bit must also be set for this resource.
+** SAHPI_CAPABILITY_WATCHDOG
+** SAHPI_CAPABILITY_CONTROL
+** SAHPI_CAPABILITY_FRU
+** Indicates that the resource is a field-replaceable unit; i.e., it is
+** capable of being removed and replaced in a live system. This does not
+** necessarily imply that the resource supports managed hotswap.
+** SAHPI_CAPABILITY_INVENTORY_DATA
+** SAHPI_CAPABILITY_SEL
+** SAHPI_CAPABILITY_RDR
+** Indicates that a resource data record (RDR) repository is supplied
+** by the resource. Since the existence of an RDR is mandatory, this
+** capability must be asserted.
+** SAHPI_CAPABILITY_SENSOR
+*/
+
+typedef SaHpiUint32T SaHpiCapabilitiesT;
+#define SAHPI_CAPABILITY_DOMAIN (SaHpiCapabilitiesT)0x80000000
+#define SAHPI_CAPABILITY_RESOURCE (SaHpiCapabilitiesT)0X40000000
+#define SAHPI_CAPABILITY_EVT_DEASSERTS (SaHpiCapabilitiesT)0x00008000
+#define SAHPI_CAPABILITY_AGGREGATE_STATUS (SaHpiCapabilitiesT)0x00002000
+#define SAHPI_CAPABILITY_CONFIGURATION (SaHpiCapabilitiesT)0x00001000
+#define SAHPI_CAPABILITY_MANAGED_HOTSWAP (SaHpiCapabilitiesT)0x00000800
+#define SAHPI_CAPABILITY_WATCHDOG (SaHpiCapabilitiesT)0x00000400
+#define SAHPI_CAPABILITY_CONTROL (SaHpiCapabilitiesT)0x00000200
+#define SAHPI_CAPABILITY_FRU (SaHpiCapabilitiesT)0x00000100
+#define SAHPI_CAPABILITY_INVENTORY_DATA (SaHpiCapabilitiesT)0x00000008
+#define SAHPI_CAPABILITY_SEL (SaHpiCapabilitiesT)0x00000004
+#define SAHPI_CAPABILITY_RDR (SaHpiCapabilitiesT)0x00000002
+#define SAHPI_CAPABILITY_SENSOR (SaHpiCapabilitiesT)0x00000001
+
+/*
+** RPT Entry
+**
+** This structure is used to store the RPT entry information.
+**
+** The ResourceCapabilities field definies the capabilities of the resource.
+** This field must be non-zero for all valid resources.
+**
+** The ResourceTag field is an informational value that supplies the caller with naming
+** information for the resource. This should be set to the "user-visible" name for a
+** resource, which can be used to identify the resource in messages to a human operator.
+** For example, it could be set to match a physical printed label attached to the primary
+** entity which the resource manages. See section 5.2.6, saHpiResourceTagSet(), on page 33.
+*/
+typedef struct {
+ SaHpiEntryIdT EntryId;
+ SaHpiResourceIdT ResourceId;
+ SaHpiResourceInfoT ResourceInfo;
+ SaHpiEntityPathT ResourceEntity; /* If resource manages a FRU, entity path of the FRU */
+ /* If resource manages a single entity, entity path of
+ that entity. */
+ /* If resource manages multiple entities, the
+ entity path of the "primary" entity managed by the
+ resource */
+ /* Must be set to the same value in every domain which
+ contains this resource */
+ SaHpiCapabilitiesT ResourceCapabilities; /* Must be non-0. */
+ SaHpiSeverityT ResourceSeverity; /* Indicates the criticality that
+ should be raised when the resource
+ is not responding */
+ SaHpiDomainIdT DomainId; /* The Domain ID is used when the resource
+ is also a domain. */
+ SaHpiTextBufferT ResourceTag;
+} SaHpiRptEntryT;
+
+
+
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** System Event Log **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+/* This section defines the types associated with the SEL. */
+/*
+** Event Log Information
+**
+** The Entries entry denotes the number of active entries contained in the log.
+** The Size entry denotes the total number of entries the log is able to hold.
+** The UpdateTimestamp entry denotes the timestamp of the last addition,
+** deletion or log clear operation.
+** The CurrentTime entry denotes the log's idea of the current time; i.e the
+** timestamp that would be placed on an entry if it was added now.
+** The Enabled entry indicates whether the log is enabled. If the event log
+** is "disabled" no events generated within the HPI implementation will be
+** added to the event log. Events may still be added to the event log with
+** the saHpiEventLogEntryAdd() function. When the event log is "enabled"
+** events may be automatically added to the event log as they are generated
+** in a resource or a domain, however, it is implementation-specific which
+** events are automatically added to any event log.
+** The OverflowFlag entry indicates the log has overflowed. Events have been
+** dropped or overwritten due to a table overflow.
+** The OverflowAction entry indicates the behavior of the SEL when an overflow
+** occurs.
+** The DeleteEntrySupported indicates whether the delete command is supported for
+** event log entries. Note that clearing an entire log is valid even if this
+** flag is not set.
+*/
+typedef enum {
+ SAHPI_SEL_OVERFLOW_DROP, /* New entries are dropped when log is full*/
+ SAHPI_SEL_OVERFLOW_WRAP, /* Log wraps when log is full */
+ SAHPI_SEL_OVERFLOW_WRITELAST /* Last entry overwritten when log is full */
+} SaHpiSelOverflowActionT;
+
+typedef struct {
+ SaHpiUint32T Entries;
+ SaHpiUint32T Size;
+ SaHpiTimeT UpdateTimestamp;
+ SaHpiTimeT CurrentTime;
+ SaHpiBoolT Enabled;
+ SaHpiBoolT OverflowFlag;
+ SaHpiSelOverflowActionT OverflowAction;
+ SaHpiBoolT DeleteEntrySupported;
+} SaHpiSelInfoT;
+/*
+** Event Log Entry
+** These types define the event log entry.
+*/
+typedef SaHpiUint32T SaHpiSelEntryIdT;
+/* Reserved values for event log entry IDs */
+#define SAHPI_OLDEST_ENTRY (SaHpiSelEntryIdT)0x00000000
+#define SAHPI_NEWEST_ENTRY (SaHpiSelEntryIdT)0xFFFFFFFF
+#define SAHPI_NO_MORE_ENTRIES (SaHpiSelEntryIdT)0xFFFFFFFE
+
+
+
+typedef struct {
+ SaHpiSelEntryIdT EntryId; /* Entry ID for record */
+ SaHpiTimeT Timestamp; /* Time at which the event was placed
+ in the event log. The value
+ SAHPI_TIME_UNSPECIFIED indicates that
+ the time of the event cannot be
+ determined; otherwise, if less than
+ or equal to SAHPI_TIME_MAX_RELATIVE,
+ then it relative; if it is greater than
+ SAHPI_TIME_MAX_RELATIVE, then it is absolute. */
+ SaHpiEventT Event; /* Logged Event */
+} SaHpiSelEntryT;
+
+
+
+
+
+/*******************************************************************************
+**
+** Name: saHpiInitialize
+**
+** Description:
+** This function allows the management service an opportunity to perform
+** platform-specific initialization. saHpiInitialize() must be called
+** before any other functions are called.
+**
+** Parameters:
+** HpiImplVersion - [out] Pointer to the version of the HPI
+** implementation.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_DUPLICATE is returned when the HPI has already
+** been initialized. Once one saHpiInitialize() call has been made,
+** another one cannot be made until after a saHpiFinalize() call is made.
+**
+**
+** Remarks:
+** This function returns the version of the HPI implementation. Note: If
+** the HPI interface version is needed it can be retrieved from the
+** SAHPI_INTERFACE_VERSION definition.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiInitialize(
+ SAHPI_OUT SaHpiVersionT *HpiImplVersion
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiFinalize
+**
+** Description:
+** This function allows the management service an opportunity to perform
+** platform-specific cleanup. All sessions should be closed (see
+** saHpiSessionClose()), before this function is executed. All open
+** sessions will be forcibly closed upon execution of this command.
+**
+** Parameters:
+** None.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None. 5 Domains
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiFinalize (
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSessionOpen
+**
+** Description:
+** This function opens a HPI session for a given domain and set of
+** security characteristics (future). This function call assumes that a
+** pre-arranged agreement between caller and the HPI implementation
+** identifies the resources within the specified domain. As a future
+** roadmap item, functions for discovery of domains and allocation of
+** resources within domains may be developed.
+**
+** Parameters:
+** DomainId - [in] Domain ID to be controlled by middleware/application.
+** A domain ID of SAHPI_DEFAULT_DOMAIN_ID indicates the default domain.
+** SessionId - [out] Pointer to a location to store a handle to the newly
+** opened session. This handle is used for subsequent access to domain
+** resources and events.
+** SecurityParams - [in] Pointer to security and permissions data
+** structure. This parameter is reserved for future use, and must be set
+** to NULL.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_INVALID_DOMAIN is returned if no domain
+** matching the specified domain ID exists.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSessionOpen (
+ SAHPI_IN SaHpiDomainIdT DomainId,
+ SAHPI_OUT SaHpiSessionIdT *SessionId,
+ SAHPI_IN void *SecurityParams
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSessionClose
+**
+** Description:
+** This function closes a HPI session. After closing a session, the
+** session ID will no longer be valid.
+**
+** Parameters:
+** SessionId - [in] Session handle previously obtained using
+** saHpiSessionOpen().
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSessionClose (
+ SAHPI_IN SaHpiSessionIdT SessionId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourcesDiscover
+**
+** Description:
+** This function requests the underlying management service to discover
+** information about the resources it controls for the domain associated
+** with the open session. This function may be called during operation to
+** regenerate the RPT table. For those FRUs that must be discovered by
+** polling, latency between FRU insertion and actual addition of the
+** resource associated with that FRU to the RPT exists. To overcome this
+** latency, a discovery of all present resources may be forced by calling
+** saHpiResourcesDiscover ().
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourcesDiscover (
+ SAHPI_IN SaHpiSessionIdT SessionId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiRptInfoGet
+**
+** Description:
+** This function is used for requesting information about the resource
+** presence table (RPT) such as an update counter and timestamp. This is
+** particularly useful when using saHpiRptEntryGet() (see page 31).
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** RptInfo - [out] Pointer to the information describing the resource
+** presence table.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiRptInfoGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_OUT SaHpiRptInfoT *RptInfo
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiRptEntryGet
+**
+** Description:
+** This function retrieves resource information for the specified entry
+** of the resource presence table. This function allows the caller to
+** read the RPT entry-by-entry. If the EntryID parameter is set to
+** SAHPI_FIRST_ENTRY, the first entry in the RPT will be returned. When
+** an entry is successfully retrieved, *NextEntryID will be set to the
+** ID of the next valid entry; however, when the last entry has been
+** retrieved, *NextEntryID will be set to SAHPI_LAST_ENTRY. To retrieve
+** an entire list of entries, call this function first with an EntryID of
+** SAHPI_FIRST_ENTRY and then use the returned NextEntryID in the next
+** call. Proceed until the NextEntryID returned is SAHPI_LAST_ENTRY. At
+** initialization, the user may not wish to turn on eventing, since the
+** context of the events, as provided by the RPT, is not known. In this
+** instance, if a FRU is inserted into the system while the RPT is being
+** read entry by entry, the resource associated with that FRU may be
+** missed. (Keep in mind that there is no specified ordering for the RPT
+** entries.) The update counter provides a means for insuring that no
+** resources are missed when stepping through the RPT. In order to use
+** this feature, the user should invoke saHpiRptInfoGet(), and get the
+** update counter value before retrieving the first RPT entry. After
+** reading the last entry, the user should again invoke the
+** saHpiRptInfoGet() to get the update counter value. If the update
+** counter has not been incremented, no new records have been added.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** EntryId - [in] Handle of the entry to retrieve from the RPT. Reserved
+** entry ID values: SAHPI_FIRST_ENTRY Get first entry SAHPI_LAST_ENTRY
+** Reserved as delimiter for end of list. Not a valid entry identifier.
+**
+** NextEntryId - [out] Pointer to location to store the record ID of next
+** entry in RPT.
+** RptEntry - [out] Pointer to the structure to hold the returned RPT
+** entry.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiRptEntryGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiEntryIdT EntryId,
+ SAHPI_OUT SaHpiEntryIdT *NextEntryId,
+ SAHPI_OUT SaHpiRptEntryT *RptEntry
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiRptEntryGetByResourceId
+**
+** Description:
+** This function retrieves resource information from the resource
+** presence table for the specified resource using its resource ID.
+** Typically at start-up, the RPT is read entry-by-entry, using
+** saHpiRptEntryGet(). From this, the caller can establish the set of
+** resource IDs to use for future calls to the HPI functions. However,
+** there may be other ways of learning resource IDs without first reading
+** the RPT. For example, resources may be added to the domain while the
+** system is running in response to a hot-swap action. When a resource is
+** added, the application will receive a hot-swap event containing the
+** resource ID of the new resource. The application may then want to
+** search the RPT for more detailed information on the newly added
+** resource. In this case, the resource ID can be used to locate the
+** applicable RPT entry information.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource whose RPT entry should
+** be returned.
+** RptEntry - [out] Pointer to structure to hold the returned RPT entry.
+**
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiRptEntryGetByResourceId (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiRptEntryT *RptEntry
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourceSeveritySet
+**
+** Description:
+** This function allows the caller to set the severity level applied to
+** an event issued if a resource unexpectedly becomes unavailable to the
+** HPI. A resource may become unavailable for several reasons including:
+** ? The FRU associated with the resource is no longer present in the
+** system (a surprise extraction has occurred) ? A catastrophic failure
+** has occurred Typically, the HPI implementation will provide an
+** appropriate default value for this parameter, which may vary by
+** resource; management software can override this default value by use
+** of this function ? If a resource is removed from, then re-added to the
+** RPT (e.g., because of a hot-swap action), the HPI implementation may
+** reset the value of this parameter.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource for which the severity
+** level will be set.
+** Severity - [in] Severity level of event issued when the resource
+** unexpectedly becomes unavailable to the HPI.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceSeveritySet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSeverityT Severity
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourceTagSet
+**
+** Description:
+** This function allows the caller to set the resource tag for a
+** particular resource. The resource tag is an informational value that
+** supplies the caller with naming information for the resource. This
+** should be set to the "user-visible" name for a resource, which can be
+** used to identify the resource in messages to a human operator. For
+** example, it could be set to match a physical, printed label attached
+** to the entity associated with the resource. Typically, the HPI
+** implementation will provide an appropriate default value for this
+** parameter; this function is provided so that management software can
+** override the default, if desired. The value of the resource tag may be
+** retrieved from the resource's RPT entry. Note: If a resource is
+** removed from, then re-added to the RPT (e.g., because of a hot-swap
+** action), the HPI implementation may reset the value of this parameter.
+**
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource for which the resource
+** tag should be set.
+** ResourceTag - [in] Pointer to string representing the resource tag.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceTagSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiTextBufferT *ResourceTag
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourceIdGet
+**
+** Description:
+** This function returns the resource ID of the resource associated with
+** the entity upon which the caller is running.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [out] Pointer to location to hold the returned resource
+** ID.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_NOT_PRESENT is returned if the entity the
+** caller is running on is not manageable in the addressed domain.
+** SA_ERR_HPI_UNKNOWN is returned if the domain controller cannot
+** determine an appropriate response. That is, there may be an
+** appropriate resource ID in the domain to return, but it cannot be
+** determined.
+**
+** Remarks:
+** This function must be issued within a session to a domain that
+** includes a resource associated with the entity upon which the caller
+** is running, or the SA_ERR_HPI_NOT_PRESENT return will be issued. Since
+** entities are contained within other entities, there may be multiple
+** possible resources that could be returned to this call. For example,
+** if there is a resource ID associated with a particular compute blade
+** upon which the caller is running, and another associated with the
+** chassis which contains the compute blade, either could logically be
+** returned as an indication of a resource associated with the entity
+** upon which the caller was running. The function should return the
+** resource ID of the "smallest" resource that is associated with the
+** caller. So, in the example above, the function should return the
+** resource ID of the compute blade. Once the function has returned the
+** resourceID, the caller may issue further HPI calls using that
+** resourceID to learn the type of resource that been identified.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceIdGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_OUT SaHpiResourceIdT *ResourceId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEntitySchemaGet
+**
+** Description:
+** This function returns the identifier of the Entity Schema for the HPI
+** implementation. This schema defines valid Entity Paths that may be
+** returned by the HPI implementation.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** SchemaId - [out] Pointer to the ID of the schema in use; zero
+** indicates that a custom schema is in use.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** This function may be issued on any session opened to any domain in the
+** system, and will return the same identifier. The identifier returned
+** should either be zero, indicating that the HPI implementation uses a
+** custom schema; or one of the schema identifiers defined in Appendix A,
+** "Pre-Defined Entity Schemas," page 107. In the case of a custom
+** schema, the HPI implementation may use arbitrary entity paths to
+** describe resources in the system; in the case of a pre-defined schema,
+** all entity paths should conform to the schema.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEntitySchemaGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_OUT SaHpiUint32T *SchemaId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogInfoGet
+**
+** Description:
+** This function retrieves the number of entries in the system event log,
+** total size of the event log, timestamp for the most recent entry, the
+** log's idea of the current time (i.e., timestamp that would be placed
+** on an entry at this moment), enabled/disabled status of the log (see
+** saHpiEventLogStateSet()), the overflow flag, the overflow action, and
+** whether the log supports deletion of individual entries.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource that contains the system
+** event log to be managed. Set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the domain system event log.
+** Info - [out] Pointer to the returned SEL information.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogInfoGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiSelInfoT *Info
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogEntryGet
+**
+** Description:
+** This function retrieves an event log entry from a system event log.
+** The special entry IDs SAHPI_OLDEST_ENTRY and SAHPI_NEWEST_ENTRY are
+** used to select the oldest and newest entries, respectively, in the log
+** being read. A returned NextEntryID of SAHPI_NO_MORE_ENTRIES indicates
+** that the newest entry has been returned; there are no more entries
+** going forward (time-wise) in the log. A returned PrevEntryID of
+** SAHPI_NO_MORE_ENTRIES indicates that the oldest entry has been
+** returned. To retrieve an entire list of entries going forward (oldest
+** entry to newest entry) in the log, call this function first with an
+** EntryID of SAHPI_OLDEST_ENTRY and then use the returned NextEntryID as
+** the EntryID in the next call. Proceed until the NextEntryID returned
+** is SAHPI_NO_MORE_ENTRIES. To retrieve an entire list of entries going
+** backward (newest entry to oldest entry) in the log, call this function
+** first with an EntryID of SAHPI_NEWEST_ENTRY and then use the returned
+** PrevEntryID as the EntryID in the next call. Proceed until the
+** PrevEntryID returned is SAHPI_NO_MORE_ENTRIES.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource that contains the system
+** event log to be read. Set to SAHPI_DOMAIN_CONTROLLER_ID to address the
+** domain system event log.
+** EntryId - [in] Handle of the entry to retrieve from the SEL. Reserved
+** event log entry ID values: SAHPI_OLDEST_ENTRY Oldest entry in the
+** log. SAHPI_NEWEST_ENTRY Newest entry in the log.
+** SAHPI_NO_MORE_ENTRIES Not valid for this parameter. Used only when
+** retrieving the next and previous entry IDs.
+** PrevEntryId - [out] Handle of previous (older adjacent) entry in event
+** log. Reserved event log entry ID values: SAHPI_OLDEST_ENTRY Not valid
+** for this parameter. Used only for the EntryID parameter.
+** SAHPI_NEWEST_ENTRY Not valid for this parameter. Used only for the
+** EntryID parameter. SAHPI_NO_MORE_ENTRIES No more entries in the log
+** before the one referenced by the EntryId parameter.
+** NextEntryId - [out] Handle of next (newer adjacent) entry in event
+** log. Reserved event log entry ID values: SAHPI_OLDEST_ENTRY Not valid
+** for this parameter. Used only for the EntryID parameter.
+** SAHPI_NEWEST_ENTRY Not valid for this parameter. Used only for the
+** EntryID parameter. SAHPI_NO_MORE_ENTRIES No more entries in the log
+** after the one referenced by the EntryId parameter.
+** EventLogEntry - [out] Pointer to retrieved event log entry.
+** Rdr - [in/out] Pointer to structure to receive resource data record
+** associated with the event, if available. If NULL, no RDR data will be
+** returned.
+** RptEntry - [in/out] Pointer to structure to receive RPT Entry
+** associated with the event, if available. If NULL, no RPT entry data
+** will be returned.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Event logs may include RPT entries and resource data records
+** associated with the resource and sensor issuing an event along with
+** the basic event data in the log. Because the system may be
+** reconfigured after the event was entered in the log, this stored
+** information may be important to interpret the event. If the event log
+** includes logged RPT Entries and/or RDRs, and if the caller provides a
+** pointer to a structure to receive this information, it will be
+** returned along with the event log entry. If the caller provides a
+** pointer for an RPT entry, but the event log does not include a logged
+** RPT entry for the event being returned, RptEntry->ResourceCapabilities
+** will be set to zero. No valid RPTEntry will have a zero value here. If
+** the caller provides a pointer for an RDR, but the event log does not
+** include a logged RDR for the event being returned, Rdr->RdrType will
+** be set to SAHPI_NO_RECORD.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogEntryGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSelEntryIdT EntryId,
+ SAHPI_OUT SaHpiSelEntryIdT *PrevEntryId,
+ SAHPI_OUT SaHpiSelEntryIdT *NextEntryId,
+ SAHPI_OUT SaHpiSelEntryT *EventLogEntry,
+ SAHPI_INOUT SaHpiRdrT *Rdr,
+ SAHPI_INOUT SaHpiRptEntryT *RptEntry
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogEntryAdd
+**
+** Description:
+** This function enables system management software to add entries to the
+** system event log.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource that contains the system
+** event log to be managed. Set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the Domain System Event Log.
+** EvtEntry - [in] Pointer to event log entry data to write to the system
+** event log.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** This function forces a write of the event to the addressed event log.
+** Nothing else is done with the event. Specific implementations of HPI
+** may have restrictions on how much data may be passed to the
+** saHpiEventLogEntryAdd() function. These restrictions should be
+** documented by the provider of the HPI interface. If more event log
+** data is provided than can be written, an error will be returned.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogEntryAdd (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSelEntryT *EvtEntry
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogEntryDelete
+**
+** Description:
+** This function deletes an event log entry. This operation is only valid
+** if so indicated by saHpiEventLogInfoGet(), via the
+** DeleteEntrySupported field in the SaHpiSelInfoT structure.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] ResourceID of the resource that contains the system
+** event log to be managed. Set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the domain system event log.
+** EntryId - [in] Entry ID on the event log entry to delete. Reserved
+** event log entry ID values: SAHPI_OLDEST_ENTRY - Oldest entry in the
+** log. SAHPI_NEWEST_ENTRY - Newest entry in the log.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_INVALID_CMD is returned if this log does not
+** support this operation.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogEntryDelete (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSelEntryIdT EntryId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogClear
+**
+** Description:
+** This function erases the contents of the specified system event log.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] ResourceID of the resource that contains the system
+** event log to be managed. Set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the domain system event log.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Note that all event logs must support the "clear" operation,
+** regardless of the setting of the DeleteEntrySupported field in the
+** SaHpiSelInfoT structure returned by saHpiEventLogInfoGet().
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogClear (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogTimeGet
+**
+** Description:
+** This function retrieves the current time from the event log's own time
+** clock. The value of this clock is used to timestamp log entries
+** written into the log.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] ResourceID of the resource that contains the System
+** Event Log to be managed. Set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the Domain System Event Log.
+** Time - [out] Pointer to the returned SEL current time. If the
+** implementation cannot supply an absolute time value, then it may
+** supply a time relative to some system-defined epoch, such as system
+** boot. If the time value is less than or equal to
+** SAHPI_TIME_MAX_RELATIVE, but not SAHPI_TIME_UNSPECIFIED, then it is
+** relative; if it is greater than SAHPI_TIME_MAX_RELATIVE, then it is
+** absolute. The value SAHPI_TIME_UNSPECIFIED indicates that the time is
+** not set, or cannot be determined.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogTimeGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiTimeT *Time
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogTimeSet
+**
+** Description:
+** This function sets the event log's time clock, which is used to
+** timestamp events written into the log.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource that contains the system
+** event log to be managed. set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the domain system event log.
+** Time - [in] time to set the SEL clock to. If the implementation cannot
+** supply an absolute time, then it may supply a time relative to some
+** system-defined epoch, such as system boot. If the timestamp value is
+** less than or equal to SAHPI_TIME_MAX_RELATIVE, but not
+** SAHPI_TIME_UNSPECIFIED, then it is relative; if it is greater than
+** SAHPI_TIME_MAX_RELATIVE, then it is absolute. The value
+** SAHPI_TIME_UNSPECIFIED indicates that the time of the event cannot be
+** determined.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogTimeSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiTimeT Time
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogStateGet
+**
+** Description:
+** This function enables system management software to get the event log
+** state. If the event log is "disabled" no events generated within the
+** HPI implementation will be added to the event log. Events may still be
+** added to the event log with the saHpiEventLogEntryAdd() function. When
+** the event log is "enabled" events may be automatically added to the
+** event log as they are generated in a resource or a domain, however, it
+** is implementation-specific which events are automatically added to any
+** event log.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] ResourceID of the resource that contains the System
+** Event Log to be managed. Set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the Domain System Event Log.
+** Enable - [out] Pointer to the current SEL state. True indicates that
+** the SEL is enabled; false indicates that it is disabled.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiBoolT *Enable
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogStateSet
+**
+** Description:
+** This function enables system management software to set the event log
+** enabled state. If the event log is "disabled" no events generated
+** within the HPI implementation will be added to the event log. Events
+** may still be added to the event log using the saHpiEventLogEntryAdd()
+** function. When the event log is "enabled" events may be automatically
+** added to the event log as they are generated in a resource or a
+** domain. The actual set of events that are automatically added to any
+** event log is implementation-specific. Typically, the HPI
+** implementation will provide an appropriate default value for this
+** parameter, which may vary by resource. This function is provided so
+** that management software can override the default, if desired. Note:
+** If a resource hosting an event log is re-initialized (e.g., because of
+** a hot-swap action), the HPI implementation may reset the value of this
+** parameter.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource that contains the system
+** event log to be managed. Set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the domain system event log.
+** Enable - [in] SEL state to be set. True indicates that the SEL is to
+** be enabled; false indicates that it is to be disabled.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogStateSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiBoolT Enable
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSubscribe
+**
+** Description:
+** This function allows the caller to subscribe for session events. This
+** single call provides subscription to all session events, regardless of
+** event type or event severity. Only one subscription is allowed per
+** session, and additional subscribers will receive an appropriate error
+** code. No event filtering will be done by the underlying management
+** service.
+**
+** Parameters:
+** SessionId - [in] Session for which event subscription will be opened.
+** ProvideActiveAlarms - [in] Indicates whether or not alarms which are
+** active at the time of subscription should be queued for future
+** retrieval via the saHpiEventGet() function.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_DUPLICATE is returned when a subscription is
+** already in place for this session.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSubscribe (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiBoolT ProvideActiveAlarms
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiUnsubscribe
+**
+** Description:
+** This function removes the event subscription for the session. After
+** removal of a subscription, additional saHpiEventGet() calls will not
+** be allowed unless the caller re-subscribes for events first. Any
+** events that are still in the event queue when this function is called
+** will be cleared from it.
+**
+** Parameters:
+** SessionId - [in] Session for which event subscription will be closed.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_INVALID_REQUEST is returned if the caller is
+** not currently subscribed for events in this session.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiUnsubscribe (
+ SAHPI_IN SaHpiSessionIdT SessionId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventGet
+**
+** Description:
+** This function allows the caller to get an event. This call is only
+** valid within a session, which has subscribed for events. If the
+** ProvideActiveAlarms parameter was set in the subscription, the first
+** events retrieved will reflect the state of currently active alarms for
+** the resources belonging to the domain. After all active alarms are
+** retrieved this function will begin returning newly generated events as
+** the domain controller receives them. If there are one or more events
+** on the event queue when this function is called, it will immediately
+** return the next event on the queue. Otherwise, if the Timeout
+** parameter is SAHPI_TIMEOUT_IMMEDIATE, it will return
+** SA_ERR_HPI_TIMEOUT immediately. Otherwise, it will block for a time
+** specified by the timeout parameter; if an event is added to the queue
+** within that time, it will be returned immediately; if not,
+** saHpiEventGet() will return SA_ERR_HPI_TIMEOUT. If the Timeout
+** parameter is SAHPI_TIMEOUT_BLOCK, then saHpiEventGet() will block
+** indefinitely, until an event becomes available, and then return that
+** event. This provides for notification of events as they occur.
+**
+** Parameters:
+** SessionId - [in] Session for which events are retrieved.
+** Timeout - [in] The number of nanoseconds to wait for an event to
+** arrive. Reserved time out values: SAHPI_TIMEOUT_IMMEDIATE Time out
+** immediately if there are no events available (non-blocking call).
+** SAHPI_TIMEOUT_BLOCK Call should not return until an event is
+** retrieved.
+** Event - [out] Pointer to the next available event.
+** Rdr - [in/out] Pointer to structure to receive the resource data
+** associated with the event. If NULL, no RDR will be returned.
+** RptEntry - [in/out] Pointer to structure to receive the RPT entry
+** associated with the resource that generated the event. If NULL, no RPT
+** entry will be returned.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_TIMEOUT is returned if no event is available
+** to return within the timeout period. If SAHPI_TIMEOUT_IMMEDIATE is
+** passed in the Timeout parameter, this error return will be used if
+** there is no event queued when the function is called.
+**
+** Remarks:
+** If the caller provides a pointer for an RPT entry, but the event does
+** not include a valid resource ID for a resource in the domain (possible
+** on OEM or USER type event), then the ResourceCapabilities field in
+** *RptEntry will be set to zero. No valid RPT entry will have a zero
+** value here. If the caller provides a pointer for an RDR, but there is
+** no valid RDR associated with the event being returned (e.g., returned
+** event is not a sensor event), Rdr->RdrType will be set to
+** SAHPI_NO_RECORD. The timestamp reported in the returned event
+** structure is the best approximation an implementation has to when the
+** event actually occurred. The implementation may need to make an
+** approximation (such as the time the event was placed on the event
+** queue) because it may not have access to the actual time the event
+** occurred. The value SAHPI_TIME_UNSPECIFIED indicates that the time of
+** the event cannot be determined. If the implementation cannot supply an
+** absolute timestamp, then it may supply a timestamp relative to some
+** system-defined epoch, such as system boot. If the timestamp value is
+** less than or equal to SAHPI_TIME_MAX_RELATIVE, but not
+** SAHPI_TIME_UNSPECIFIED, then it is relative; if it is greater than
+** SAHPI_TIME_MAX_RELATIVE, then it is absolute. 6 Resource Functions
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiTimeoutT Timeout,
+ SAHPI_OUT SaHpiEventT *Event,
+ SAHPI_INOUT SaHpiRdrT *Rdr,
+ SAHPI_INOUT SaHpiRptEntryT *RptEntry
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiRdrGet
+**
+** Description:
+** This function returns a resource data record from the addressed
+** resource. Submitting an EntryId of SAHPI_FIRST_ENTRY results in the
+** first RDR being read. A returned NextEntryID of SAHPI_LAST_ENTRY
+** indicates the last RDR has been returned. A successful retrieval will
+** include the next valid EntryId. To retrieve the entire list of RDRs,
+** call this function first with an EntryId of SAHPI_FIRST_ENTRY and then
+** use the returned NextEntryId in the next call. Proceed until the
+** NextEntryId returned is SAHPI_LAST_ENTRY.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** EntryId - [in] Handle of the RDR to retrieve. Reserved entry ID
+** values: SAHPI_FIRST_ENTRY Get first entry SAHPI_LAST_ENTRY Reserved as
+** delimiter for end of list. Not a valid entry identifier.
+** NextEntryId - [out] Pointer to location to store Entry ID of next
+** entry in RDR repository.
+** Rdr - [out] Pointer to the structure to receive the requested resource
+** data record.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** A resource's RDR repository is static over the lifetime of the
+** resource; therefore no precautions are required against changes to the
+** content of the RDR repository while it is being accessed.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiRdrGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiEntryIdT EntryId,
+ SAHPI_OUT SaHpiEntryIdT *NextEntryId,
+ SAHPI_OUT SaHpiRdrT *Rdr
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSensorReadingGet
+**
+** Description:
+** This function is used to retrieve a sensor reading.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** SensorNum - [in] Sensor number for which the sensor reading is being
+** retrieved.
+** Reading - [out] Pointer to a structure to receive sensor reading
+** values.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorReadingGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_OUT SaHpiSensorReadingT *Reading
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSensorReadingConvert
+**
+** Description:
+** This function converts between raw and interpreted sensor reading
+** values. The type of conversion done depends on the passed-in
+** ReadingInput parameter. If it contains only a raw value, then this is
+** converted to an interpreted value in ConvertedReading; if it contains
+** only an interpreted value, then this is converted to a raw value in
+** ConvertedReading. If it contains neither type of value, or both, then
+** an error is returned. The ReadingInput parameter is not altered in any
+** case. If the sensor does not use raw values - i.e., it directly
+** returns interpreted values - then this routine returns an error.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** SensorNum - [in] Sensor number for which reading is associated.
+** ReadingInput - [in] Pointer to the structure that contains raw or
+** interpreted reading to be converted.
+** ConvertedReading - [out] Pointer to structure to hold converted
+** reading.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_INVALID_PARAMS is returned if the ReadingInput
+** parameter is invalid; e.g. if it contains neither a raw nor an
+** interpreted value; or if it contains both; or if it contains an
+** invalid value. SA_ERR_HPI_INVALID_DATA is returned if the sensor does
+** not support raw readings. SA_ERR_HPI_NOT_PRESENT is returned if the
+** sensor is not present.
+**
+** Remarks:
+** The EventStatus field in ReadingInput is not used by this function. To
+** make conversions, sensor-specific data may be required. Thus, the
+** function references a particular sensor in the system through the
+** SessionID/ResourceID/SensorNum parameters. If this sensor is not
+** present, and sensor- specific information is required, the conversion
+** will fail and SA_ERR_HPI_NOT_PRESENT will be returned.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorReadingConvert (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_IN SaHpiSensorReadingT *ReadingInput,
+ SAHPI_OUT SaHpiSensorReadingT *ConvertedReading
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSensorThresholdsGet
+**
+** Description:
+** This function retrieves the thresholds for the given sensor.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** SensorNum - [in] Sensor number for which threshold values are being
+** retrieved.
+** SensorThresholds - [out] Pointer to returned sensor thresholds.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorThresholdsGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_OUT SaHpiSensorThresholdsT *SensorThresholds
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSensorThresholdsSet
+**
+** Description:
+** This function sets the specified thresholds for the given sensor.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of addressed resource.
+** SensorNum - [in] Sensor number for which threshold values are being
+** set.
+** SensorThresholds - [in] Pointer to the sensor thresholds values being
+** set.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** For each threshold or hysteresis value to be set, the corresponding
+** sensor reading structure must indicate whether a raw or interpreted
+** value is present. If neither are present, then that threshold or
+** hysteresis value will not be set. Each sensor may require settings to
+** be done with raw, or interpreted values, or may permit either; this is
+** defined by the field ThresholdDefn.TholdCapabilities in the sensor's
+** RDR (saHpiSensorRecT). If the interpreted value and raw value are both
+** provided, and both are legal for the sensor, the interpreted value
+** will be ignored and the raw value will be used.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorThresholdsSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_IN SaHpiSensorThresholdsT *SensorThresholds
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSensorTypeGet
+**
+** Description:
+** This function retrieves the sensor type and event category for the
+** specified sensor.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** SensorNum - [in] Sensor number for which the type is being retrieved
+** Type - [out] Pointer to returned enumerated sensor type for the
+** specified sensor.
+** Category - [out] Pointer to location to receive the returned sensor
+** event category.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorTypeGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_OUT SaHpiSensorTypeT *Type,
+ SAHPI_OUT SaHpiEventCategoryT *Category
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSensorEventEnablesGet
+**
+** Description:
+** This function provides the ability to get the disable or enable event
+** message generation status for individual sensor events. The sensor
+** event states are relative to the event category specified by the
+** sensor. See the SaHpiEventCategoryT definition in section 7.3,
+** "Events, Part 1," on page 83 for more information. Within the
+** structure returned, there are two elements that contain bit flags; one
+** for assertion events and one for de-assertion events. A bit set to '1'
+** in the "AssertEvents" element in the structure indicates that an event
+** will be generated when the corresponding event state changes from
+** de-asserted to asserted on that sensor. A bit set to '1' in the
+** "DeassertEvents" element in the structure indicates that an event will
+** be generated when the corresponding event state changes from asserted
+** to de-asserted on that sensor. The saHpiSensorEventEnablesGet()
+** function also returns the general sensor status - whether the sensor
+** is completely disabled, or event generation is completely disabled.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** SensorNum - [in] Sensor number for which the event enable
+** configuration is being requested
+** Enables - [out] Pointer to the structure for returning sensor status
+** and event enable information.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Disabling events means that events are disabled for all sessions, not
+** just the session referenced by the SessionId parameter. For sensors
+** hosted by resources that have the "SAHPI_CAPABILITY_EVT_DEASSERTS"
+** flag set in its RPT entry, the "AssertEvents" element and the
+** "DeassertsEvents" element will always have same value.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorEventEnablesGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_OUT SaHpiSensorEvtEnablesT *Enables
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSensorEventEnablesSet
+**
+** Description:
+** This function provides the ability to set the disable or enable event
+** message generation status for individual sensor events. The sensor
+** event states are relative to the event category specified by the
+** sensor. See the SaHpiEventCategoryT definition for more information.
+** Within the structure passed, there are two elements, which contain bit
+** flags; one for assertion events and one for de-assertion events.
+** However, the use of these two elements depends on whether the resource
+** addressed has the "SAHPI_CAPABILITY_EVT_DEASSERTS" flag set in its RPT
+** entry. This capability, if set, advertises that all sensors hosted by
+** the resource will always send a "de-assert" event when any state is
+** de-asserted whose assertion generates an "assert" event. Thus, for
+** sensors hosted by resources that advertise this behavior, it is not
+** meaningful to control assert events and de-assert events separately.
+** For sensors on resources that do not have the
+** "SAHPI_CAPABILITY_EVT_DEASSERTS" flag set, a bit set to '1' in the
+** "AssertEvents" element in the structure indicates that an event will
+** be generated when the corresponding event state changes from
+** de-asserted to asserted on that sensor., and a bit set to '1' in the
+** "DeassertEvents" element in the structure indicates that an event will
+** be generated when the corresponding event state changes from asserted
+** to de-asserted on that sensor. For sensors on resources, which do have
+** the "SAHPI_CAPABILITY_EVT_DEASSERTS" flag set, the "DeassertEvents"
+** element is not used. For sensors on these resources, a bit set to '1'
+** in the "AssertEvents" element in the structure indicates that an event
+** will be generated when the corresponding event state changes in either
+** direction (de-asserted to asserted or asserted to de-asserted). The
+** saHpiSensorEventEnablesSet() function also allows setting of general
+** sensor status - whether the sensor is completely disabled, or event
+** generation is completely disabled.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** SensorNum - [in] Sensor number for which the event enables are being
+** set.
+** Enables - [in] Pointer to the structure containing the enabled status
+** for each event.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Disabling events means that events are disabled for all sessions, not
+** just the session referenced by the SessionId parameter.
+** saHpiSensorEventEnablesGet () will return the values which were last
+** set by saHpiSensorEventEnablesSet() for the "AssertEvents" and
+** "DeassertEvents" elements in the passed data structures. However, for
+** sensors hosted by any resource that has the
+** SAHPI_CAPABILITY_EVT_DEASSERTS flag set in its RPT entry, the passed
+** "AssertEvents" element on the saHpiSensorEventEnablesSet () function
+** is used for both assertion and de-assertion event enable flags. In
+** this case, this value will be returned in both the "AssertEvents" and
+** "DeassertEvents" elements on a subsequent saHpiSensorEventEnablesGet
+** () call.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorEventEnablesSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_IN SaHpiSensorEvtEnablesT *Enables
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiControlTypeGet
+**
+** Description:
+** This function retrieves the control type of a control object.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** CtrlNum - [in] Control number
+** Type - [out] Pointer to SaHpiCtrlTypeT variable to receive the
+** enumerated control type for the specified control.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** The Type parameter must point to a variable of type SaHpiCtrlTypeT.
+** Upon successful completion, the enumerated control type is returned in
+** the variable pointed to by Type.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiControlTypeGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiCtrlNumT CtrlNum,
+ SAHPI_OUT SaHpiCtrlTypeT *Type
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiControlStateGet
+**
+** Description:
+** This function retrieves the current state (generally the last state
+** set) of a control object.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of addressed resource.
+** CtrlNum - [in] Number of the control for which the state is being
+** retrieved.
+** CtrlState - [in/out] Pointer to a control data structure into which
+** the current control state will be placed. For text controls, the line
+** number to read is passed in via CtrlState->StateUnion.Text.Line.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Note that Text controls are unique in that they have a state
+** associated with each line of the control - the state being the text on
+** that line. The line number to be read is passed in to
+** sahpiControlStateGet()via CtrlState- >StateUnion.Text.Line; the
+** contents of that line of the control will be returned in CtrlState-
+** >StateUnion.Text.Text. If the line number passed in is
+** SAHPI_TLN_ALL_LINES, then sahpiControlStateGet() will return the
+** entire text of the control, or as much of it as will fit in a single
+** SaHpiTextBufferT, in CtrlState- >StateUnion.Text.Text. This value will
+** consist of the text of all the lines concatenated, using the maximum
+** number of characters for each line (no trimming of trailing blanks).
+** Note that depending on the data type and language, the text may be
+** encoded in 2-byte Unicode, which requires two bytes of data per
+** character. Note that the number of lines and columns in a text control
+** can be obtained from the control's Resource Data Record.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiControlStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiCtrlNumT CtrlNum,
+ SAHPI_INOUT SaHpiCtrlStateT *CtrlState
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiControlStateSet
+**
+** Description:
+** This function is used for setting the state of the specified control
+** object.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** CtrlNum - [in] Number of the control for which the state is being set.
+**
+** CtrlState - [in] Pointer to a control state data structure holding the
+** state to be set
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** The CtrlState parameter must be of the correct type for the specified
+** control. Text controls include a line number and a line of text in the
+** CtrlState parameter, allowing update of just a single line of a text
+** control. If less than a full line of data is written, the control will
+** clear all spaces beyond those written on the line. Thus writing a
+** zero-length string will clear the addressed line. It is also possible
+** to include more characters in the text passed in the CtrlState
+** structure than will fit on one line; in this case, the control will
+** "wrap" to the next line (still clearing the trailing characters on the
+** last line written). Thus, there are two ways to write multiple lines
+** to a text control: (a) call saHpiControlStateSet() repeatedly for each
+** line, or (b) call saHpiControlStateSet() once and send more characters
+** than will fit on one line. The caller should not assume any "cursor
+** positioning" characters are available to use, but rather should always
+** write full lines and allow "wrapping" to occur. When calling
+** saHpiControlStateSet() for a text control, the caller may set the line
+** number to SAHPI_TLN_ALL_LINES; in this case, the entire control will
+** be cleared, and the data will be written starting on line 0. (This is
+** different from simply writing at line 0, which only alters the lines
+** written to.) This feature may be used to clear the entire control,
+** which can be accomplished by setting: CtrlState->StateUnion.Text.Line
+** = SAHPI_TLN_ALL_LINES; CtrlState->StateUnion.Text.Text.DataLength = 0;
+** Note that the number of lines and columns in a text control can be
+** obtained from the control's Resource Data Record.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiControlStateSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiCtrlNumT CtrlNum,
+ SAHPI_IN SaHpiCtrlStateT *CtrlState
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEntityInventoryDataRead
+**
+** Description:
+** This function returns inventory data for a particular entity
+** associated with a resource.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** EirId - [in] Identifier for the entity inventory repository.
+** BufferSize - [in] Size of the InventData buffer passed in.
+** InventData - [out] Pointer to the buffer for the returned data.
+** ActualSize - [out] Pointer to size of the actual amount of data
+** returned.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_INVENT_DATA_TRUNCATED is returned if the buffer
+** passed in the InventData structure is not large enough (as indicated
+** by the "BufferSize" parameter) to hold the entire InventData
+** structure.
+**
+** Remarks:
+** Before calling saHpiEntityInventoryDataRead() the caller should
+** allocate a sufficiently large buffer to hold the data, and pass the
+** size of the buffer in the "BufferSize" parameter. The
+** saHpiEntityInventoryDataRead() function will return, at the location
+** pointed to by the ActualSize parameter, the actual space used in the
+** buffer to hold the returned data. If the data will not fit in the
+** buffer, as much as will fit will be returned, *ActualSize will be set
+** to indicated a suggested buffer size for the entire inventory data,
+** the "Validity" field in the InventData buffer will be set to
+** "SAHPI_INVENT_DATA_OVERFLOW," and an error return will be made. Since
+** it is impossible to know how large the inventory data may be without
+** actually reading and processing it from the entity inventory
+** repository, it may be advisable to err on the large side in allocating
+** the buffer. Note that the data includes many pointers to
+** SaHpiTextBufferT structures. The implementation of
+** saHpiEntityInventoryDataRead() may not reserve space for the maximum
+** size of each of these structures when formatting the data in the
+** returned buffer. Thus, if a user wishes to lengthen the data in one of
+** these structures, a new SaHpiTextBufferT structure should be
+** allocated, and the appropriate pointer reset to point to this new
+** structure in memory. See the description of the SaHpiInventoryDataT
+** structure in section 7.9, "Entity Inventory Data," on page 94, for
+** details on the format of the returned data.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEntityInventoryDataRead (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiEirIdT EirId,
+ SAHPI_IN SaHpiUint32T BufferSize,
+ SAHPI_OUT SaHpiInventoryDataT *InventData,
+ SAHPI_OUT SaHpiUint32T *ActualSize
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEntityInventoryDataWrite
+**
+** Description:
+** This function writes the specified data to the inventory information
+** area. Note: If the resource hosting the inventory data is
+** re-initialized, or if the entity itself is removed and reinserted, the
+** inventory data may be reset to its default settings, losing data
+** written to the repository with this function.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** EirId - [in] Identifier for the entity inventory repository.
+** InventData - [in] Pointer to data to write to the repository.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** The SaHpiInventoryDataT structure consists of a Validity field and
+** then a set of pointers to record structures. It is not required that
+** all pointers point to data within a single contiguous buffer. The
+** "Validity" field in the SaHpiInventoryDataT structure must be set to
+** "SAHPI_INVENT_DATA_VALID," or else the saHpiEntityInventoryDataWrite()
+** function will take no action and return an error. This is to help
+** prevent invalid data returned by a saHpiEntityInventoryDataRead()
+** function from being inadvertently written to the resource. For this
+** protection to work, the caller should not change the value of the
+** "Validity" field in the SaHpiInventoryDataT structure unless building
+** an entire Inventory Data set from scratch. Some implementations may
+** impose limitations on the languages of the strings passed in within
+** the InventData parameter. Implementation-specific documentation
+** should identify these restrictions.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEntityInventoryDataWrite (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiEirIdT EirId,
+ SAHPI_IN SaHpiInventoryDataT *InventData
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiWatchdogTimerGet
+**
+** Description:
+** This function retrieves the current watchdog timer settings and
+** configuration.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource, which contains the
+** watchdog timer being addressed.
+** WatchdogNum - [in] The watchdog number that specifies the watchdog
+** timer on a resource.
+** Watchdog - [out] Pointer to watchdog data structure.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** See the description of the SaHpiWatchdogT structure in 7.11,
+** "Watchdogs" on page 96 for details on what information is returned by
+** this function.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiWatchdogTimerGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiWatchdogNumT WatchdogNum,
+ SAHPI_OUT SaHpiWatchdogT *Watchdog
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiWatchdogTimerSet
+**
+** Description:
+** This function provides a method for initializing the watchdog timer
+** configuration. Once the appropriate configuration has be set using
+** saHpiWatchdogTimerSet(), the user must then call
+** saHpiWatchdogTimerReset() to initially start the watchdog timer.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource that contains the
+** watchdog timer being addressed.
+** WatchdogNum - [in] The watchdog number specifying the specific
+** watchdog timer on a resource.
+** Watchdog - [in] Pointer to watchdog data structure.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** If the initial counter value in the SaHpiWatchdogT structure is set to
+** 0, the Watchdog will immediately time out and take the pre-timeout and
+** timeout actions, as well as log an event. This provides a mechanism
+** for software to force an immediate recovery action should that be
+** dependent on a Watchdog timeout occurring. See the description of the
+** SaHpiWatchdogT structure for more details on the effects of this
+** command related to specific data passed in that structure.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiWatchdogTimerSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiWatchdogNumT WatchdogNum,
+ SAHPI_IN SaHpiWatchdogT *Watchdog
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiWatchdogTimerReset
+**
+** Description:
+** This function provides a method to start or restart the watchdog timer
+** from the initial countdown value.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID for the resource that contains the
+** watchdog timer being addressed.
+** WatchdogNum - [in] The watchdog number specifying the specific
+** watchdog timer on a resource.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** If the Watchdog has been configured to issue a Pre-Timeout interrupt,
+** and that interrupt has already occurred, the saHpiWatchdogTimerReset()
+** function will not reset the watchdog counter. The only way to stop a
+** Watchdog from timing out once a Pre-Timeout interrupt has occurred is
+** to use the saHpiWatchdogTimerSet() function to reset and/or stop the
+** timer.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiWatchdogTimerReset (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiWatchdogNumT WatchdogNum
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiHotSwapControlRequest
+**
+** Description:
+** A resource supporting hot swap typically supports default policies for
+** insertion and extraction. On insertion, the default policy may be for
+** the resource to turn the associated FRU's local power on and to
+** de-assert reset. On extraction, the default policy may be for the
+** resource to immediately power off the FRU and turn on a hot swap
+** indicator. This function allows a caller, after receiving a hot swap
+** event with HotSwapState equal to SAHPI_HS_STATE_INSERTION_PENDING or
+** SAHPI_HS_STATE_EXTRACTION_PENDING, to request control of the hot swap
+** policy and prevent the default policy from being invoked. Because a
+** resource that supports the simplified hot swap model will never
+** transition into Insertion Pending or Extraction Pending states, this
+** function is not applicable to those resources.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiHotSwapControlRequest (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourceActiveSet
+**
+** Description:
+** During insertion, a resource supporting hot swap will generate an
+** event to indicate that it is in the INSERTION PENDING state. If the
+** management middleware or other user software calls
+** saHpiHotSwapControlRequest() before the resource begins an auto-insert
+** operation, then the resource will remain in INSERTION PENDING state
+** while the user acts on the resource to integrate it into the system.
+** During this state, the user can instruct the resource to power on the
+** associated FRU, to de-assert reset, or to turn off its hot swap
+** indicator using the saHpiResourcePowerStateSet(),
+** saHpiResourceResetStateSet(), or saHpiHotSwapIndicatorStateSet()
+** functions, respectively. Once the user has completed with the
+** integration of the FRU, this function must be called to signal that
+** the resource should now transition into ACTIVE/HEALTHY or
+** ACTIVE/UNHEALTHY state (depending on whether or not there are active
+** faults). The user may also use this function to request a resource to
+** return to the ACTIVE/HEALTHY or ACTIVE/UNHEALTHY state from the
+** EXTRACTION PENDING state in order to reject an extraction request.
+** Because a resource that supports the simplified hot swap model will
+** never transition into Insertion Pending or Extraction Pending states,
+** this function is not applicable to those resources.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Only valid if resource is in INSERTION PENDING or EXTRACTION PENDING
+** state and an auto-insert or auto-extract policy action has not been
+** initiated.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceActiveSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourceInactiveSet
+**
+** Description:
+** During extraction, a resource supporting hot swap will generate an
+** event to indicate that it is in the EXTRACTION PENDING state. If the
+** management middleware or other user software calls
+** saHpiHotSwapControlRequest() before the resource begins an
+** auto-extract operation, then the resource will remain in EXTRACTION
+** PENDING state while the user acts on the resource to isolate the
+** associated FRU from the system. During this state, the user can
+** instruct the resource to power off the FRU, to assert reset, or to
+** turn on its hot swap indicator using the saHpiResourcePowerStateSet(),
+** saHpiResourceResetStateSet(), or saHpiHotSwapIndicatorStateSet()
+** functions, respectively. Once the user has completed the shutdown of
+** the FRU, this function must be called to signal that the resource
+** should now transition into INACTIVE state. The user may also use this
+** function to request a resource to return to the INACTIVE state from
+** the INSERTION PENDING state to abort a hot-swap insertion action.
+** Because a resource that supports the simplified hot swap model will
+** never transition into Insertion Pending or Extraction Pending states,
+** this function is not applicable to those resources.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Only valid if resource is in EXTRACTION PENDING or INSERTION PENDING
+** state and an auto-extract or auto-insert policy action has not been
+** initiated.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceInactiveSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiAutoInsertTimeoutGet
+**
+** Description:
+** This function allows the caller to request the auto-insert timeout
+** value. This value indicates how long the HPI implementation will wait
+** before the default auto-insertion policy is invoked. Further
+** information on the auto-insert timeout can be found in the function
+** saHpiAutoInsertTimeoutSet().
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** Timeout - [out] Pointer to location to store the number of nanoseconds
+** to wait before autonomous handling of the hotswap event. Reserved time
+** out values: SAHPI_TIMEOUT_IMMEDIATE indicates autonomous handling is
+** immediate. SAHPI_TIMEOUT_BLOCK indicates autonomous handling does not
+** occur.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAutoInsertTimeoutGet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_OUT SaHpiTimeoutT *Timeout
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiAutoInsertTimeoutSet
+**
+** Description:
+** This function allows the caller to configure a timeout for how long to
+** wait before the default auto-insertion policy is invoked. This
+** function accepts a parameter instructing the implementation to impose
+** a delay before a resource will perform its default hot swap policy for
+** auto-insertion. The parameter may be set to SAHPI_TIMEOUT_IMMEDIATE to
+** direct resources to proceed immediately to auto-insertion, or to
+** SAHPI_TIMEOUT_BLOCK to prevent auto-insertion from ever occurring. If
+** the parameter is set to another value, then it defines the number of
+** nanoseconds between the time a hot swap event with HotSwapState =
+** SAHPI_HS_STATE_INSERTION_PENDING is generated, and the time that the
+** auto-insertion policy will be invoked for that resource. If, during
+** this time period, a saHpiHotSwapControlRequest() function is
+** processed, the timer will be stopped, and the auto-insertion policy
+** will not be invoked. Once the auto-insertion process begins, the user
+** software will not be allowed to take control of the insertion process;
+** hence, the timeout should be set appropriately to allow for this
+** condition. Note that the timeout period begins when the hot swap event
+** with HotSwapState = SAHPI_HS_STATE_INSERTION_PENDING is initially
+** generated; not when it is received by a caller with a saHpiEventGet()
+** function call, or even when it is placed in a session event queue.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** Timeout - [in] The number of nanoseconds to wait before autonomous
+** handling of the hotswap event. Reserved time out values:
+** SAHPI_TIMEOUT_IMMEDIATE indicates proceed immediately to autonomous
+** handling. SAHPI_TIMEOUT_BLOCK indicates prevent autonomous handling.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAutoInsertTimeoutSet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiTimeoutT Timeout
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiAutoExtractTimeoutGet
+**
+** Description:
+** This function allows the caller to request the timeout for how long
+** the implementation will wait before the default auto-extraction policy
+** is invoked. Further information on auto-extract time outs is detailed
+** in saHpiAutoExtractTimeoutSet().
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** Timeout - [out] Pointer to location to store the number of nanoseconds
+** to wait before autonomous handling of the hotswap event. Reserved time
+** out values: SAHPI_TIMEOUT_IMMEDIATE indicates autonomous handling is
+** immediate. SAHPI_TIMEOUT_BLOCK indicates autonomous handling does not
+** occur.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAutoExtractTimeoutGet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiTimeoutT *Timeout
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiAutoExtractTimeoutSet
+**
+** Description:
+** This function allows the caller to configure a timeout for how long to
+** wait before the default auto-extraction policy is invoked. This
+** function accepts a parameter instructing the implementation to impose
+** a delay before a resource will perform its default hot swap policy for
+** auto-extraction. The parameter may be set to SAHPI_TIMEOUT_IMMEDIATE
+** to direct the resource to proceed immediately to auto-extraction, or
+** to SAHPI_TIMEOUT_BLOCK to prevent auto-extraction from ever occurring
+** on a resource. If the parameter is set to another value, then it
+** defines the number of nanoseconds between the time a hot swap event
+** with HotSwapState = SAHPI_HS_STATE_EXTRACTION_PENDING is generated,
+** and the time that the auto- extraction policy will be invoked for the
+** resource. If, during this time period, a saHpiHotSwapControlRequest()
+** function is processed, the timer will be stopped, and the
+** auto-extraction policy will not be invoked. Once the auto-extraction
+** process begins, the user software will not be allowed to take control
+** of the extraction process; hence, the timeout should be set
+** appropriately to allow for this condition. Note that the timeout
+** period begins when the hot swap event with HotSwapState =
+** SAHPI_HS_STATE_EXTRACTION_PENDING is initially generated; not when it
+** is received by a caller with a saHpiEventGet() function call, or even
+** when it is placed in a session event queue. The auto-extraction policy
+** is set at the resource level and is only supported by resources
+** supporting the "Managed Hot Swap" capability. After discovering that a
+** newly inserted resource supports "Managed Hot Swap," middleware or
+** other user software may use this function to change the default
+** auto-extraction policy for that resource. If a resource supports the
+** simplified hot-swap model, setting this timer has no effect since the
+** resource will transition directly to "Not Present" state on an
+** extraction.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** Timeout - [in] The number of nanoseconds to wait before autonomous
+** handling of the hotswap event. Reserved time out values:
+** SAHPI_TIMEOUT_IMMEDIATE indicates proceed immediately to autonomous
+** handling. SAHPI_TIMEOUT_BLOCK indicates prevent autonomous handling.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAutoExtractTimeoutSet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiTimeoutT Timeout
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiHotSwapStateGet
+**
+** Description:
+** This function allows the caller to retrieve the current hot swap state
+** of a resource. The returned state will be one of the following five
+** states: ? SAHPI_HS_STATE_INSERTION_PENDING ?
+** SAHPI_HS_STATE_ACTIVE_HEALTHY ? SAHPI_HS_STATE_ACTIVE_UNHEALTHY ?
+** SAHPI_HS_STATE_EXTRACTION_PENDING ? SAHPI_HS_STATE_INACTIVE The state
+** SAHPI_HS_STATE_NOT_PRESENT will never be returned, because a resource
+** that is not present cannot be addressed by this function in the first
+** place.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** State - [out] Pointer to location to store returned state information.
+**
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiHotSwapStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiHsStateT *State
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiHotSwapActionRequest
+**
+** Description:
+** A resource supporting hot swap typically requires a physical action on
+** the associated FRU to invoke an insertion or extraction process. An
+** insertion process is invoked by physically inserting the FRU into a
+** chassis. Physically opening an ejector latch or pressing a button
+** invokes the extraction process. This function allows the caller to
+** invoke an insertion or extraction process via software.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** Action - [in] Requested action: SAHPI_HS_ACTION_INSERTION or
+** SAHPI_HS_ACTION_EXTRACTION
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** There may be limitations on when saHpiHotSwapActionRequest() may be
+** called, and what value may be used for the "Action" parameter
+** depending on what state the resource is currently in. At the least,
+** this function may be called: ? To request an Insertion action when the
+** resource is in INACTIVE state ? To request an Extraction action when
+** the resource is in the ACTIVE/HEALTHY or ACTIVE/ UNHEALTHY state.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiHotSwapActionRequest (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiHsActionT Action
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourcePowerStateGet
+**
+** Description:
+** A typical resource supporting hot swap will have the ability to
+** control local power on the FRU associated with the resource. During
+** insertion, the FRU can be instructed to power on. During extraction
+** the FRU can be requested to power off. This function allows the caller
+** to retrieve the current power state of the FRU associated with the
+** specified resource.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** State - [out] The current power state of the resource.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** This function returns the actual low-level power state of the FRU,
+** regardless of what hot-swap state the resource is in. Not all
+** resources supporting managed hot swap will necessarily support this
+** function. In particular, resources that use the simplified hot swap
+** model may not have the ability to control FRU power. An appropriate
+** error code will be returned if the resource does not support power
+** control on the FRU.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourcePowerStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiHsPowerStateT *State
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourcePowerStateSet
+**
+** Description:
+** A typical resource supporting hot swap will have to ability to control
+** local power on the FRU associated with the resource. During insertion,
+** the FRU can be instructed to power on. During extraction the FRU can
+** be requested to power off. This function allows the caller to set the
+** current power state of the FRU associated with the specified resource.
+**
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** State - [in] the new power state that the specified resource will be
+** set to.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** This function controls the hardware power on the FRU of what hot-swap
+** state the resource is in. For example, it is legal (and may be
+** desirable) to cycle power on the FRU even while it is in ACTIVE state
+** in order to attempt to clear a fault condition. Similarly, a resource
+** could be instructed to power on a FRU even while it is in INACTIVE
+** state, for example, in order to run off-line diagnostics. Not all
+** resources supporting managed hot swap will necessarily support this
+** function. In particular, resources that use the simplified hot swap
+** model may not have the ability to control FRU power. An appropriate
+** error code will be returned if the resource does not support power
+** control on the FRU.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourcePowerStateSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiHsPowerStateT State
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiHotSwapIndicatorStateGet
+**
+** Description:
+** A FRU associated with a hot-swappable resource may include a hot swap
+** indicator such as a blue LED. This indicator signifies that the FRU is
+** ready for removal.. This function allows the caller to retrieve the
+** state of this indicator. The returned state is either
+** SAHPI_HS_INDICATOR_OFF or SAHPI_HS_INDICATOR_ON. This function will
+** return the state of the indicator, regardless of what hot swap state
+** the resource is in.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** State - [out] Pointer to location to store state of hot swap
+** indicator.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Not all resources supporting managed hot swap will necessarily support
+** this function. In particular, resources that use the simplified hot
+** swap model may not have the ability to control a FRU hot swap
+** indicator (it is likely that none exists). An appropriate error code
+** will be returned if the resource does not support control of a hot
+** swap indicator on the FRU.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiHotSwapIndicatorStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiHsIndicatorStateT *State
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiHotSwapIndicatorStateSet
+**
+** Description:
+** A FRU associated with a hot-swappable resource may include a hot swap
+** indicator such as a blue LED. This indicator signifies that the FRU is
+** ready for removal. This function allows the caller to set the state of
+** this indicator. Valid states include SAHPI_HS_INDICATOR_OFF or
+** SAHPI_HS_INDICATOR_ON. This function will set the indicator regardless
+** of what hot swap state the resource is in, though it is recommended
+** that this function be used only in conjunction with moving the
+** resource to the appropriate hot swap state.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource
+** State - [in] State of hot swap indicator to be set.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Not all resources supporting managed hot swap will necessarily support
+** this function. In particular, resources that use the simplified hot
+** swap model may not have the ability to control a FRU hot swap
+** indicator (it is likely that none exists). An appropriate error code
+** will be returned if the resource does not support control of a hot
+** swap indicator on the FRU.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiHotSwapIndicatorStateSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiHsIndicatorStateT State
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiParmControl
+**
+** Description:
+** This function allows the user to save and restore parameters
+** associated with a specific resource. Valid actions for this function
+** include: SAHPI_DEFAULT_PARM Restores the factory default settings for
+** a specific resource. Factory defaults include sensor thresholds and
+** configurations, and resource- specific configuration parameters.
+** SAHPI_SAVE_PARM Stores the resource configuration parameters in
+** non-volatile storage. Resource configuration parameters stored in
+** non-volatile storage will survive power cycles and resource resets.
+** SAHPI_RESTORE_PARM Restores resource configuration parameters from
+** non-volatile storage. Resource configuration parameters include sensor
+** thresholds and sensor configurations, as well as resource-specific
+** parameters.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** Action - [in] Action to perform on resource parameters.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Resource-specific parameters should be documented in an implementation
+** guide for the HPI implementation.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiParmControl (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiParmActionT Action
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourceResetStateGet
+**
+** Description:
+** This function gets the reset state of an entity, allowing the user to
+** determine if the entity is being held with its reset asserted. If a
+** resource manages multiple entities, this function will address the
+** entity which is identified in the RPT entry for the resource.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** ResetAction - [out] The current reset state of the entity. Valid reset
+** states are: SAHPI_RESET_ASSERT: The entity's reset is asserted, e.g.,
+** for hot swap insertion/extraction purposes SAHPI_RESET_DEASSERT: The
+** entity's reset is not asserted
+**
+** Return Value:
+** SA_OK is returned if the resource has reset control, and the reset
+** state has successfully been determined; otherwise, an error code is
+** returned. SA_ERR_HPI_INVALID_CMD is returned if the resource has no
+** reset control.
+**
+** Remarks:
+** SAHPI_RESET_COLD and SAHPI_RESET_WARM are pulsed resets, and are not
+** valid return values for ResetAction. If the entity is not being held
+** in reset (using SAHPI_RESET_ASSERT), the appropriate return value is
+** SAHPI_RESET_DEASSERT.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceResetStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiResetActionT *ResetAction
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourceResetStateSet
+**
+** Description:
+** This function directs the resource to perform the specified reset type
+** on the entity that it manages. If a resource manages multiple
+** entities, this function addresses the entity that is identified in the
+** RPT entry for the resource. Entities may be reset for a variety of
+** reasons. A misbehaving entity may be reset to bring it to a known
+** state. In these cases, either a warm reset or a cold reset may be
+** performed. A warm reset preserves entity state, whereas a cold reset
+** does not. Both of these reset types are pulsed asserted and then
+** de-asserted by the HPI implementation. This allows the HPI
+** implementation to hold the reset asserted for the appropriate length
+** of time, as needed by each entity. saHpiResourceResetStateSet() can
+** also be used for insertion and extraction scenarios. A typical
+** resource supporting hot swap will have to ability to control local
+** reset within the FRU. During insertion, a resource can be instructed
+** to assert reset, while the FRU powers on. During extraction a resource
+** can be requested to assert reset before the FRU is powered off. This
+** function allows the caller to set the reset state of the specified
+** FRU. SAHPI_RESET_ASSERT is used to hold the resource in reset; the FRU
+** is brought out of the reset state by using either SAHPI_COLD_RESET or
+** SAHPI_WARM_RESET.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** ResetAction - [in] Type of reset to perform on the entity. Valid reset
+** actions are: SAHPI_COLD_RESET: Perform a 'Cold Reset' on the entity
+** (pulse), leaving reset de-asserted SAHPI_WARM_RESET: Perform a 'Warm
+** Reset' on the entity (pulse), leaving reset de-asserted
+** SAHPI_RESET_ASSERT: Put the entity into reset state and hold reset
+** asserted, e.g., for hot swap insertion/extraction purposes
+**
+** Return Value:
+** SA_OK is returned if the resource has reset control, and the requested
+** reset action has succeeded; otherwise, an error code is returned.
+** SA_ERR_HPI_INVALID_CMD is returned if the resource has no reset
+** control, or if the requested reset action is not supported by the
+** resource.
+**
+** Remarks:
+** Some resources may not support reset, or may only support a subset of
+** the defined reset action types. Also, on some resources, cold and warm
+** resets may be equivalent. 7 Data Type Definitions
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceResetStateSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiResetActionT ResetAction
+);
+
+
+
+#endif
+
diff --git a/hpiutil/SaHpi.h-A b/hpiutil/SaHpi.h-A
new file mode 100644
index 0000000..6efd5e9
--- /dev/null
+++ b/hpiutil/SaHpi.h-A
@@ -0,0 +1,4509 @@
+/*******************************************************************************
+**
+** FILE:
+** SaHpi.h
+**
+** DESCRIPTION:
+** This file provides the C language binding for the Service
+** Availability(TM) Forum Platform Interface. It contains all of
+** the prototypes and type definitions. Note, this file was
+** generated from the Platform Interface specification document.
+**
+** SPECIFICATION VERSION:
+** SAI-HPI-A.01.01
+**
+** DATE:
+** Thu Oct 3 14:48:41 2002
+**
+** LEGAL:
+** OWNERSHIP OF SPECIFICATION AND COPYRIGHTS.
+** The Specification and all worldwide copyrights therein are
+** the exclusive property of Licensor. You may not remove, obscure, or
+** alter any copyright or other proprietary rights notices that are in or
+** on the copy of the Specification you download. You must reproduce all
+** such notices on all copies of the Specification you make. Licensor
+** may make changes to the Specification, or to items referenced therein,
+** at any time without notice. Licensor is not obligated to support or
+** update the Specification.
+**
+** Copyright(c) 2002, Service Availability(TM) Forum. All rights
+** reserved.
+**
+*******************************************************************************/
+
+#ifndef __SAHPI_H
+#define __SAHPI_H
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Basic Data Types and Values **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* General Types - need to be specified correctly for the host architecture */
+typedef unsigned char SaHpiUint8T;
+typedef unsigned short SaHpiUint16T;
+typedef unsigned int SaHpiUint32T;
+typedef char SaHpiInt8T;
+typedef short SaHpiInt16T;
+typedef int SaHpiInt32T;
+typedef long long SaHpiInt64T;
+typedef float SaHpiFloat32T;
+typedef double SaHpiFloat64T;
+
+typedef SaHpiUint8T SaHpiBoolT;
+#define SAHPI_TRUE 1
+#define SAHPI_FALSE 0
+
+/* Platform, O/S, or Vendor dependent */
+#define SAHPI_API
+#define SAHPI_IN
+#define SAHPI_OUT
+#define SAHPI_INOUT
+
+/*
+** Identifier for the manufacturer
+**
+** This is the IANA-assigned private enterprise number for the
+** manufacturer of the resource or FRU, or of the manufacturer
+** defining an OEM control or event type. A list of current
+** IANA-assigned private enterprise numbers may be obtained at
+**
+** http://www.iana.org/assignments/enterprise-numbers
+**
+** If a manufacturer does not currently have an assigned number, one
+** may be obtained by following the instructions located at
+**
+** http://www.iana.org/cgi-bin/enterprise.pl
+*/
+typedef SaHpiUint32T SaHpiManufacturerIdT;
+#define SAHPI_MANUFACTURER_ID_UNSPECIFIED (SaHpiManufacturerIdT)0
+
+/* Version Types */
+typedef SaHpiUint32T SaHpiVersionT;
+
+/*
+** Interface Version
+**
+** The interface version is the version of the actual interface and not the
+** version of the implementation. It is a 24 bit value where
+** the most significant 8 bits represent the compatibility level
+** (with letters represented as the corresponding numbers);
+** the next 8 bits represent the major version number; and
+** the least significant 8 bits represent the minor version number.
+*/
+#define SAHPI_INTERFACE_VERSION (SaHpiVersionT)0x010101 /* A.01.01 */
+
+/*
+** Return Codes
+**
+** SaErrorT is defined in the HPI specification. In the future a
+** common SAF types definition may be created to contain this type. At
+** that time, this typedef should be removed.
+*/
+typedef SaHpiInt32T SaErrorT; /* Return code */
+
+/*
+** SA_OK: This code indicates that a command completed successfully.
+*/
+#define SA_OK (SaErrorT)0x0000
+
+/* This value is the base for all HPI-specific error codes. */
+#define SA_HPI_ERR_BASE -1000
+
+/*
+** SA_ERR_HPI_ERROR: An unspecified error occurred. This code should
+** be returned only as a last resort; eg. if the cause of an error
+** cannot be determined.
+*/
+#define SA_ERR_HPI_ERROR (SaErrorT)(SA_HPI_ERR_BASE - 1)
+
+/*
+** SA_ERR_HPI_UNSUPPORTED_API: The HPI implementation does not support
+** this API. This code is appropriate, for example, if invoking the
+** Hot Swap functions on an HPI implementation which has no hot swap
+** support. Note that such an implementation would not report any hot
+** swap capabilities via its RDRs.
+*/
+#define SA_ERR_HPI_UNSUPPORTED_API (SaErrorT)(SA_HPI_ERR_BASE - 2)
+
+/*
+** SA_ERR_HPI_BUSY: The command cannot be performed because the
+** targeted device is busy.
+*/
+#define SA_ERR_HPI_BUSY (SaErrorT)(SA_HPI_ERR_BASE - 3)
+
+/*
+** SA_ERR_HPI_INVALID: The request is fundamentally invalid.
+*/
+#define SA_ERR_HPI_INVALID (SaErrorT)(SA_HPI_ERR_BASE - 4)
+
+/*
+** SA_ERR_HPI_INVALID_CMD: The specific object to which a command was
+** directed does not support that command (which was otherwise valid).
+*/
+#define SA_ERR_HPI_INVALID_CMD (SaErrorT)(SA_HPI_ERR_BASE - 5)
+
+/*
+** SA_ERR_HPI_TIMEOUT: The requested operation, which had a timeout
+** value specified, timed out. For example, when reading input with a
+** timeout value, if no input arrives within the timeout interval,
+** this code should be returned. This should only be returned in
+** cases where a timeout is anticipated as a valid consequence of the
+** operation; if the addressed entity is not responding due to a
+** fault, use SA_ERR_HPI_NO_RESPONSE (qv).
+*/
+#define SA_ERR_HPI_TIMEOUT (SaErrorT)(SA_HPI_ERR_BASE - 6)
+
+/*
+** SA_ERR_HPI_OUT_OF_SPACE: The requested command failed due to
+** resource limits.
+*/
+#define SA_ERR_HPI_OUT_OF_SPACE (SaErrorT)(SA_HPI_ERR_BASE - 7)
+
+/*
+** SA_ERR_HPI_DATA_TRUNCATED: The returned data was truncated. For
+** example, when reading data into a fixed-size buffer, if the data is
+** larger than the buffer, this code should be returned.
+*/
+#define SA_ERR_HPI_DATA_TRUNCATED (SaErrorT)(SA_HPI_ERR_BASE - 8)
+
+/*
+** SA_ERR_HPI_DATA_LEN_INVALID: The specified data length is invalid.
+*/
+#define SA_ERR_HPI_DATA_LEN_INVALID (SaErrorT)(SA_HPI_ERR_BASE - 9)
+
+/*
+** SA_ERR_HPI_DATA_EX_LIMITS: The supplied data exceeds limits.
+*/
+#define SA_ERR_HPI_DATA_EX_LIMITS (SaErrorT)(SA_HPI_ERR_BASE - 10)
+
+/*
+** SA_ERR_HPI_INVALID_PARAMS: One or more parameters to the command
+** were invalid.
+*/
+#define SA_ERR_HPI_INVALID_PARAMS (SaErrorT)(SA_HPI_ERR_BASE - 11)
+
+/*
+** SA_ERR_HPI_INVALID_DATA: Cannot return requested data; eg. the
+** specific object to which a command was directed does not support
+** the data required by the command.
+*/
+#define SA_ERR_HPI_INVALID_DATA (SaErrorT)(SA_HPI_ERR_BASE - 12)
+
+/*
+** SA_ERR_HPI_NOT_PRESENT: The requested object was not present. For
+** example, this code would be returned when attempting to access an
+** entry in a RPT or RDR which is not present. As another example, this
+** code would also be returned when accessing an invalid management
+** instrument on a valid resource.
+*/
+#define SA_ERR_HPI_NOT_PRESENT (SaErrorT)(SA_HPI_ERR_BASE - 13)
+
+/*
+** SA_ERR_HPI_INVALID_DATA_FIELD: Invalid data field.
+*/
+#define SA_ERR_HPI_INVALID_DATA_FIELD (SaErrorT)(SA_HPI_ERR_BASE - 14)
+
+/*
+** SA_ERR_HPI_INVALID_SENSOR_CMD: Invalid sensor command.
+*/
+#define SA_ERR_HPI_INVALID_SENSOR_CMD (SaErrorT)(SA_HPI_ERR_BASE - 15)
+
+/*
+** SA_ERR_HPI_NO_RESPONSE: There was no response from the domain or
+** object targeted by the command, due to some fault. This code
+** indicates an un-anticipated failure to respond; compare with
+** SA_ERR_HPI_TIMEOUT.
+*/
+#define SA_ERR_HPI_NO_RESPONSE (SaErrorT)(SA_HPI_ERR_BASE - 16)
+
+/*
+** SA_ERR_HPI_DUPLICATE: Duplicate request -- such as attempting to
+** initialize something which has already been initialized (and which
+** cannot be initialized twice).
+*/
+#define SA_ERR_HPI_DUPLICATE (SaErrorT)(SA_HPI_ERR_BASE - 17)
+
+/*
+** SA_ERR_HPI_UPDATING: The command could not be completed because
+** the targeted object is in update mode.
+*/
+#define SA_ERR_HPI_UPDATING (SaErrorT)(SA_HPI_ERR_BASE - 18)
+
+/*
+** SA_ERR_HPI_INITIALIZING: The command could not be completed because
+** the targeted object is initializing.
+*/
+#define SA_ERR_HPI_INITIALIZING (SaErrorT)(SA_HPI_ERR_BASE - 19)
+
+/*
+** SA_ERR_HPI_UNKNOWN: This code should be returned if, for some
+** reason, the HPI implementation cannot determine the proper response
+** to a command. For example, there may be a proper value to return
+** for a given call, but the implementation may be unable to determine
+** which one it is.
+*/
+#define SA_ERR_HPI_UNKNOWN (SaErrorT)(SA_HPI_ERR_BASE - 20)
+
+/*
+** SA_ERR_HPI_INVALID_SESSION: An invalid session ID was specified in
+** the command.
+*/
+#define SA_ERR_HPI_INVALID_SESSION (SaErrorT)(SA_HPI_ERR_BASE - 21)
+
+/*
+** SA_ERR_HPI_INVALID_DOMAIN: Invalid domain ID specified -- ie. a
+** domain ID which does not correspond to any real domain was
+** specified in the command.
+*/
+#define SA_ERR_HPI_INVALID_DOMAIN (SaErrorT)(SA_HPI_ERR_BASE - 22)
+
+/*
+** SA_ERR_HPI_INVALID_RESOURCE: Invalid resource ID specified -- ie. a
+** resource ID which does not correspond to a resource in the addressed
+** domain was specified in the command.
+*/
+#define SA_ERR_HPI_INVALID_RESOURCE (SaErrorT)(SA_HPI_ERR_BASE - 23)
+
+/*
+** SA_ERR_HPI_INVALID_REQUEST: The request is invalid in the current
+** context. An example would be attempting to unsubscribe for events,
+** when the caller has not subscribed to events.
+*/
+#define SA_ERR_HPI_INVALID_REQUEST (SaErrorT)(SA_HPI_ERR_BASE - 24)
+
+/*
+** SA_ERR_HPI_ENTITY_NOT_PRESENT: The addressed management instrument is not active
+** because the entity with which it is associated is not present. This
+** condition could occur, for instance, when an alarm module is managing a
+** fan tray FRU. The alarm module would contain management instruments (sensors,
+** etc) for the fan tray. The fan tray may be removed, even though the
+** management instruments are still represented in the alarm module. In this
+** case, SA_ERR_HPI_ENTITY_NOT_PRESENT would be returned if a management instrument
+** associated with a removed entity is accessed.
+*/
+#define SA_ERR_HPI_ENTITY_NOT_PRESENT (SaErrorT)(SA_HPI_ERR_BASE - 25)
+
+/*
+** SA_ERR_HPI_UNINITIALIZED: This code is returned when a request is
+** made, and the HPI has not, yet, been initialized via saHpiInitialize().
+*/
+#define SA_ERR_HPI_UNINITIALIZED (SaErrorT)(SA_HPI_ERR_BASE - 26)
+
+
+/*
+** Domain, Session and Resource Type Definitions
+*/
+
+/* Domain ID. */
+typedef SaHpiUint32T SaHpiDomainIdT;
+#define SAHPI_DEFAULT_DOMAIN_ID (SaHpiDomainIdT)0
+
+/* The SAHPI_UNSPECIFIED_DOMAIN_ID value may be used by an implementation
+** when populating the ResourceId value for an RPT entry that is a
+** domain only.
+*/
+#define SAHPI_UNSPECIFIED_DOMAIN_ID (SaHpiDomainIdT) 0xFFFFFFFF
+
+/* Session ID. */
+typedef SaHpiUint32T SaHpiSessionIdT;
+
+/* Resource identifier. */
+typedef SaHpiUint32T SaHpiResourceIdT;
+
+/* The SAHPI_UNSPECIFIED_RESOURCE_ID value may be used by an implementation
+** when populating the DomainId value for an RPT entry that is a
+** resource only. Note that this reserved value (0xFFFFFFFF) is also used
+** to designate the domain controller, for domain-based event log access.
+*/
+#define SAHPI_UNSPECIFIED_RESOURCE_ID (SaHpiResourceIdT) 0xFFFFFFFF
+
+/* The SAHPI_DOMAIN_CONTROLLER_ID value is a reserved resource ID
+** value which is used to select the domain controller's event log
+** (as opposed to a real resource's event log) when accessing logs.
+** This value must not be used as the ID of any real resource.
+*/
+#define SAHPI_DOMAIN_CONTROLLER_ID (SaHpiResourceIdT) 0xFFFFFFFE
+
+/* Table Related Type Definitions */
+typedef SaHpiUint32T SaHpiEntryIdT;
+#define SAHPI_FIRST_ENTRY (SaHpiEntryIdT)0x00000000
+#define SAHPI_LAST_ENTRY (SaHpiEntryIdT)0xFFFFFFFF
+
+/*
+** Time Related Type Definitions
+**
+** An HPI time value represents the local time as the number of nanoseconds
+** from 00:00:00, January 1, 1970, in a 64-bit signed integer. This format
+** is sufficient to represent times with nano-second resolution from the
+** year 1678 to 2262. Every API which deals with time values must define
+** the timezone used.
+**
+** It should be noted that although nano-second resolution is supported
+** in the data type, the actual resolution provided by an implementation
+** may be more limited than this.
+**
+** The value -2**63, which is 0x8000000000000000, is used to indicate
+** "unknown/unspecified time".
+**
+** Conversion to/from POSIX and other common time representations is
+** relatively straightforward. The following code framgment converts
+** between SaHpiTimeT and time_t:
+**
+** time_t tt1, tt2;
+** SaHpiTimeT saHpiTime;
+**
+** time(&tt1);
+** saHpiTime = (SaHpiTimeT) tt1 * 1000000000;
+** tt2 = saHpiTime / 1000000000;
+**
+** The following fragment converts between SaHpiTimeT and a struct timeval:
+**
+** struct timeval tv1, tv2;
+** SaHpiTimeT saHpiTime;
+**
+** gettimeofday(&tv1, NULL);
+** saHpiTime = (SaHpiTimeT) tv1.tv_sec * 1000000000 + tv1.tv_usec * 1000;
+** tv2.tv_sec = saHpiTime / 1000000000;
+** tv2.tv_usec = saHpiTime % 1000000000 / 1000;
+**
+** The following fragment converts between SaHpiTimeT and a struct timespec:
+**
+** struct timespec ts1, ts2;
+** SaHpiTimeT saHpiTime;
+**
+** clock_gettime(CLOCK_REALTIME, &ts1);
+** saHpiTime = (SaHpiTimeT) ts1.tv_sec * 1000000000 + ts1.tv_nsec;
+** ts2.tv_sec = saHpiTime / 1000000000;
+** ts2.tv_nsec = saHpiTime % 1000000000;
+**
+** Note, however, that since time_t is (effectively) universally 32 bits,
+** all of these conversions will cease to work on January 18, 2038.
+**
+** Some subsystems may need the flexibility to report either absolute or
+** relative (eg. to system boot) times. This will typically be in the
+** case of a board which may or may not, depending on the system setup,
+** have an idea of absolute time. For example, some boards may have
+** "time of day" clocks which start at zero, and never get set to the
+** time of day.
+**
+** In these cases, times which represent "current" time (in events, for
+** example) can be reported based on the clock value, whether it has been
+** set to the actual date/time, or whether it represents the elapsed time
+** since boot. If it is the time since boot, the value will be (for 27
+** years) less than 0x0C00000000000000, which is Mon May 26 16:58:48 1997.
+** If the value is greater than this, then it can be assumed to be an
+** absolute time.
+**
+** Every API which can report either absolute or relative times must
+** state this rule clearly in its interface specification.
+*/
+typedef SaHpiInt64T SaHpiTimeT; /* Time in nanoseconds */
+
+/* Unspecified or unknown time */
+#define SAHPI_TIME_UNSPECIFIED (SaHpiTimeT) 0x8000000000000000
+
+/* Maximum time that can be specified as relative */
+#define SAHPI_TIME_MAX_RELATIVE (SaHpiTimeT) 0x0C00000000000000
+typedef SaHpiInt64T SaHpiTimeoutT; /* Timeout in nanoseconds */
+
+/* Non-blocking call */
+#define SAHPI_TIMEOUT_IMMEDIATE (SaHpiTimeoutT) 0x0000000000000000
+
+/* Blocking call, wait indefinitely for call to complete */
+#define SAHPI_TIMEOUT_BLOCK (SaHpiTimeoutT) -1
+
+/*
+** Language
+**
+** This enumeration lists all of the languages that can be associated with text.
+**
+** SAHPI_LANG_UNDEF indicates that the language is unspecified or
+** unknown.
+*/
+typedef enum {
+ SAHPI_LANG_UNDEF = 0, SAHPI_LANG_AFAR, SAHPI_LANG_ABKHAZIAN,
+ SAHPI_LANG_AFRIKAANS, SAHPI_LANG_AMHARIC, SAHPI_LANG_ARABIC,
+ SAHPI_LANG_ASSAMESE, SAHPI_LANG_AYMARA, SAHPI_LANG_AZERBAIJANI,
+ SAHPI_LANG_BASHKIR, SAHPI_LANG_BYELORUSSIAN, SAHPI_LANG_BULGARIAN,
+ SAHPI_LANG_BIHARI, SAHPI_LANG_BISLAMA, SAHPI_LANG_BENGALI,
+ SAHPI_LANG_TIBETAN, SAHPI_LANG_BRETON, SAHPI_LANG_CATALAN,
+ SAHPI_LANG_CORSICAN, SAHPI_LANG_CZECH, SAHPI_LANG_WELSH,
+ SAHPI_LANG_DANISH, SAHPI_LANG_GERMAN, SAHPI_LANG_BHUTANI,
+ SAHPI_LANG_GREEK, SAHPI_LANG_ENGLISH, SAHPI_LANG_ESPERANTO,
+ SAHPI_LANG_SPANISH, SAHPI_LANG_ESTONIAN, SAHPI_LANG_BASQUE,
+ SAHPI_LANG_PERSIAN, SAHPI_LANG_FINNISH, SAHPI_LANG_FIJI,
+ SAHPI_LANG_FAEROESE, SAHPI_LANG_FRENCH, SAHPI_LANG_FRISIAN,
+ SAHPI_LANG_IRISH, SAHPI_LANG_SCOTSGAELIC, SAHPI_LANG_GALICIAN,
+ SAHPI_LANG_GUARANI, SAHPI_LANG_GUJARATI, SAHPI_LANG_HAUSA,
+ SAHPI_LANG_HINDI, SAHPI_LANG_CROATIAN, SAHPI_LANG_HUNGARIAN,
+ SAHPI_LANG_ARMENIAN, SAHPI_LANG_INTERLINGUA, SAHPI_LANG_INTERLINGUE,
+ SAHPI_LANG_INUPIAK, SAHPI_LANG_INDONESIAN, SAHPI_LANG_ICELANDIC,
+ SAHPI_LANG_ITALIAN, SAHPI_LANG_HEBREW, SAHPI_LANG_JAPANESE,
+ SAHPI_LANG_YIDDISH, SAHPI_LANG_JAVANESE, SAHPI_LANG_GEORGIAN,
+ SAHPI_LANG_KAZAKH, SAHPI_LANG_GREENLANDIC, SAHPI_LANG_CAMBODIAN,
+ SAHPI_LANG_KANNADA, SAHPI_LANG_KOREAN, SAHPI_LANG_KASHMIRI,
+ SAHPI_LANG_KURDISH, SAHPI_LANG_KIRGHIZ, SAHPI_LANG_LATIN,
+ SAHPI_LANG_LINGALA, SAHPI_LANG_LAOTHIAN, SAHPI_LANG_LITHUANIAN,
+ SAHPI_LANG_LATVIANLETTISH, SAHPI_LANG_MALAGASY, SAHPI_LANG_MAORI,
+ SAHPI_LANG_MACEDONIAN, SAHPI_LANG_MALAYALAM, SAHPI_LANG_MONGOLIAN,
+ SAHPI_LANG_MOLDAVIAN, SAHPI_LANG_MARATHI, SAHPI_LANG_MALAY,
+ SAHPI_LANG_MALTESE, SAHPI_LANG_BURMESE, SAHPI_LANG_NAURU,
+ SAHPI_LANG_NEPALI, SAHPI_LANG_DUTCH, SAHPI_LANG_NORWEGIAN,
+ SAHPI_LANG_OCCITAN, SAHPI_LANG_AFANOROMO, SAHPI_LANG_ORIYA,
+ SAHPI_LANG_PUNJABI, SAHPI_LANG_POLISH, SAHPI_LANG_PASHTOPUSHTO,
+ SAHPI_LANG_PORTUGUESE, SAHPI_LANG_QUECHUA, SAHPI_LANG_RHAETOROMANCE,
+ SAHPI_LANG_KIRUNDI, SAHPI_LANG_ROMANIAN, SAHPI_LANG_RUSSIAN,
+ SAHPI_LANG_KINYARWANDA, SAHPI_LANG_SANSKRIT, SAHPI_LANG_SINDHI,
+ SAHPI_LANG_SANGRO, SAHPI_LANG_SERBOCROATIAN, SAHPI_LANG_SINGHALESE,
+ SAHPI_LANG_SLOVAK, SAHPI_LANG_SLOVENIAN, SAHPI_LANG_SAMOAN,
+ SAHPI_LANG_SHONA, SAHPI_LANG_SOMALI, SAHPI_LANG_ALBANIAN,
+ SAHPI_LANG_SERBIAN, SAHPI_LANG_SISWATI, SAHPI_LANG_SESOTHO,
+ SAHPI_LANG_SUDANESE, SAHPI_LANG_SWEDISH, SAHPI_LANG_SWAHILI,
+ SAHPI_LANG_TAMIL, SAHPI_LANG_TELUGU, SAHPI_LANG_TAJIK,
+ SAHPI_LANG_THAI, SAHPI_LANG_TIGRINYA, SAHPI_LANG_TURKMEN,
+ SAHPI_LANG_TAGALOG, SAHPI_LANG_SETSWANA, SAHPI_LANG_TONGA,
+ SAHPI_LANG_TURKISH, SAHPI_LANG_TSONGA, SAHPI_LANG_TATAR,
+ SAHPI_LANG_TWI, SAHPI_LANG_UKRAINIAN, SAHPI_LANG_URDU,
+ SAHPI_LANG_UZBEK, SAHPI_LANG_VIETNAMESE, SAHPI_LANG_VOLAPUK,
+ SAHPI_LANG_WOLOF, SAHPI_LANG_XHOSA, SAHPI_LANG_YORUBA,
+ SAHPI_LANG_CHINESE, SAHPI_LANG_ZULU
+} SaHpiLanguageT;
+
+/*
+** Text Buffers
+**
+** These structures are used for defining the type of data in the text buffer
+** and the length of the buffer. Text buffers are used in the inventory data,
+** RDR, RPT, etc. for variable length strings of data.
+*/
+
+#define SAHPI_MAX_TEXT_BUFFER_LENGTH 255
+
+typedef enum {
+ SAHPI_TL_TYPE_BINARY = 0, /* String of bytes, any values legal */
+ SAHPI_TL_TYPE_BCDPLUS, /* String of 0-9, space, dash, period ONLY */
+ SAHPI_TL_TYPE_ASCII6, /* Reduced ASCII character set: 0x20-0x5F
+ ONLY */
+ SAHPI_TL_TYPE_LANGUAGE /* ASCII or UNICODE depending on language */
+} SaHpiTextTypeT;
+
+typedef struct {
+ SaHpiTextTypeT DataType;
+ SaHpiLanguageT Language; /* Language the text is in. */
+ SaHpiUint8T DataLength; /* Bytes used in Data buffer */
+ SaHpiUint8T Data[SAHPI_MAX_TEXT_BUFFER_LENGTH]; /* Data buffer */
+} SaHpiTextBufferT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Entities **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+/*
+** Entity Types
+**
+** Entities are used to associate specific hardware components with sensors,
+** controls, watchdogs, or resources. Entities are defined with an entity
+** type enumeration, and an entity instance number (to distinguish between
+** multiple instances of a particular type of entity; e.g., multiple power
+** supplies in a system).
+**
+** Entities are uniquely identified in a system with an ordered series of
+** Entity Type / Entity Instance pairs called an "Entity Path". Each subsequent
+** Entity Type/Entity Instance in the path is the next higher "containing"
+** entity. The "root" of the Entity Path (the outermost level of containment)
+** is designated with an Entity Type of SAHPI_ENT_ROOT if the entire Entity Path
+** is fewer than SAHPI_MAX_ENTITY_PATH entries in length.
+**
+** Enumerated Entity Types include those types enumerated by the IPMI Consortium
+** for IPMI-managed entities, as well as additional types defined by the
+** HPI specification. Room is left in the enumeration for the inclusion of
+** Entity Types taken from other lists, if needed in the future.
+*/
+/* Base values for entity types from various sources. */
+#define SAHPI_ENT_IPMI_GROUP 0
+#define SAHPI_ENT_SAFHPI_GROUP 0x10000
+#define SAHPI_ENT_ROOT_VALUE 0xFFFF
+typedef enum
+{
+ SAHPI_ENT_UNSPECIFIED = SAHPI_ENT_IPMI_GROUP,
+ SAHPI_ENT_OTHER,
+ SAHPI_ENT_UNKNOWN,
+ SAHPI_ENT_PROCESSOR,
+ SAHPI_ENT_DISK_BAY, /* Disk or disk bay */
+ SAHPI_ENT_PERIPHERAL_BAY,
+ SAHPI_ENT_SYS_MGMNT_MODULE, /* System management module */
+ SAHPI_ENT_SYSTEM_BOARD, /* Main system board, may also be
+ processor board and/or internal
+ expansion board */
+ SAHPI_ENT_MEMORY_MODULE, /* Board holding memory devices */
+ SAHPI_ENT_PROCESSOR_MODULE, /* Holds processors, use this
+ designation when processors are not
+ mounted on system board */
+ SAHPI_ENT_POWER_SUPPLY, /* Main power supply (supplies) for the
+ system */
+ SAHPI_ENT_ADD_IN_CARD,
+ SAHPI_ENT_FRONT_PANEL_BOARD, /* Control panel */
+ SAHPI_ENT_BACK_PANEL_BOARD,
+ SAHPI_ENT_POWER_SYSTEM_BOARD,
+ SAHPI_ENT_DRIVE_BACKPLANE,
+ SAHPI_ENT_SYS_EXPANSION_BOARD, /* System internal expansion board
+ (contains expansion slots). */
+ SAHPI_ENT_OTHER_SYSTEM_BOARD, /* Part of board set */
+ SAHPI_ENT_PROCESSOR_BOARD, /* Holds 1 or more processors. Includes
+ boards that hold SECC modules) */
+ SAHPI_ENT_POWER_UNIT, /* Power unit / power domain (typically
+ used as a pre-defined logical entity
+ for grouping power supplies)*/
+ SAHPI_ENT_POWER_MODULE, /* Power module / DC-to-DC converter.
+ Use this value for internal
+ converters. Note: You should use
+ entity ID (power supply) for the
+ main power supply even if the main
+ supply is a DC-to-DC converter */
+ SAHPI_ENT_POWER_MGMNT, /* Power management/distribution
+ board */
+ SAHPI_ENT_CHASSIS_BACK_PANEL_BOARD,
+ SAHPI_ENT_SYSTEM_CHASSIS,
+ SAHPI_ENT_SUB_CHASSIS,
+ SAHPI_ENT_OTHER_CHASSIS_BOARD,
+ SAHPI_ENT_DISK_DRIVE_BAY,
+ SAHPI_ENT_PERIPHERAL_BAY_2,
+ SAHPI_ENT_DEVICE_BAY,
+ SAHPI_ENT_COOLING_DEVICE, /* Fan/cooling device */
+ SAHPI_ENT_COOLING_UNIT, /* Can be used as a pre-defined logical
+ entity for grouping fans or other
+ cooling devices. */
+ SAHPI_ENT_INTERCONNECT, /* Cable / interconnect */
+ SAHPI_ENT_MEMORY_DEVICE, /* This Entity ID should be used for
+ replaceable memory devices, e.g.
+ DIMM/SIMM. It is recommended that
+ Entity IDs not be used for
+ individual non-replaceable memory
+ devices. Rather, monitoring and
+ error reporting should be associated
+ with the FRU [e.g. memory card]
+ holding the memory. */
+ SAHPI_ENT_SYS_MGMNT_SOFTWARE, /* System Management Software */
+ SAHPI_ENT_BIOS,
+ SAHPI_ENT_OPERATING_SYSTEM,
+ SAHPI_ENT_SYSTEM_BUS,
+ SAHPI_ENT_GROUP, /* This is a logical entity for use with
+ Entity Association records. It is
+ provided to allow a sensor data
+ record to point to an entity-
+ association record when there is no
+ appropriate pre-defined logical
+ entity for the entity grouping.
+ This Entity should not be used as a
+ physical entity. */
+ SAHPI_ENT_REMOTE, /* Out of band management communication
+ device */
+ SAHPI_ENT_EXTERNAL_ENVIRONMENT,
+ SAHPI_ENT_BATTERY,
+ SAHPI_ENT_CHASSIS_SPECIFIC = SAHPI_ENT_IPMI_GROUP + 0x90,
+ SAHPI_ENT_BOARD_SET_SPECIFIC = SAHPI_ENT_IPMI_GROUP + 0xB0,
+ SAHPI_ENT_OEM_SYSINT_SPECIFIC = SAHPI_ENT_IPMI_GROUP + 0xD0,
+ SAHPI_ENT_ROOT = SAHPI_ENT_ROOT_VALUE,
+ SAHPI_ENT_RACK = SAHPI_ENT_SAFHPI_GROUP,
+ SAHPI_ENT_SUBRACK,
+ SAHPI_ENT_COMPACTPCI_CHASSIS,
+ SAHPI_ENT_ADVANCEDTCA_CHASSIS,
+ SAHPI_ENT_SYSTEM_SLOT,
+ SAHPI_ENT_SBC_BLADE,
+ SAHPI_ENT_IO_BLADE,
+ SAHPI_ENT_DISK_BLADE,
+ SAHPI_ENT_DISK_DRIVE,
+ SAHPI_ENT_FAN,
+ SAHPI_ENT_POWER_DISTRIBUTION_UNIT,
+ SAHPI_ENT_SPEC_PROC_BLADE, /* Special Processing Blade,
+ including DSP */
+ SAHPI_ENT_IO_SUBBOARD, /* I/O Sub-Board, including
+ PMC I/O board */
+ SAHPI_ENT_SBC_SUBBOARD, /* SBC Sub-Board, including PMC
+ SBC board */
+ SAHPI_ENT_ALARM_MANAGER, /* Chassis alarm manager board */
+ SAHPI_ENT_ALARM_MANAGER_BLADE, /* Blade-based alarm manager */
+ SAHPI_ENT_SUBBOARD_CARRIER_BLADE /* Includes PMC Carrier Blade --
+ Use only if "carrier" is only
+ function of blade. Else use
+ primary function (SBC_BLADE,
+ DSP_BLADE, etc.). */
+ } SaHpiEntityTypeT;
+
+typedef SaHpiUint32T SaHpiEntityInstanceT;
+
+typedef struct {
+ SaHpiEntityTypeT EntityType;
+ SaHpiEntityInstanceT EntityInstance;
+} SaHpiEntityT;
+
+#define SAHPI_MAX_ENTITY_PATH 16
+
+typedef struct {
+ SaHpiEntityT Entry[SAHPI_MAX_ENTITY_PATH];
+} SaHpiEntityPathT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Events, part 1 **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** Category
+**
+** Sensor events contain an event category and event state. Depending on the
+** event category, the event states take on different meanings for events
+** generated by specific sensors.
+**
+** The SAHPI_EC_GENERIC category can be used for discrete sensors which have
+** state meanings other than those identified with other event categories.
+*/
+typedef SaHpiUint8T SaHpiEventCategoryT;
+
+#define SAHPI_EC_UNSPECIFIED (SaHpiEventCategoryT)0x00 /* Unspecified */
+#define SAHPI_EC_THRESHOLD (SaHpiEventCategoryT)0x01 /* Threshold
+ events */
+#define SAHPI_EC_USAGE (SaHpiEventCategoryT)0x02 /* Usage state
+ events */
+#define SAHPI_EC_STATE (SaHpiEventCategoryT)0x03 /* Generic state
+ events */
+#define SAHPI_EC_PRED_FAIL (SaHpiEventCategoryT)0x04 /* Predictive fail
+ events */
+#define SAHPI_EC_LIMIT (SaHpiEventCategoryT)0x05 /* Limit events */
+#define SAHPI_EC_PERFORMANCE (SaHpiEventCategoryT)0x06 /* Performance
+ events */
+#define SAHPI_EC_SEVERITY (SaHpiEventCategoryT)0x07 /* Severity
+ indicating
+ events */
+#define SAHPI_EC_PRESENCE (SaHpiEventCategoryT)0x08 /* Device presence
+ events */
+#define SAHPI_EC_ENABLE (SaHpiEventCategoryT)0x09 /* Device enabled
+ events */
+#define SAHPI_EC_AVAILABILITY (SaHpiEventCategoryT)0x0A /* Availability
+ state events */
+
+#define SAHPI_EC_REDUNDANCY (SaHpiEventCategoryT)0x0B /* Redundancy
+ state events */
+#define SAHPI_EC_USER (SaHpiEventCategoryT)0x7E /* User defined
+ events */
+#define SAHPI_EC_GENERIC (SaHpiEventCategoryT)0x7F /* OEM defined
+ events */
+
+/*
+** Event States
+**
+** The following event states are specified relative to the categories listed
+** above. The event types are only valid for their given category. Each set of
+** events is labeled as to which category it belongs to.
+** Each event will have only one event state associated with it. When retrieving
+** the event status or event enabled status a bit mask of all applicable event
+** states is used. Similarly, when setting the event enabled status a bit mask
+** of all applicable event states is used.
+*/
+typedef SaHpiUint16T SaHpiEventStateT;
+
+/*
+** SaHpiEventCategoryT == <any>
+*/
+#define SAHPI_ES_UNSPECIFIED (SaHpiEventStateT)0x0000
+
+/*
+** SaHpiEventCategoryT == SAHPI_EC_THRESHOLD
+** When using these event states, the event state should match
+** the event severity (for example SAHPI_ES_LOWER_MINOR should have an
+** event severity of SAHPI_MINOR).
+*/
+#define SAHPI_ES_LOWER_MINOR (SaHpiEventStateT)0x0001
+#define SAHPI_ES_LOWER_MAJOR (SaHpiEventStateT)0x0002
+#define SAHPI_ES_LOWER_CRIT (SaHpiEventStateT)0x0004
+#define SAHPI_ES_UPPER_MINOR (SaHpiEventStateT)0x0008
+#define SAHPI_ES_UPPER_MAJOR (SaHpiEventStateT)0x0010
+#define SAHPI_ES_UPPER_CRIT (SaHpiEventStateT)0x0020
+
+/* SaHpiEventCategoryT == SAHPI_EC_USAGE */
+#define SAHPI_ES_IDLE (SaHpiEventStateT)0x0001
+#define SAHPI_ES_ACTIVE (SaHpiEventStateT)0x0002
+#define SAHPI_ES_BUSY (SaHpiEventStateT)0x0004
+
+/* SaHpiEventCategoryT == SAHPI_EC_STATE */
+#define SAHPI_ES_STATE_DEASSERTED (SaHpiEventStateT)0x0001
+#define SAHPI_ES_STATE_ASSERTED (SaHpiEventStateT)0x0002
+
+/* SaHpiEventCategoryT == SAHPI_EC_PRED_FAIL */
+#define SAHPI_ES_PRED_FAILURE_DEASSERT (SaHpiEventStateT)0x0001
+#define SAHPI_ES_PRED_FAILURE_ASSERT (SaHpiEventStateT)0x0002
+
+/* SaHpiEventCategoryT == SAHPI_EC_LIMIT */
+#define SAHPI_ES_LIMIT_NOT_EXCEEDED (SaHpiEventStateT)0x0001
+#define SAHPI_ES_LIMIT_EXCEEDED (SaHpiEventStateT)0x0002
+
+/* SaHpiEventCategoryT == SAHPI_EC_PERFORMANCE */
+#define SAHPI_ES_PERFORMANCE_MET (SaHpiEventStateT)0x0001
+#define SAHPI_ES_PERFORMANCE_LAGS (SaHpiEventStateT)0x0002
+
+/*
+** SaHpiEventCategoryT == SAHPI_EC_SEVERITY
+** When using these event states, the event state should match
+** the event severity
+*/
+#define SAHPI_ES_OK (SaHpiEventStateT)0x0001
+#define SAHPI_ES_MINOR_FROM_OK (SaHpiEventStateT)0x0002
+#define SAHPI_ES_MAJOR_FROM_LESS (SaHpiEventStateT)0x0004
+#define SAHPI_ES_CRITICAL_FROM_LESS (SaHpiEventStateT)0x0008
+#define SAHPI_ES_MINOR_FROM_MORE (SaHpiEventStateT)0x0010
+#define SAHPI_ES_MAJOR_FROM_CRITICAL (SaHpiEventStateT)0x0020
+#define SAHPI_ES_CRITICAL (SaHpiEventStateT)0x0040
+#define SAHPI_ES_MONITOR (SaHpiEventStateT)0x0080
+#define SAHPI_ES_INFORMATIONAL (SaHpiEventStateT)0x0100
+
+/* SaHpiEventCategoryT == SAHPI_EC_PRESENCE */
+#define SAHPI_ES_ABSENT (SaHpiEventStateT)0x0001
+#define SAHPI_ES_PRESENT (SaHpiEventStateT)0x0002
+
+/* SaHpiEventCategoryT == SAHPI_EC_ENABLE */
+#define SAHPI_ES_DISABLED (SaHpiEventStateT)0x0001
+#define SAHPI_ES_ENABLED (SaHpiEventStateT)0x0002
+
+/* SaHpiEventCategoryT == SAHPI_EC_AVAILABILITY */
+#define SAHPI_ES_RUNNING (SaHpiEventStateT)0x0001
+#define SAHPI_ES_TEST (SaHpiEventStateT)0x0002
+#define SAHPI_ES_POWER_OFF (SaHpiEventStateT)0x0004
+#define SAHPI_ES_ON_LINE (SaHpiEventStateT)0x0008
+#define SAHPI_ES_OFF_LINE (SaHpiEventStateT)0x0010
+#define SAHPI_ES_OFF_DUTY (SaHpiEventStateT)0x0020
+#define SAHPI_ES_DEGRADED (SaHpiEventStateT)0x0040
+#define SAHPI_ES_POWER_SAVE (SaHpiEventStateT)0x0080
+#define SAHPI_ES_INSTALL_ERROR (SaHpiEventStateT)0x0100
+
+/* SaHpiEventCategoryT == SAHPI_EC_REDUNDANCY */
+#define SAHPI_ES_FULLY_REDUNDANT (SaHpiEventStateT)0x0001
+#define SAHPI_ES_REDUNDANCY_LOST (SaHpiEventStateT)0x0002
+#define SAHPI_ES_REDUNDANCY_DEGRADED (SaHpiEventStateT)0x0004
+#define SAHPI_ES_REDUNDANCY_LOST_SUFFICIENT_RESOURCES \
+ (SaHpiEventStateT)0x0008
+#define SAHPI_ES_NON_REDUNDANT_SUFFICIENT_RESOURCES \
+ (SaHpiEventStateT)0x0010
+#define SAHPI_ES_NON_REDUNDANT_INSUFFICIENT_RESOURCES \
+ (SaHpiEventStateT)0x0020
+#define SAHPI_ES_REDUNDANCY_DEGRADED_FROM_FULL (SaHpiEventStateT)0x0040
+#define SAHPI_ES_REDUNDANCY_DEGRADED_FROM_NON (SaHpiEventStateT)0x0080
+
+/*
+** SaHpiEventCategoryT == SAHPI_EC_GENERIC || SAHPI_EC_USER
+** These event states are defined by the OEM or the user of the
+** implementation.
+*/
+#define SAHPI_ES_STATE_00 (SaHpiEventStateT)0x0001
+#define SAHPI_ES_STATE_01 (SaHpiEventStateT)0x0002
+#define SAHPI_ES_STATE_02 (SaHpiEventStateT)0x0004
+#define SAHPI_ES_STATE_03 (SaHpiEventStateT)0x0008
+#define SAHPI_ES_STATE_04 (SaHpiEventStateT)0x0010
+#define SAHPI_ES_STATE_05 (SaHpiEventStateT)0x0020
+#define SAHPI_ES_STATE_06 (SaHpiEventStateT)0x0040
+#define SAHPI_ES_STATE_07 (SaHpiEventStateT)0x0080
+#define SAHPI_ES_STATE_08 (SaHpiEventStateT)0x0100
+#define SAHPI_ES_STATE_09 (SaHpiEventStateT)0x0200
+#define SAHPI_ES_STATE_10 (SaHpiEventStateT)0x0400
+#define SAHPI_ES_STATE_11 (SaHpiEventStateT)0x0800
+#define SAHPI_ES_STATE_12 (SaHpiEventStateT)0x1000
+#define SAHPI_ES_STATE_13 (SaHpiEventStateT)0x2000
+#define SAHPI_ES_STATE_14 (SaHpiEventStateT)0x4000
+
+
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Sensors **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* Sensor Number */
+typedef SaHpiUint8T SaHpiSensorNumT;
+
+/* Type of Sensor */
+typedef enum {
+ SAHPI_TEMPERATURE = 0x01,
+ SAHPI_VOLTAGE,
+ SAHPI_CURRENT,
+ SAHPI_FAN,
+ SAHPI_PHYSICAL_SECURITY,
+ SAHPI_PLATFORM_VIOLATION,
+ SAHPI_PROCESSOR,
+ SAHPI_POWER_SUPPLY,
+ SAHPI_POWER_UNIT,
+ SAHPI_COOLING_DEVICE,
+ SAHPI_OTHER_UNITS_BASED_SENSOR,
+ SAHPI_MEMORY,
+ SAHPI_DRIVE_SLOT,
+ SAHPI_POST_MEMORY_RESIZE,
+ SAHPI_SYSTEM_FW_PROGRESS,
+ SAHPI_EVENT_LOGGING_DISABLED,
+ SAHPI_RESERVED1,
+ SAHPI_SYSTEM_EVENT,
+ SAHPI_CRITICAL_INTERRUPT,
+ SAHPI_BUTTON,
+ SAHPI_MODULE_BOARD,
+ SAHPI_MICROCONTROLLER_COPROCESSOR,
+ SAHPI_ADDIN_CARD,
+ SAHPI_CHASSIS,
+ SAHPI_CHIP_SET,
+ SAHPI_OTHER_FRU,
+ SAHPI_CABLE_INTERCONNECT,
+ SAHPI_TERMINATOR,
+ SAHPI_SYSTEM_BOOT_INITIATED,
+ SAHPI_BOOT_ERROR,
+ SAHPI_OS_BOOT,
+ SAHPI_OS_CRITICAL_STOP,
+ SAHPI_SLOT_CONNECTOR,
+ SAHPI_SYSTEM_ACPI_POWER_STATE,
+ SAHPI_RESERVED2,
+ SAHPI_PLATFORM_ALERT,
+ SAHPI_ENTITY_PRESENCE,
+ SAHPI_MONITOR_ASIC_IC,
+ SAHPI_LAN,
+ SAHPI_MANAGEMENT_SUBSYSTEM_HEALTH,
+ SAHPI_BATTERY,
+ SAHPI_OPERATIONAL = 0xA0,
+ SAHPI_OEM_SENSOR=0xC0
+} SaHpiSensorTypeT;
+
+/*
+** Interpreted Sensor Reading Type
+**
+** These definitions list the available data types that can be
+** used for interpreted sensor readings. Interpreted sensor readings are provided
+** because typically sensors measure their associated entities in a way that is
+** not human readable/understandable. For example a fan sensor may measure the
+** number of ticks that it takes a fan blade to move passed a sensor. The human
+** readable reading type would be revolutions per minute (RPM).
+*/
+
+#define SAHPI_SENSOR_BUFFER_LENGTH 32
+
+typedef enum {
+ SAHPI_SENSOR_INTERPRETED_TYPE_UINT8,
+ SAHPI_SENSOR_INTERPRETED_TYPE_UINT16,
+ SAHPI_SENSOR_INTERPRETED_TYPE_UINT32,
+ SAHPI_SENSOR_INTERPRETED_TYPE_INT8,
+ SAHPI_SENSOR_INTERPRETED_TYPE_INT16,
+ SAHPI_SENSOR_INTERPRETED_TYPE_INT32,
+ SAHPI_SENSOR_INTERPRETED_TYPE_FLOAT32,
+ SAHPI_SENSOR_INTERPRETED_TYPE_BUFFER /* 32 byte array */
+} SaHpiSensorInterpretedTypeT;
+
+typedef union {
+ SaHpiUint8T SensorUint8;
+ SaHpiUint16T SensorUint16;
+ SaHpiUint32T SensorUint32;
+ SaHpiInt8T SensorInt8;
+ SaHpiInt16T SensorInt16;
+ SaHpiInt32T SensorInt32;
+ SaHpiFloat32T SensorFloat32;
+ SaHpiUint8T SensorBuffer[SAHPI_SENSOR_BUFFER_LENGTH];
+} SaHpiSensorInterpretedUnionT;
+
+typedef struct {
+ SaHpiSensorInterpretedTypeT Type;
+ SaHpiSensorInterpretedUnionT Value;
+} SaHpiSensorInterpretedT;
+
+/*
+** Sensor Status
+**
+** The sensor status structure is used to determine if sensor scanning is
+** enabled and if events are enabled. If events are enabled, the structure will
+** have valid data for the outstanding sensor event states.
+*/
+typedef SaHpiUint8T SaHpiSensorStatusT;
+#define SAHPI_SENSTAT_EVENTS_ENABLED (SaHpiSensorStatusT)0x80
+#define SAHPI_SENSTAT_SCAN_ENABLED (SaHpiSensorStatusT)0x40
+#define SAHPI_SENSTAT_BUSY (SaHpiSensorStatusT)0x20
+
+typedef struct {
+ SaHpiSensorStatusT SensorStatus;
+ SaHpiEventStateT EventStatus;
+} SaHpiSensorEvtStatusT;
+
+/* Sensor Event Enables */
+typedef struct {
+ SaHpiSensorStatusT SensorStatus;
+ SaHpiEventStateT AssertEvents;
+ SaHpiEventStateT DeassertEvents;
+} SaHpiSensorEvtEnablesT;
+
+/*
+** Sensor Reading
+**
+** The sensor reading type is the data structure returned from a call to get
+** sensor reading. The structure is also used when setting and getting sensor
+** threshold values and reporting sensor ranges.
+** Each sensor may support one or more of raw, interpreted, or event status
+** representations of the sensor data. For analog sensors the raw value is the
+** raw value from the sensor (such as ticks per fan blade) and the interpreted
+** value is the raw value converted in to a usable format (such as RPM). The
+** interpreted value can be calculated by the HPI implementation using the
+** sensor factors or by another OEM means.
+*/
+typedef SaHpiUint8T SaHpiSensorReadingFormatsT;
+#define SAHPI_SRF_RAW (SaHpiSensorReadingFormatsT)0x01
+#define SAHPI_SRF_INTERPRETED (SaHpiSensorReadingFormatsT)0x02
+#define SAHPI_SRF_EVENT_STATE (SaHpiSensorReadingFormatsT)0x04
+
+typedef struct {
+ SaHpiSensorReadingFormatsT ValuesPresent;
+ SaHpiUint32T Raw;
+ SaHpiSensorInterpretedT Interpreted;
+ SaHpiSensorEvtStatusT EventStatus;
+} SaHpiSensorReadingT;
+
+/*
+** Threshold Values
+** This structure encompasses all of the thresholds that can be set.
+*/
+typedef struct {
+ SaHpiSensorReadingT LowCritical; /* Lower Critical Threshold */
+ SaHpiSensorReadingT LowMajor; /* Lower Major Threshold */
+ SaHpiSensorReadingT LowMinor; /* Lower Minor Threshold */
+ SaHpiSensorReadingT UpCritical; /* Upper critical Threshold */
+ SaHpiSensorReadingT UpMajor; /* Upper major Threshold */
+ SaHpiSensorReadingT UpMinor; /* Upper minor Threshold */
+ SaHpiSensorReadingT PosThdHysteresis; /* Positive Threshold Hysteresis */
+ SaHpiSensorReadingT NegThdHysteresis; /* Negative Threshold Hysteresis */
+}SaHpiSensorThresholdsT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Sensor Resource Data Records **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** Sensor Factors
+**
+** The sensor factors structure defines the conversion factors for linear and
+** linearized sensors.
+** The SaHpiSensorLinearizationT enumeration coupled with the various other
+** sensor factors define a formula that can be applied to raw sensor data to
+** convert it to appropriate engineering units. If linearization is
+** SAHPI_SL_NONLINEAR, SAHPI_SL_UNSPECIFIED, or SAHPI_SL_OEM then there is no
+** predefined conversion from raw to interpreted and the sensor factors may or
+** may not be meaningful depending on the implementation.
+** For other linearization values, raw readings may be converted to interpreted
+** values using the formula:
+**Interpreted = L [( M*raw + B*10^ExpB )*10^ExpR ]
+**where "L[x]" is the indicated linearization function
+** (for SAHPI_SL_LINEAR, L[x]=x).
+** The Tolerance Factor is given as +/- 1/2 raw counts, so tolerance in
+** interpreted values can be calculated as:
+** L[ M * ToleranceFactor/2 * 10^ExpR ]
+** The Accuracy Factor is given as 1/100 of a percent, scaled up by ExpA. Thus
+** the accuracy is:
+**( ( AccuracyFactor/100 ) / 10^ExpA )%
+*/
+typedef enum {
+ SAHPI_SL_LINEAR = 0, /* Already linear */
+ SAHPI_SL_LN,
+ SAHPI_SL_LOG10,
+ SAHPI_SL_LOG2,
+ SAHPI_SL_E,
+ SAHPI_SL_EXP10,
+ SAHPI_SL_EXP2,
+ SAHPI_SL_1OVERX,
+ SAHPI_SL_SQRX,
+ SAHPI_SL_CUBEX,
+ SAHPI_SL_SQRTX,
+ SAHPI_SL_CUBERTX,
+ SAHPI_SL_NONLINEAR = 0x70, /* Cannot be linearized with a predefind formula*/
+ SAHPI_SL_OEM,
+ SAHPI_SL_UNSPECIFIED = 0xFF
+} SaHpiSensorLinearizationT;
+
+typedef struct {
+ SaHpiInt16T M_Factor; /* M Factor */
+ SaHpiInt16T B_Factor; /* B Factor */
+ SaHpiUint16T AccuracyFactor; /* Accuracy */
+ SaHpiUint8T ToleranceFactor; /* Tolerance */
+ SaHpiUint8T ExpA; /* Accuracy Exp */
+ SaHpiInt8T ExpR; /* Result Exp */
+ SaHpiInt8T ExpB; /* B Exp */
+ SaHpiSensorLinearizationT Linearization;
+} SaHpiSensorFactorsT;
+
+/*
+** Sensor Range
+** Sensor range values can include minimum, maximum, normal minimum, normal
+** maximum, and nominal values.
+*/
+typedef SaHpiUint8T SaHpiSensorRangeFlagsT;
+#define SAHPI_SRF_MIN (SaHpiSensorRangeFlagsT)0x10
+#define SAHPI_SRF_MAX (SaHpiSensorRangeFlagsT)0x08
+#define SAHPI_SRF_NORMAL_MIN (SaHpiSensorRangeFlagsT)0x04
+#define SAHPI_SRF_NORMAL_MAX (SaHpiSensorRangeFlagsT)0x02
+#define SAHPI_SRF_NOMINAL (SaHpiSensorRangeFlagsT)0x01
+
+typedef struct {
+ SaHpiSensorRangeFlagsT Flags;
+ SaHpiSensorReadingT Max;
+ SaHpiSensorReadingT Min;
+ SaHpiSensorReadingT Nominal;
+ SaHpiSensorReadingT NormalMax;
+ SaHpiSensorReadingT NormalMin;
+} SaHpiSensorRangeT;
+
+/*
+** Sensor Units
+** This is a list of all the sensor units supported by HPI.
+*/
+typedef enum {
+ SAHPI_SU_UNSPECIFIED = 0, SAHPI_SU_DEGREES_C, SAHPI_SU_DEGREES_F,
+ SAHPI_SU_DEGREES_K, SAHPI_SU_VOLTS, SAHPI_SU_AMPS,
+ SAHPI_SU_WATTS, SAHPI_SU_JOULES, SAHPI_SU_COULOMBS,
+ SAHPI_SU_VA, SAHPI_SU_NITS, SAHPI_SU_LUMEN,
+ SAHPI_SU_LUX, SAHPI_SU_CANDELA, SAHPI_SU_KPA,
+ SAHPI_SU_PSI, SAHPI_SU_NEWTON, SAHPI_SU_CFM,
+ SAHPI_SU_RPM, SAHPI_SU_HZ, SAHPI_SU_MICROSECOND,
+ SAHPI_SU_MILLISECOND, SAHPI_SU_SECOND, SAHPI_SU_MINUTE,
+ SAHPI_SU_HOUR, SAHPI_SU_DAY, SAHPI_SU_WEEK,
+ SAHPI_SU_MIL, SAHPI_SU_INCHES, SAHPI_SU_FEET,
+ SAHPI_SU_CU_IN, SAHPI_SU_CU_FEET, SAHPI_SU_MM,
+ SAHPI_SU_CM, SAHPI_SU_M, SAHPI_SU_CU_CM,
+ SAHPI_SU_CU_M, SAHPI_SU_LITERS, SAHPI_SU_FLUID_OUNCE,
+ SAHPI_SU_RADIANS, SAHPI_SU_STERADIANS, SAHPI_SU_REVOLUTIONS,
+ SAHPI_SU_CYCLES, SAHPI_SU_GRAVITIES, SAHPI_SU_OUNCE,
+ SAHPI_SU_POUND, SAHPI_SU_FT_LB, SAHPI_SU_OZ_IN,
+ SAHPI_SU_GAUSS, SAHPI_SU_GILBERTS, SAHPI_SU_HENRY,
+ SAHPI_SU_MILLIHENRY, SAHPI_SU_FARAD, SAHPI_SU_MICROFARAD,
+ SAHPI_SU_OHMS, SAHPI_SU_SIEMENS, SAHPI_SU_MOLE,
+ SAHPI_SU_BECQUEREL, SAHPI_SU_PPM, SAHPI_SU_RESERVED,
+ SAHPI_SU_DECIBELS, SAHPI_SU_DBA, SAHPI_SU_DBC,
+ SAHPI_SU_GRAY, SAHPI_SU_SIEVERT, SAHPI_SU_COLOR_TEMP_DEG_K,
+ SAHPI_SU_BIT, SAHPI_SU_KILOBIT, SAHPI_SU_MEGABIT,
+ SAHPI_SU_GIGABIT, SAHPI_SU_BYTE, SAHPI_SU_KILOBYTE,
+ SAHPI_SU_MEGABYTE, SAHPI_SU_GIGABYTE, SAHPI_SU_WORD,
+ SAHPI_SU_DWORD, SAHPI_SU_QWORD, SAHPI_SU_LINE,
+ SAHPI_SU_HIT, SAHPI_SU_MISS, SAHPI_SU_RETRY,
+ SAHPI_SU_RESET, SAHPI_SU_OVERRUN, SAHPI_SU_UNDERRUN,
+ SAHPI_SU_COLLISION, SAHPI_SU_PACKETS, SAHPI_SU_MESSAGES,
+ SAHPI_SU_CHARACTERS, SAHPI_SU_ERRORS, SAHPI_SU_CORRECTABLE_ERRORS,
+ SAHPI_SU_UNCORRECTABLE_ERRORS
+} SaHpiSensorUnitsT;
+
+/*
+** Modifier Unit Use
+** This type defines how the modifier unit is used. For example: base unit ==
+** meter, modifier unit == seconds, and modifier unit use ==
+** SAHPI_SMUU_BASIC_OVER_MODIFIER. The resulting unit would be meters per second.
+*/
+typedef enum {
+ SAHPI_SMUU_NONE = 0,
+ SAHPI_SMUU_BASIC_OVER_MODIFIER, /* Basic Unit / Modifier Unit */
+ SAHPI_SMUU_BASIC_TIMES_MODIFIER /* Basic Unit * Modifier Unit */
+} SaHpiSensorModUnitUseT;
+
+/*
+** Sign Format
+** This type defines what the sign format of the sensor's raw value is (1's
+** complement, unsigned, etc.).
+*/
+typedef enum {
+ SAHPI_SDF_UNSIGNED = 0,
+ SAHPI_SDF_1S_COMPLEMENT,
+ SAHPI_SDF_2S_COMPLEMENT
+} SaHpiSensorSignFormatT;
+
+/*
+** Data Format
+** This structure encapsulates all of the various types that make up the
+** definition of sensor data.
+*/
+typedef struct {
+ SaHpiSensorReadingFormatsT ReadingFormats; /* Indicates if sensor supports
+ readings in raw, interpreted,
+ and/or event status formats */
+ SaHpiBoolT IsNumeric; /* If FALSE, rest of this
+ structure is not
+ meaningful */
+ SaHpiSensorSignFormatT SignFormat; /* Signed format */
+ SaHpiSensorUnitsT BaseUnits; /* Base units (meters, etc.) */
+ SaHpiSensorUnitsT ModifierUnits; /* Modifier unit (second, etc.) */
+ SaHpiSensorModUnitUseT ModifierUse; /* Modifier use(m/sec, etc.) */
+ SaHpiBoolT FactorsStatic; /* True if the sensor factors
+ are static. If false
+ factors vary over sensor
+ range, and are not
+ accessible through HPI */
+ SaHpiSensorFactorsT Factors;
+ SaHpiBoolT Percentage; /* Is value a percentage */
+ SaHpiSensorRangeT Range; /* Valid range of sensor */
+} SaHpiSensorDataFormatT;
+
+/*
+** Threshold Support
+**
+** These types define what threshold values are readable, writable, and fixed.
+** It also defines how the threshold values are read and written.
+*/
+typedef SaHpiUint8T SaHpiSensorThdMaskT;
+#define SAHPI_STM_LOW_MINOR (SaHpiSensorThdMaskT)0x01
+#define SAHPI_STM_LOW_MAJOR (SaHpiSensorThdMaskT)0x02
+#define SAHPI_STM_LOW_CRIT (SaHpiSensorThdMaskT)0x04
+#define SAHPI_STM_UP_MINOR (SaHpiSensorThdMaskT)0x08
+#define SAHPI_STM_UP_MAJOR (SaHpiSensorThdMaskT)0x10
+#define SAHPI_STM_UP_CRIT (SaHpiSensorThdMaskT)0x20
+#define SAHPI_STM_UP_HYSTERESIS (SaHpiSensorThdMaskT)0x40
+#define SAHPI_STM_LOW_HYSTERESIS (SaHpiSensorThdMaskT)0x80
+
+typedef SaHpiUint8T SaHpiSensorThdCapT;
+#define SAHPI_STC_RAW (SaHpiSensorThdMaskT)0x01 /* read/write as
+ raw counts */
+#define SAHPI_STC_INTERPRETED (SaHpiSensorThdMaskT)0x02 /* read/write as
+ interpreted */
+
+typedef struct {
+ SaHpiBoolT IsThreshold; /* True if the sensor
+ supports thresholds. If false,
+ rest of structure is not
+ meaningful. */
+ SaHpiSensorThdCapT TholdCapabilities;
+ SaHpiSensorThdMaskT ReadThold; /* Readable thresholds */
+ SaHpiSensorThdMaskT WriteThold; /* Writable thresholds */
+ SaHpiSensorThdMaskT FixedThold; /* Fixed thresholds */
+} SaHpiSensorThdDefnT;
+
+/*
+** Event Control
+**
+** This type defines how sensor event messages can be controlled (can be turned
+** off and on for each type of event, etc.).
+*/
+typedef enum {
+ SAHPI_SEC_PER_EVENT = 0, /* Event message control per event */
+ SAHPI_SEC_ENTIRE_SENSOR, /* Control for entire sensor only */
+ SAHPI_SEC_GLOBAL_DISABLE, /* Global disable of events only */
+ SAHPI_SEC_NO_EVENTS /* Events not supported */
+} SaHpiSensorEventCtrlT;
+
+/*
+** Record
+**
+** This is the sensor resource data record which describes all of the static
+** data associated with a sensor.
+*/
+typedef struct {
+ SaHpiSensorNumT Num; /* Sensor Number/Index */
+ SaHpiSensorTypeT Type; /* General Sensor Type */
+ SaHpiEventCategoryT Category; /* Event category */
+ SaHpiSensorEventCtrlT EventCtrl; /* How events can be controlled */
+ SaHpiEventStateT Events; /* Bit mask of event states
+ supported */
+ SaHpiBoolT Ignore; /* Ignore sensor (entity not
+ present, disabled, etc.) */
+ SaHpiSensorDataFormatT DataFormat; /* Format of the data */
+ SaHpiSensorThdDefnT ThresholdDefn; /* Threshold Definition */
+ SaHpiUint32T Oem; /* Reserved for OEM use */
+} SaHpiSensorRecT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Aggregate Status **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* These are the default sensor numbers for aggregate status. */
+#define SAHPI_DEFAGSENS_OPER (SaHpiSensorNumT)0xFE
+#define SAHPI_DEFAGSENS_PWR (SaHpiSensorNumT)0xFD
+#define SAHPI_DEFAGSENS_TEMP (SaHpiSensorNumT)0xFC
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Controls **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* Control Number */
+typedef SaHpiUint8T SaHpiCtrlNumT;
+
+/*
+** Type of Control
+**
+** This enumerated type defines the different types of generic controls.
+*/
+typedef enum {
+ SAHPI_CTRL_TYPE_DIGITAL = 0x00,
+ SAHPI_CTRL_TYPE_DISCRETE,
+ SAHPI_CTRL_TYPE_ANALOG,
+ SAHPI_CTRL_TYPE_STREAM,
+ SAHPI_CTRL_TYPE_TEXT,
+ SAHPI_CTRL_TYPE_OEM = 0xC0
+} SaHpiCtrlTypeT;
+
+/*
+** Control State Type Definitions
+**
+** Defines the types of control states.
+*/
+typedef enum {
+ SAHPI_CTRL_STATE_OFF = 0,
+ SAHPI_CTRL_STATE_ON,
+ SAHPI_CTRL_STATE_PULSE_OFF,
+ SAHPI_CTRL_STATE_PULSE_ON,
+ SAHPI_CTRL_STATE_AUTO = 0xFF
+} SaHpiCtrlStateDigitalT;
+
+typedef SaHpiUint32T SaHpiCtrlStateDiscreteT;
+
+typedef SaHpiInt32T SaHpiCtrlStateAnalogT;
+
+#define SAHPI_CTRL_MAX_STREAM_LENGTH 4
+typedef struct {
+ SaHpiBoolT Repeat; /* Repeat flag */
+ SaHpiUint32T StreamLength; /* Length of the data, in bytes,
+ ** stored in the stream. */
+ SaHpiUint8T Stream[SAHPI_CTRL_MAX_STREAM_LENGTH];
+} SaHpiCtrlStateStreamT;
+
+typedef SaHpiUint8T SaHpiTxtLineNumT;
+
+/* Reserved number for sending output to all lines */
+#define SAHPI_TLN_ALL_LINES (SaHpiTxtLineNumT)0xFF
+
+typedef struct {
+ SaHpiTxtLineNumT Line; /* Operate on line # */
+ SaHpiTextBufferT Text; /* Text to display */
+} SaHpiCtrlStateTextT;
+
+#define SAHPI_CTRL_MAX_OEM_BODY_LENGTH 255
+typedef struct {
+ SaHpiManufacturerIdT MId;
+ SaHpiUint8T BodyLength;
+ SaHpiUint8T Body[SAHPI_CTRL_MAX_OEM_BODY_LENGTH]; /* OEM Specific */
+} SaHpiCtrlStateOemT;
+
+typedef union {
+ SaHpiCtrlStateDigitalT Digital;
+ SaHpiCtrlStateDiscreteT Discrete;
+ SaHpiCtrlStateAnalogT Analog;
+ SaHpiCtrlStateStreamT Stream;
+ SaHpiCtrlStateTextT Text;
+ SaHpiCtrlStateOemT Oem;
+} SaHpiCtrlStateUnionT;
+
+typedef struct {
+ SaHpiCtrlTypeT Type; /* Type of control */
+ SaHpiCtrlStateUnionT StateUnion; /* Data for control type */
+} SaHpiCtrlStateT;
+
+
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Control Resource Data Records **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** Output Type
+**
+** This enumeration defines the what the control's output will be.
+*/
+typedef enum {
+ SAHPI_CTRL_GENERIC = 0,
+ SAHPI_CTRL_LED,
+ SAHPI_CTRL_FAN_SPEED,
+ SAHPI_CTRL_DRY_CONTACT_CLOSURE,
+ SAHPI_CTRL_POWER_SUPPLY_INHIBIT,
+ SAHPI_CTRL_AUDIBLE,
+ SAHPI_CTRL_FRONT_PANEL_LOCKOUT,
+ SAHPI_CTRL_POWER_INTERLOCK,
+ SAHPI_CTRL_POWER_STATE,
+ SAHPI_CTRL_LCD_DISPLAY,
+ SAHPI_CTRL_OEM
+} SaHpiCtrlOutputTypeT;
+
+/*
+** Specific Record Types
+** These types represent the specific types of control resource data records.
+*/
+typedef struct {
+ SaHpiCtrlStateDigitalT Default;
+} SaHpiCtrlRecDigitalT;
+
+typedef struct {
+ SaHpiCtrlStateDiscreteT Default;
+} SaHpiCtrlRecDiscreteT;
+
+typedef struct {
+ SaHpiCtrlStateAnalogT Min; /* Minimum Value */
+ SaHpiCtrlStateAnalogT Max; /* Maximum Value */
+ SaHpiCtrlStateAnalogT Default;
+} SaHpiCtrlRecAnalogT;
+
+typedef struct {
+ SaHpiCtrlStateStreamT Default;
+} SaHpiCtrlRecStreamT;
+
+typedef struct {
+ SaHpiUint8T MaxChars; /* Maximum chars per line */
+ SaHpiUint8T MaxLines; /* Maximum # of lines */
+ SaHpiLanguageT Language; /* Language Code */
+ SaHpiTextTypeT DataType; /* Permitted Data */
+ SaHpiCtrlStateTextT Default;
+} SaHpiCtrlRecTextT;
+
+#define SAHPI_CTRL_OEM_CONFIG_LENGTH 10
+typedef struct {
+ SaHpiManufacturerIdT MId;
+ SaHpiUint8T ConfigData[SAHPI_CTRL_OEM_CONFIG_LENGTH];
+ SaHpiCtrlStateOemT Default;
+} SaHpiCtrlRecOemT;
+
+typedef union {
+ SaHpiCtrlRecDigitalT Digital;
+ SaHpiCtrlRecDiscreteT Discrete;
+ SaHpiCtrlRecAnalogT Analog;
+ SaHpiCtrlRecStreamT Stream;
+ SaHpiCtrlRecTextT Text;
+ SaHpiCtrlRecOemT Oem;
+} SaHpiCtrlRecUnionT;
+
+/*
+** Record Definition
+** Definition of the control resource data record.
+*/
+typedef struct {
+ SaHpiCtrlNumT Num; /* Control Number/Index */
+ SaHpiBoolT Ignore; /* Ignore control (entity
+ not present, disabled, etc.) */
+ SaHpiCtrlOutputTypeT OutputType;
+ SaHpiCtrlTypeT Type; /* Type of control */
+ SaHpiCtrlRecUnionT TypeUnion; /* Specific control record */
+ SaHpiUint32T Oem; /* Reserved for OEM use */
+} SaHpiCtrlRecT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Entity Inventory Data **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+/*
+** These structures are used to read and write inventory data to entity inventory
+** repositories within a resource.
+*/
+/*
+** Entity Inventory Repository ID
+** Identifier for an entity inventory repository.
+*/
+typedef SaHpiUint8T SaHpiEirIdT;
+#define SAHPI_DEFAULT_INVENTORY_ID (SaHpiEirIdT)0x00
+
+/* Data Validity */
+typedef enum {
+ SAHPI_INVENT_DATA_VALID,
+ SAHPI_INVENT_DATA_INVALID,
+ SAHPI_INVENT_DATA_OVERFLOW
+} SaHpiInventDataValidityT;
+
+/* Inventory Record definitions */
+typedef enum {
+ SAHPI_INVENT_RECTYPE_INTERNAL_USE = 0xB0,
+ SAHPI_INVENT_RECTYPE_CHASSIS_INFO,
+ SAHPI_INVENT_RECTYPE_BOARD_INFO,
+ SAHPI_INVENT_RECTYPE_PRODUCT_INFO,
+ SAHPI_INVENT_RECTYPE_OEM = 0xC0
+} SaHpiInventDataRecordTypeT;
+
+typedef enum {
+ SAHPI_INVENT_CTYP_OTHER = 1,
+ SAHPI_INVENT_CTYP_UNKNOWN,
+ SAHPI_INVENT_CTYP_DESKTOP,
+ SAHPI_INVENT_CTYP_LOW_PROFILE_DESKTOP,
+ SAHPI_INVENT_CTYP_PIZZA_BOX,
+ SAHPI_INVENT_CTYP_MINI_TOWER,
+ SAHPI_INVENT_CTYP_TOWER,
+ SAHPI_INVENT_CTYP_PORTABLE,
+ SAHPI_INVENT_CTYP_LAPTOP,
+ SAHPI_INVENT_CTYP_NOTEBOOK,
+ SAHPI_INVENT_CTYP_HANDHELD,
+ SAHPI_INVENT_CTYP_DOCKING_STATION,
+ SAHPI_INVENT_CTYP_ALLINONE,
+ SAHPI_INVENT_CTYP_SUBNOTEBOOK,
+ SAHPI_INVENT_CTYP_SPACE_SAVING,
+ SAHPI_INVENT_CTYP_LUNCH_BOX,
+ SAHPI_INVENT_CTYP_MAIN_SERVER,
+ SAHPI_INVENT_CTYP_EXPANSION,
+ SAHPI_INVENT_CTYP_SUBCHASSIS,
+ SAHPI_INVENT_CTYP_BUS_EXPANSION_CHASSIS,
+ SAHPI_INVENT_CTYP_PERIPHERAL_CHASSIS,
+ SAHPI_INVENT_CTYP_RAID_CHASSIS,
+ SAHPI_INVENT_CTYP_RACKMOUNT
+} SaHpiInventChassisTypeT;
+
+typedef struct {
+ SaHpiUint8T Data[1]; /* Variable length opaque data */
+} SaHpiInventInternalUseDataT;
+
+typedef struct {
+ SaHpiTimeT MfgDateTime; /* May be set to
+ SAHPI_TIME_UNSPECIFIED
+ if manufacturing
+ date/time not available */
+ SaHpiTextBufferT *Manufacturer;
+ SaHpiTextBufferT *ProductName;
+ SaHpiTextBufferT *ProductVersion;
+ SaHpiTextBufferT *ModelNumber;
+ SaHpiTextBufferT *SerialNumber;
+ SaHpiTextBufferT *PartNumber;
+ SaHpiTextBufferT *FileId;
+ SaHpiTextBufferT *AssetTag;
+ SaHpiTextBufferT *CustomField[1]; /* Variable number of fields,
+ last is NULL */
+} SaHpiInventGeneralDataT;
+
+typedef struct {
+ SaHpiInventChassisTypeT Type; /* Type of chassis */
+ SaHpiInventGeneralDataT GeneralData;
+} SaHpiInventChassisDataT;
+
+typedef struct {
+ SaHpiManufacturerIdT MId;/* OEM Manuf. ID */
+ SaHpiUint8T Data[1]; /* Variable length data, defined by OEM,
+ Length derived from DataLength in
+ SaHpiInventDataRecordT structure:
+ DataLength - 4(because DataLength
+ includes the MId) */
+} SaHpiInventOemDataT;
+
+typedef union {
+ SaHpiInventInternalUseDataT InternalUse;
+ SaHpiInventChassisDataT ChassisInfo;
+ SaHpiInventGeneralDataT BoardInfo;
+ SaHpiInventGeneralDataT ProductInfo;
+ SaHpiInventOemDataT OemData;
+} SaHpiInventDataUnionT;
+
+typedef struct {
+ SaHpiInventDataRecordTypeT RecordType;
+ SaHpiUint32T DataLength; /* Length of Data field for
+ this record */
+ SaHpiInventDataUnionT RecordData; /* Variable length data */
+} SaHpiInventDataRecordT;
+
+typedef struct {
+ SaHpiInventDataValidityT Validity; /* Indication as to whether data
+ Returned by
+ saHpiEntityInventoryDataRead() is
+ complete and valid. Unless this
+ flag indicates valid data,
+ saHpiEntityInventoryDataWrite() will
+ not take any actions except to
+ return an error.*/
+ SaHpiInventDataRecordT *DataRecords[1]; /* Array of pointers to inventory
+ Data Records. Variable
+ number of entries. Last
+ entry is NULL. */
+} SaHpiInventoryDataT;
+
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Inventory Resource Data Records **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** All inventory data contained in an entity inventory repository
+** must be represented in the RDR repository
+** with an SaHpiInventoryRecT.
+*/
+typedef struct {
+ SaHpiEirIdT EirId;
+ SaHpiUint32T Oem;
+} SaHpiInventoryRecT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Watchdogs **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** This section defines all of the data types associated with watchdog timers.
+*/
+
+/* Watchdog Number - Identifier for a watchdog timer. */
+typedef SaHpiUint8T SaHpiWatchdogNumT;
+#define SAHPI_DEFAULT_WATCHDOG_NUM (SaHpiWatchdogNumT)0x00
+
+/*
+** Watchdog Timer Action
+**
+** These enumerations represent the possible actions to be taken upon watchdog
+** timer timeout and the events that are generated for watchdog actions.
+*/
+typedef enum {
+ SAHPI_WA_NO_ACTION = 0,
+ SAHPI_WA_RESET,
+ SAHPI_WA_POWER_DOWN,
+ SAHPI_WA_POWER_CYCLE
+} SaHpiWatchdogActionT;
+
+typedef enum {
+ SAHPI_WAE_NO_ACTION = 0,
+ SAHPI_WAE_RESET,
+ SAHPI_WAE_POWER_DOWN,
+ SAHPI_WAE_POWER_CYCLE,
+ SAHPI_WAE_TIMER_INT=0x08 /* Used if Timer Preinterrupt only */
+} SaHpiWatchdogActionEventT;
+
+/*
+** Watchdog Pre-timer Interrupt
+**
+** These enumerations represent the possible types of interrupts that may be
+** triggered by a watchdog pre-timer event. The actual meaning of these
+** operations may differ depending on the hardware architecture.
+*/
+typedef enum {
+ SAHPI_WPI_NONE = 0,
+ SAHPI_WPI_SMI,
+ SAHPI_WPI_NMI,
+ SAHPI_WPI_MESSAGE_INTERRUPT,
+ SAHPI_WPI_OEM = 0x0F
+} SaHpiWatchdogPretimerInterruptT;
+
+/*
+** Watchdog Timer Use
+**
+** These enumerations represent the possible watchdog users that may have caused
+** the watchdog to expire. For instance, if watchdog is being used during power
+** on self test (POST), and it expires, the SAHPI_WTU_BIOS_POST expiration type
+** will be set. Most specific uses for Watchdog timer by users of HPI should
+** indicate SAHPI_WTU_SMS_OS if the use is to provide an OS-healthy heartbeat,
+** or SAHPI_WTU_OEM if it is used for some other purpose.
+*/
+typedef enum {
+ SAHPI_WTU_NONE = 0,
+ SAHPI_WTU_BIOS_FRB2,
+ SAHPI_WTU_BIOS_POST,
+ SAHPI_WTU_OS_LOAD,
+ SAHPI_WTU_SMS_OS, /* System Management System providing
+ heartbeat for OS */
+ SAHPI_WTU_OEM,
+ SAHPI_WTU_UNSPECIFIED = 0x0F
+} SaHpiWatchdogTimerUseT;
+
+/*
+** Timer Use Expiration Flags
+** These values are used for the Watchdog Timer Use Expiration flags in the
+** SaHpiWatchdogT structure.
+*/
+typedef SaHpiUint8T SaHpiWatchdogExpFlagsT;
+#define SAHPI_WATCHDOG_EXP_BIOS_FRB2 (SaHpiWatchdogExpFlagsT)0x02
+#define SAHPI_WATCHDOG_EXP_BIOS_POST (SaHpiWatchdogExpFlagsT)0x04
+#define SAHPI_WATCHDOG_EXP_OS_LOAD (SaHpiWatchdogExpFlagsT)0x08
+#define SAHPI_WATCHDOG_EXP_SMS_OS (SaHpiWatchdogExpFlagsT)0x10
+#define SAHPI_WATCHDOG_EXP_OEM (SaHpiWatchdogExpFlagsT)0x20
+
+/*
+** Watchdog Structure
+**
+** This structure is used by the saHpiWatchdogTimerGet() and
+** saHpiWatchdogTimerSet() functions. The use of the structure varies slightly by
+** each function.
+**
+** For saHpiWatchdogTimerGet() :
+**
+** Log - indicates whether or not the Watchdog is configured to
+** issue an event when it next times out. TRUE=event will
+** be issued on timeout.
+** Running - indicates whether or not the Watchdog is currently
+** running or stopped. TRUE=Watchdog is running.
+** TimerUse - indicates the current use of the timer; one of five
+** preset uses which was included on the last
+** saHpiWatchdogTimerSet() function call, or through some
+** other implementation-dependent means to start the
+** Watchdog timer.
+** TimerAction - indicates what action will be taken when the Watchdog
+** times out.
+** PretimerInterrupt - indicates which action will be taken
+** "PreTimeoutInterval" seconds prior to Watchdog timer
+** expiration.
+** PreTimeoutInterval - indicates how many milliseconds prior to timer time
+** out the PretimerInterrupt action will be taken. If
+** "PreTimeoutInterval" = 0, the PretimerInterrupt action
+** will occur concurrently with "TimerAction." HPI
+** implementations may not be able to support millisecond
+** resolution and may have a maximum value restriction.
+** These restrictions should be documented by the
+** provider of the HPI interface.
+** TimerUseExpFlags - set of five bit flags which indicate that a Watchdog
+** timer timeout has occurred while the corresponding
+** TimerUse value was set. Once set, these flags stay
+** set until specifically cleared with a
+** saHpiWatchdogTimerSet() call, or by some other
+** implementation-dependent means.
+** InitialCount - The time, in milliseconds, before the timer will time
+** out after a saHpiWatchdogTimerReset() function call is
+** made, or some other implementation-dependent strobe is
+** sent to the Watchdog. HPI implementations may not be
+** able to support millisecond resolution and may have a
+** maximum value restriction. These restrictions should
+** be documented by the provider of the HPI interface.
+** PresentCount - The remaining time in milliseconds before the timer
+** will time out unless a saHpiWatchdogTimerReset()
+** function call is made, or some other implementation-
+** dependent strobe is sent to the Watchdog.
+** HPI implementations may not be able to support
+** millisecond resolution on watchdog timers, but will
+** return the number of clock ticks remaining times the
+** number of milliseconds between each tick.
+**
+** For saHpiWatchdogTimerSet():
+**
+** Log - indicates whether or not the Watchdog should issue
+** an event when it next times out. TRUE=event will be
+** issued on timeout.
+** Running - indicates whether or not the Watchdog should be
+** stopped before updating.
+** TRUE = Watchdog is not stopped. If it is already
+** stopped, it will remain stopped, but if it is
+** running, it will continue to run, with the
+** countdown timer reset to the new InitialCount.
+** Note that there is a race condition possible
+** with this setting, so it should be used with
+** care.
+** FALSE = Watchdog is stopped. After
+** saHpiWatchdogTimerSet() is called, a subsequent
+** call to saHpiWatchdogTimerReset() is required to
+** start the timer.
+** TimerUse - indicates the current use of the timer. Will control
+** which TimerUseExpFlag is set if the timer expires.
+** TimerAction - indicates what action will be taken when the Watchdog
+** times out.
+** PretimerInterrupt - indicates which action will be taken
+** "PreTimeoutInterval" seconds prior to Watchdog timer
+** expiration.
+** PreTimeoutInterval - indicates how many milliseconds prior to timer time
+** out the PretimerInterrupt action will be taken. If
+** "PreTimeoutInterval" = 0, the PretimerInterrupt action
+** will occur concurrently with "TimerAction." HPI
+** implementations may not be able to support millisecond
+** resolution and may have a maximum value restriction.
+** These restrictions should be documented by the
+** provider of the HPI interface.
+** TimerUseExpFlags - Set of five bit flags corresponding to the five
+** TimerUse values. For each bit set, the corresponding
+** Timer Use Expiration Flag will be CLEARED. Generally,
+** a program should only clear the Timer Use Expiration
+** Flag corresponding to its own TimerUse, so that other
+** software, which may have used the timer for another
+** purpose in the past can still read its TimerUseExpFlag
+** to determine whether or not the timer expired during
+** that use.
+** InitialCount - The time, in milliseconds, before the timer will time
+** out after a saHpiWatchdogTimerReset() function call is
+** made, or some other implementation-dependent strobe is
+** sent to the Watchdog. HPI implementations may not be
+** able to support millisecond resolution and may have a
+** maximum value restriction. These restrictions should
+** be documented by the provider of the HPI interface.
+** PresentCount - Not used on saHpiWatchdogTimerSet() function. Ignored.
+**
+*/
+
+typedef struct {
+ SaHpiBoolT Log;
+ SaHpiBoolT Running;
+ SaHpiWatchdogTimerUseT TimerUse;
+ SaHpiWatchdogActionT TimerAction;
+ SaHpiWatchdogPretimerInterruptT PretimerInterrupt;
+ SaHpiUint32T PreTimeoutInterval;
+ SaHpiWatchdogExpFlagsT TimerUseExpFlags;
+ SaHpiUint32T InitialCount;
+ SaHpiUint32T PresentCount;
+} SaHpiWatchdogT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Watchdog Resource Data Records **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** When the "Watchdog" capability is set in a resource, a watchdog with an
+** identifier of SAHPI_DEFAULT_WATCHDOG_NUM is required. All watchdogs must be
+** represented in the RDR repository with an SaHpiWatchdogRecT, including the
+** watchdog with an identifier of SAHPI_DEFAULT_WATCHDOG_NUM.
+*/
+typedef struct {
+ SaHpiWatchdogNumT WatchdogNum;
+ SaHpiUint32T Oem;
+} SaHpiWatchdogRecT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Resource Data Record **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** The following describes the different types of records that exist within a
+** RDR repository and the RDR super-structure to all of the specific RDR types
+** (sensor, inventory data, watchdog, etc.).
+*/
+typedef enum {
+ SAHPI_NO_RECORD,
+ SAHPI_CTRL_RDR,
+ SAHPI_SENSOR_RDR,
+ SAHPI_INVENTORY_RDR,
+ SAHPI_WATCHDOG_RDR
+} SaHpiRdrTypeT;
+
+typedef union {
+ SaHpiCtrlRecT CtrlRec;
+ SaHpiSensorRecT SensorRec;
+ SaHpiInventoryRecT InventoryRec;
+ SaHpiWatchdogRecT WatchdogRec;
+} SaHpiRdrTypeUnionT;
+
+typedef struct {
+ SaHpiEntryIdT RecordId;
+ SaHpiRdrTypeT RdrType;
+ SaHpiEntityPathT Entity; /* Entity to which this RDR relates. */
+ SaHpiRdrTypeUnionT RdrTypeUnion;
+ SaHpiTextBufferT IdString;
+} SaHpiRdrT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Hot Swap **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* Power State */
+typedef enum {
+ SAHPI_HS_POWER_OFF = 0,
+ SAHPI_HS_POWER_ON,
+ SAHPI_HS_POWER_CYCLE
+} SaHpiHsPowerStateT;
+
+/* Hot Swap Indicator State */
+typedef enum {
+ SAHPI_HS_INDICATOR_OFF = 0,
+ SAHPI_HS_INDICATOR_ON
+} SaHpiHsIndicatorStateT;
+
+/* Hot Swap Action */
+typedef enum {
+ SAHPI_HS_ACTION_INSERTION = 0,
+ SAHPI_HS_ACTION_EXTRACTION
+} SaHpiHsActionT;
+
+/* Hot Swap State */
+typedef enum {
+ SAHPI_HS_STATE_INACTIVE = 0,
+ SAHPI_HS_STATE_INSERTION_PENDING,
+ SAHPI_HS_STATE_ACTIVE_HEALTHY,
+ SAHPI_HS_STATE_ACTIVE_UNHEALTHY,
+ SAHPI_HS_STATE_EXTRACTION_PENDING,
+ SAHPI_HS_STATE_NOT_PRESENT
+} SaHpiHsStateT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Events, Part 2 **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* Event Data Structures */
+
+/*
+** Sensor Optional Data
+**
+** Sensor events may contain optional data items passed and stored with the
+** event. If these optional data items are present, they will be included with
+** the event data returned in response to a saHpiEventGet() or
+** saHpiEventLogEntryGet() function call. Also, the optional data items may be
+** included with the event data passed to the saHpiEventLogEntryAdd() function.
+**
+** Specific implementations of HPI may have restrictions on how much data may
+** be passed to saHpiEventLogEntryAdd(). These restrictions should be documented
+** by the provider of the HPI interface.
+*/
+typedef enum {
+ SAHPI_CRITICAL = 0,
+ SAHPI_MAJOR,
+ SAHPI_MINOR,
+ SAHPI_INFORMATIONAL,
+ SAHPI_OK,
+ SAHPI_DEBUG = 0xF0
+} SaHpiSeverityT;
+
+typedef SaHpiUint8T SaHpiSensorOptionalDataT;
+
+#define SAHPI_SOD_TRIGGER_READING (SaHpiSensorOptionalDataT)0x01
+#define SAHPI_SOD_TRIGGER_THRESHOLD (SaHpiSensorOptionalDataT)0x02
+#define SAHPI_SOD_OEM (SaHpiSensorOptionalDataT)0x04
+#define SAHPI_SOD_PREVIOUS_STATE (SaHpiSensorOptionalDataT)0x08
+#define SAHPI_SOD_SENSOR_SPECIFIC (SaHpiSensorOptionalDataT)0x10
+
+typedef struct {
+ SaHpiSensorNumT SensorNum;
+ SaHpiSensorTypeT SensorType;
+ SaHpiEventCategoryT EventCategory;
+ SaHpiBoolT Assertion; /* TRUE = Event State asserted
+ FALSE = deasserted */
+ SaHpiEventStateT EventState; /* State being asserted
+ deasserted */
+ SaHpiSensorOptionalDataT OptionalDataPresent;
+ SaHpiSensorReadingT TriggerReading; /* Reading that triggered
+ the event */
+ SaHpiSensorReadingT TriggerThreshold;
+ SaHpiEventStateT PreviousState;
+ SaHpiUint32T Oem;
+ SaHpiUint32T SensorSpecific;
+} SaHpiSensorEventT;
+
+typedef struct {
+ SaHpiHsStateT HotSwapState;
+ SaHpiHsStateT PreviousHotSwapState;
+} SaHpiHotSwapEventT;
+
+typedef struct {
+ SaHpiWatchdogNumT WatchdogNum;
+ SaHpiWatchdogActionEventT WatchdogAction;
+ SaHpiWatchdogPretimerInterruptT WatchdogPreTimerAction;
+ SaHpiWatchdogTimerUseT WatchdogUse;
+} SaHpiWatchdogEventT;
+
+#define SAHPI_OEM_EVENT_DATA_SIZE 32
+typedef struct {
+ SaHpiManufacturerIdT MId;
+ SaHpiUint8T OemEventData[SAHPI_OEM_EVENT_DATA_SIZE];
+} SaHpiOemEventT;
+
+/*
+** User events may be used for storing custom events created by the application / middleware;
+** eg. when injecting events into the event log using saHpiEventLogEntryAdd().
+*/
+#define SAHPI_USER_EVENT_DATA_SIZE 32
+typedef struct {
+ SaHpiUint8T UserEventData[SAHPI_USER_EVENT_DATA_SIZE];
+} SaHpiUserEventT;
+
+typedef enum {
+ SAHPI_ET_SENSOR,
+ SAHPI_ET_HOTSWAP,
+ SAHPI_ET_WATCHDOG,
+ SAHPI_ET_OEM,
+ SAHPI_ET_USER
+} SaHpiEventTypeT;
+
+typedef union {
+ SaHpiSensorEventT SensorEvent;
+ SaHpiHotSwapEventT HotSwapEvent;
+ SaHpiWatchdogEventT WatchdogEvent;
+ SaHpiOemEventT OemEvent;
+ SaHpiUserEventT UserEvent;
+} SaHpiEventUnionT;
+
+typedef struct {
+ SaHpiResourceIdT Source;
+ SaHpiEventTypeT EventType;
+ SaHpiTimeT Timestamp;
+ SaHpiSeverityT Severity;
+ SaHpiEventUnionT EventDataUnion;
+} SaHpiEventT;
+
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Parameter Control **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+typedef enum {
+ SAHPI_DEFAULT_PARM = 0,
+ SAHPI_SAVE_PARM,
+ SAHPI_RESTORE_PARM
+} SaHpiParmActionT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Reset **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+typedef enum {
+ SAHPI_COLD_RESET = 0,
+ SAHPI_WARM_RESET,
+ SAHPI_RESET_ASSERT,
+ SAHPI_RESET_DEASSERT
+} SaHpiResetActionT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Resource Presence Table **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* This section defines the types associated with the RPT. */
+
+typedef struct {
+ SaHpiUint32T UpdateCount; /* This count is incremented any time the table
+ is changed. It rolls over to zero when the
+ maximum value is reached */
+ SaHpiTimeT UpdateTimestamp; /* This time is set any time the table is
+ changed. If the implementation cannot
+ supply an absolute timestamp, then it may
+ supply a timestamp relative to some system-
+ defined epoch, such as system boot. The
+ value SAHPI_TIME_UNSPECIFIED indicates that
+ the time of the update cannot be determined.
+ Otherwise, If the value is less than or
+ equal to SAHPI_TIME_MAX_RELATIVE, then it
+ is relative; if it is greater than
+ SAHPI_TIME_MAX_RELATIVE, then it is absolute. */
+} SaHpiRptInfoT;
+
+/*
+** Resource Info Type Definitions
+**
+**
+** SaHpiResourceInfoT contains static configuration data concerning the
+** management controller associated with the resource, or the resource itself.
+** Note this information is used to describe the resource; that is, the piece of
+** infrastructure which manages an entity (or multiple entities) - NOT the entities
+** for which the resource provides management. The purpose of the
+** SaHpiResourceInfoT structure is to provide information that the HPI user may
+** need in order to interact correctly with the resource (e.g., recognize a
+** specific management controller which may have defined OEM fields in sensors,
+** OEM controls, etc.).
+**
+** All of the fields in the following structure may or may not be used by a
+** given resource.
+*/
+typedef struct {
+ SaHpiUint8T ResourceRev;
+ SaHpiUint8T SpecificVer;
+ SaHpiUint8T DeviceSupport;
+ SaHpiManufacturerIdT ManufacturerId;
+ SaHpiUint16T ProductId;
+ SaHpiUint8T FirmwareMajorRev;
+ SaHpiUint8T FirmwareMinorRev;
+ SaHpiUint8T AuxFirmwareRev;
+} SaHpiResourceInfoT;
+
+/*
+** Resource Capabilities
+**
+** This definition defines the capabilities of a given resource. One resource
+** may support any number of capabilities using the bit mask. Every resource
+** must set at least one of these capabilities; ie. zero is not a valid value
+** for a resource's capabilities.
+**
+** SAHPI_CAPABILITY_DOMAIN
+** SAHPI_CAPABILITY_RESOURCE
+** SAHPI_CAPABILITY_EVT_DEASSERTS
+** Indicates that all sensors on the resource have the property that their
+** Assertion and Deassertion event enable flags are the same. That is,
+** for all event states whose assertion triggers an event, it is
+** guaranteed that the deassertion of that event will also
+** trigger an event. Thus, the user may track the state of sensors on the
+** resource by monitoring events rather than polling for state changes.
+** SAHPI_CAPABILITY_AGGREGATE_STATUS
+** SAHPI_CAPABILITY_CONFIGURATION
+** SAHPI_CAPABILITY_MANAGED_HOTSWAP
+** Indicates that the resource supports managed hotswap. Since hotswap only
+** makes sense for field-replaceable units, the SAHPI_CAPABILITY_FRU
+** capability bit must also be set for this resource.
+** SAHPI_CAPABILITY_WATCHDOG
+** SAHPI_CAPABILITY_CONTROL
+** SAHPI_CAPABILITY_FRU
+** Indicates that the resource is a field-replaceable unit; i.e., it is
+** capable of being removed and replaced in a live system. This does not
+** necessarily imply that the resource supports managed hotswap.
+** SAHPI_CAPABILITY_INVENTORY_DATA
+** SAHPI_CAPABILITY_SEL
+** SAHPI_CAPABILITY_RDR
+** Indicates that a resource data record (RDR) repository is supplied
+** by the resource. Since the existence of an RDR is mandatory, this
+** capability must be asserted.
+** SAHPI_CAPABILITY_SENSOR
+*/
+
+typedef SaHpiUint32T SaHpiCapabilitiesT;
+#define SAHPI_CAPABILITY_DOMAIN (SaHpiCapabilitiesT)0x80000000
+#define SAHPI_CAPABILITY_RESOURCE (SaHpiCapabilitiesT)0X40000000
+#define SAHPI_CAPABILITY_EVT_DEASSERTS (SaHpiCapabilitiesT)0x00008000
+#define SAHPI_CAPABILITY_AGGREGATE_STATUS (SaHpiCapabilitiesT)0x00002000
+#define SAHPI_CAPABILITY_CONFIGURATION (SaHpiCapabilitiesT)0x00001000
+#define SAHPI_CAPABILITY_MANAGED_HOTSWAP (SaHpiCapabilitiesT)0x00000800
+#define SAHPI_CAPABILITY_WATCHDOG (SaHpiCapabilitiesT)0x00000400
+#define SAHPI_CAPABILITY_CONTROL (SaHpiCapabilitiesT)0x00000200
+#define SAHPI_CAPABILITY_FRU (SaHpiCapabilitiesT)0x00000100
+#define SAHPI_CAPABILITY_INVENTORY_DATA (SaHpiCapabilitiesT)0x00000008
+#define SAHPI_CAPABILITY_SEL (SaHpiCapabilitiesT)0x00000004
+#define SAHPI_CAPABILITY_RDR (SaHpiCapabilitiesT)0x00000002
+#define SAHPI_CAPABILITY_SENSOR (SaHpiCapabilitiesT)0x00000001
+
+/*
+** RPT Entry
+**
+** This structure is used to store the RPT entry information.
+**
+** The ResourceCapabilities field definies the capabilities of the resource.
+** This field must be non-zero for all valid resources.
+**
+** The ResourceTag field is an informational value that supplies the caller with naming
+** information for the resource. This should be set to the "user-visible" name for a
+** resource, which can be used to identify the resource in messages to a human operator.
+** For example, it could be set to match a physical printed label attached to the primary
+** entity which the resource manages. See section 5.2.6, saHpiResourceTagSet(), on page 33.
+*/
+typedef struct {
+ SaHpiEntryIdT EntryId;
+ SaHpiResourceIdT ResourceId;
+ SaHpiResourceInfoT ResourceInfo;
+ SaHpiEntityPathT ResourceEntity; /* If resource manages a FRU, entity path of the FRU */
+ /* If resource manages a single entity, entity path of
+ that entity. */
+ /* If resource manages multiple entities, the
+ entity path of the "primary" entity managed by the
+ resource */
+ /* Must be set to the same value in every domain which
+ contains this resource */
+ SaHpiCapabilitiesT ResourceCapabilities; /* Must be non-0. */
+ SaHpiSeverityT ResourceSeverity; /* Indicates the criticality that
+ should be raised when the resource
+ is not responding */
+ SaHpiDomainIdT DomainId; /* The Domain ID is used when the resource
+ is also a domain. */
+ SaHpiTextBufferT ResourceTag;
+} SaHpiRptEntryT;
+
+
+
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** System Event Log **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+/* This section defines the types associated with the SEL. */
+/*
+** Event Log Information
+**
+** The Entries entry denotes the number of active entries contained in the log.
+** The Size entry denotes the total number of entries the log is able to hold.
+** The UpdateTimestamp entry denotes the timestamp of the last addition,
+** deletion or log clear operation.
+** The CurrentTime entry denotes the log's idea of the current time; i.e the
+** timestamp that would be placed on an entry if it was added now.
+** The Enabled entry indicates whether the log is enabled. If the event log
+** is "disabled" no events generated within the HPI implementation will be
+** added to the event log. Events may still be added to the event log with
+** the saHpiEventLogEntryAdd() function. When the event log is "enabled"
+** events may be automatically added to the event log as they are generated
+** in a resource or a domain, however, it is implementation-specific which
+** events are automatically added to any event log.
+** The OverflowFlag entry indicates the log has overflowed. Events have been
+** dropped or overwritten due to a table overflow.
+** The OverflowAction entry indicates the behavior of the SEL when an overflow
+** occurs.
+** The DeleteEntrySupported indicates whether the delete command is supported for
+** event log entries. Note that clearing an entire log is valid even if this
+** flag is not set.
+*/
+typedef enum {
+ SAHPI_SEL_OVERFLOW_DROP, /* New entries are dropped when log is full*/
+ SAHPI_SEL_OVERFLOW_WRAP, /* Log wraps when log is full */
+ SAHPI_SEL_OVERFLOW_WRITELAST /* Last entry overwritten when log is full */
+} SaHpiSelOverflowActionT;
+
+typedef struct {
+ SaHpiUint32T Entries;
+ SaHpiUint32T Size;
+ SaHpiTimeT UpdateTimestamp;
+ SaHpiTimeT CurrentTime;
+ SaHpiBoolT Enabled;
+ SaHpiBoolT OverflowFlag;
+ SaHpiSelOverflowActionT OverflowAction;
+ SaHpiBoolT DeleteEntrySupported;
+} SaHpiSelInfoT;
+/*
+** Event Log Entry
+** These types define the event log entry.
+*/
+typedef SaHpiUint32T SaHpiSelEntryIdT;
+/* Reserved values for event log entry IDs */
+#define SAHPI_OLDEST_ENTRY (SaHpiSelEntryIdT)0x00000000
+#define SAHPI_NEWEST_ENTRY (SaHpiSelEntryIdT)0xFFFFFFFF
+#define SAHPI_NO_MORE_ENTRIES (SaHpiSelEntryIdT)0xFFFFFFFE
+
+
+
+typedef struct {
+ SaHpiSelEntryIdT EntryId; /* Entry ID for record */
+ SaHpiTimeT Timestamp; /* Time at which the event was placed
+ in the event log. The value
+ SAHPI_TIME_UNSPECIFIED indicates that
+ the time of the event cannot be
+ determined; otherwise, if less than
+ or equal to SAHPI_TIME_MAX_RELATIVE,
+ then it relative; if it is greater than
+ SAHPI_TIME_MAX_RELATIVE, then it is absolute. */
+ SaHpiEventT Event; /* Logged Event */
+} SaHpiSelEntryT;
+
+
+
+
+
+/*******************************************************************************
+**
+** Name: saHpiInitialize
+**
+** Description:
+** This function allows the management service an opportunity to perform
+** platform-specific initialization. saHpiInitialize() must be called
+** before any other functions are called.
+**
+** Parameters:
+** HpiImplVersion - [out] Pointer to the version of the HPI
+** implementation.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_DUPLICATE is returned when the HPI has already
+** been initialized. Once one saHpiInitialize() call has been made,
+** another one cannot be made until after a saHpiFinalize() call is made.
+**
+**
+** Remarks:
+** This function returns the version of the HPI implementation. Note: If
+** the HPI interface version is needed it can be retrieved from the
+** SAHPI_INTERFACE_VERSION definition.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiInitialize(
+ SAHPI_OUT SaHpiVersionT *HpiImplVersion
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiFinalize
+**
+** Description:
+** This function allows the management service an opportunity to perform
+** platform-specific cleanup. All sessions should be closed (see
+** saHpiSessionClose()), before this function is executed. All open
+** sessions will be forcibly closed upon execution of this command.
+**
+** Parameters:
+** None.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None. 5 Domains
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiFinalize (
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSessionOpen
+**
+** Description:
+** This function opens a HPI session for a given domain and set of
+** security characteristics (future). This function call assumes that a
+** pre-arranged agreement between caller and the HPI implementation
+** identifies the resources within the specified domain. As a future
+** roadmap item, functions for discovery of domains and allocation of
+** resources within domains may be developed.
+**
+** Parameters:
+** DomainId - [in] Domain ID to be controlled by middleware/application.
+** A domain ID of SAHPI_DEFAULT_DOMAIN_ID indicates the default domain.
+** SessionId - [out] Pointer to a location to store a handle to the newly
+** opened session. This handle is used for subsequent access to domain
+** resources and events.
+** SecurityParams - [in] Pointer to security and permissions data
+** structure. This parameter is reserved for future use, and must be set
+** to NULL.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_INVALID_DOMAIN is returned if no domain
+** matching the specified domain ID exists.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSessionOpen (
+ SAHPI_IN SaHpiDomainIdT DomainId,
+ SAHPI_OUT SaHpiSessionIdT *SessionId,
+ SAHPI_IN void *SecurityParams
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSessionClose
+**
+** Description:
+** This function closes a HPI session. After closing a session, the
+** session ID will no longer be valid.
+**
+** Parameters:
+** SessionId - [in] Session handle previously obtained using
+** saHpiSessionOpen().
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSessionClose (
+ SAHPI_IN SaHpiSessionIdT SessionId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourcesDiscover
+**
+** Description:
+** This function requests the underlying management service to discover
+** information about the resources it controls for the domain associated
+** with the open session. This function may be called during operation to
+** regenerate the RPT table. For those FRUs that must be discovered by
+** polling, latency between FRU insertion and actual addition of the
+** resource associated with that FRU to the RPT exists. To overcome this
+** latency, a discovery of all present resources may be forced by calling
+** saHpiResourcesDiscover ().
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourcesDiscover (
+ SAHPI_IN SaHpiSessionIdT SessionId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiRptInfoGet
+**
+** Description:
+** This function is used for requesting information about the resource
+** presence table (RPT) such as an update counter and timestamp. This is
+** particularly useful when using saHpiRptEntryGet() (see page 31).
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** RptInfo - [out] Pointer to the information describing the resource
+** presence table.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiRptInfoGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_OUT SaHpiRptInfoT *RptInfo
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiRptEntryGet
+**
+** Description:
+** This function retrieves resource information for the specified entry
+** of the resource presence table. This function allows the caller to
+** read the RPT entry-by-entry. If the EntryID parameter is set to
+** SAHPI_FIRST_ENTRY, the first entry in the RPT will be returned. When
+** an entry is successfully retrieved, *NextEntryID will be set to the
+** ID of the next valid entry; however, when the last entry has been
+** retrieved, *NextEntryID will be set to SAHPI_LAST_ENTRY. To retrieve
+** an entire list of entries, call this function first with an EntryID of
+** SAHPI_FIRST_ENTRY and then use the returned NextEntryID in the next
+** call. Proceed until the NextEntryID returned is SAHPI_LAST_ENTRY. At
+** initialization, the user may not wish to turn on eventing, since the
+** context of the events, as provided by the RPT, is not known. In this
+** instance, if a FRU is inserted into the system while the RPT is being
+** read entry by entry, the resource associated with that FRU may be
+** missed. (Keep in mind that there is no specified ordering for the RPT
+** entries.) The update counter provides a means for insuring that no
+** resources are missed when stepping through the RPT. In order to use
+** this feature, the user should invoke saHpiRptInfoGet(), and get the
+** update counter value before retrieving the first RPT entry. After
+** reading the last entry, the user should again invoke the
+** saHpiRptInfoGet() to get the update counter value. If the update
+** counter has not been incremented, no new records have been added.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** EntryId - [in] Handle of the entry to retrieve from the RPT. Reserved
+** entry ID values: SAHPI_FIRST_ENTRY Get first entry SAHPI_LAST_ENTRY
+** Reserved as delimiter for end of list. Not a valid entry identifier.
+**
+** NextEntryId - [out] Pointer to location to store the record ID of next
+** entry in RPT.
+** RptEntry - [out] Pointer to the structure to hold the returned RPT
+** entry.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiRptEntryGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiEntryIdT EntryId,
+ SAHPI_OUT SaHpiEntryIdT *NextEntryId,
+ SAHPI_OUT SaHpiRptEntryT *RptEntry
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiRptEntryGetByResourceId
+**
+** Description:
+** This function retrieves resource information from the resource
+** presence table for the specified resource using its resource ID.
+** Typically at start-up, the RPT is read entry-by-entry, using
+** saHpiRptEntryGet(). From this, the caller can establish the set of
+** resource IDs to use for future calls to the HPI functions. However,
+** there may be other ways of learning resource IDs without first reading
+** the RPT. For example, resources may be added to the domain while the
+** system is running in response to a hot-swap action. When a resource is
+** added, the application will receive a hot-swap event containing the
+** resource ID of the new resource. The application may then want to
+** search the RPT for more detailed information on the newly added
+** resource. In this case, the resource ID can be used to locate the
+** applicable RPT entry information.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource whose RPT entry should
+** be returned.
+** RptEntry - [out] Pointer to structure to hold the returned RPT entry.
+**
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiRptEntryGetByResourceId (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiRptEntryT *RptEntry
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourceSeveritySet
+**
+** Description:
+** This function allows the caller to set the severity level applied to
+** an event issued if a resource unexpectedly becomes unavailable to the
+** HPI. A resource may become unavailable for several reasons including:
+** ? The FRU associated with the resource is no longer present in the
+** system (a surprise extraction has occurred) ? A catastrophic failure
+** has occurred Typically, the HPI implementation will provide an
+** appropriate default value for this parameter, which may vary by
+** resource; management software can override this default value by use
+** of this function ? If a resource is removed from, then re-added to the
+** RPT (e.g., because of a hot-swap action), the HPI implementation may
+** reset the value of this parameter.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource for which the severity
+** level will be set.
+** Severity - [in] Severity level of event issued when the resource
+** unexpectedly becomes unavailable to the HPI.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceSeveritySet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSeverityT Severity
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourceTagSet
+**
+** Description:
+** This function allows the caller to set the resource tag for a
+** particular resource. The resource tag is an informational value that
+** supplies the caller with naming information for the resource. This
+** should be set to the "user-visible" name for a resource, which can be
+** used to identify the resource in messages to a human operator. For
+** example, it could be set to match a physical, printed label attached
+** to the entity associated with the resource. Typically, the HPI
+** implementation will provide an appropriate default value for this
+** parameter; this function is provided so that management software can
+** override the default, if desired. The value of the resource tag may be
+** retrieved from the resource's RPT entry. Note: If a resource is
+** removed from, then re-added to the RPT (e.g., because of a hot-swap
+** action), the HPI implementation may reset the value of this parameter.
+**
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource for which the resource
+** tag should be set.
+** ResourceTag - [in] Pointer to string representing the resource tag.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceTagSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiTextBufferT *ResourceTag
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourceIdGet
+**
+** Description:
+** This function returns the resource ID of the resource associated with
+** the entity upon which the caller is running.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [out] Pointer to location to hold the returned resource
+** ID.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_NOT_PRESENT is returned if the entity the
+** caller is running on is not manageable in the addressed domain.
+** SA_ERR_HPI_UNKNOWN is returned if the domain controller cannot
+** determine an appropriate response. That is, there may be an
+** appropriate resource ID in the domain to return, but it cannot be
+** determined.
+**
+** Remarks:
+** This function must be issued within a session to a domain that
+** includes a resource associated with the entity upon which the caller
+** is running, or the SA_ERR_HPI_NOT_PRESENT return will be issued. Since
+** entities are contained within other entities, there may be multiple
+** possible resources that could be returned to this call. For example,
+** if there is a resource ID associated with a particular compute blade
+** upon which the caller is running, and another associated with the
+** chassis which contains the compute blade, either could logically be
+** returned as an indication of a resource associated with the entity
+** upon which the caller was running. The function should return the
+** resource ID of the "smallest" resource that is associated with the
+** caller. So, in the example above, the function should return the
+** resource ID of the compute blade. Once the function has returned the
+** resourceID, the caller may issue further HPI calls using that
+** resourceID to learn the type of resource that been identified.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceIdGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_OUT SaHpiResourceIdT *ResourceId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEntitySchemaGet
+**
+** Description:
+** This function returns the identifier of the Entity Schema for the HPI
+** implementation. This schema defines valid Entity Paths that may be
+** returned by the HPI implementation.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** SchemaId - [out] Pointer to the ID of the schema in use; zero
+** indicates that a custom schema is in use.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** This function may be issued on any session opened to any domain in the
+** system, and will return the same identifier. The identifier returned
+** should either be zero, indicating that the HPI implementation uses a
+** custom schema; or one of the schema identifiers defined in Appendix A,
+** "Pre-Defined Entity Schemas," page 107. In the case of a custom
+** schema, the HPI implementation may use arbitrary entity paths to
+** describe resources in the system; in the case of a pre-defined schema,
+** all entity paths should conform to the schema.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEntitySchemaGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_OUT SaHpiUint32T *SchemaId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogInfoGet
+**
+** Description:
+** This function retrieves the number of entries in the system event log,
+** total size of the event log, timestamp for the most recent entry, the
+** log's idea of the current time (i.e., timestamp that would be placed
+** on an entry at this moment), enabled/disabled status of the log (see
+** saHpiEventLogStateSet()), the overflow flag, the overflow action, and
+** whether the log supports deletion of individual entries.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource that contains the system
+** event log to be managed. Set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the domain system event log.
+** Info - [out] Pointer to the returned SEL information.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogInfoGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiSelInfoT *Info
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogEntryGet
+**
+** Description:
+** This function retrieves an event log entry from a system event log.
+** The special entry IDs SAHPI_OLDEST_ENTRY and SAHPI_NEWEST_ENTRY are
+** used to select the oldest and newest entries, respectively, in the log
+** being read. A returned NextEntryID of SAHPI_NO_MORE_ENTRIES indicates
+** that the newest entry has been returned; there are no more entries
+** going forward (time-wise) in the log. A returned PrevEntryID of
+** SAHPI_NO_MORE_ENTRIES indicates that the oldest entry has been
+** returned. To retrieve an entire list of entries going forward (oldest
+** entry to newest entry) in the log, call this function first with an
+** EntryID of SAHPI_OLDEST_ENTRY and then use the returned NextEntryID as
+** the EntryID in the next call. Proceed until the NextEntryID returned
+** is SAHPI_NO_MORE_ENTRIES. To retrieve an entire list of entries going
+** backward (newest entry to oldest entry) in the log, call this function
+** first with an EntryID of SAHPI_NEWEST_ENTRY and then use the returned
+** PrevEntryID as the EntryID in the next call. Proceed until the
+** PrevEntryID returned is SAHPI_NO_MORE_ENTRIES.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource that contains the system
+** event log to be read. Set to SAHPI_DOMAIN_CONTROLLER_ID to address the
+** domain system event log.
+** EntryId - [in] Handle of the entry to retrieve from the SEL. Reserved
+** event log entry ID values: SAHPI_OLDEST_ENTRY Oldest entry in the
+** log. SAHPI_NEWEST_ENTRY Newest entry in the log.
+** SAHPI_NO_MORE_ENTRIES Not valid for this parameter. Used only when
+** retrieving the next and previous entry IDs.
+** PrevEntryId - [out] Handle of previous (older adjacent) entry in event
+** log. Reserved event log entry ID values: SAHPI_OLDEST_ENTRY Not valid
+** for this parameter. Used only for the EntryID parameter.
+** SAHPI_NEWEST_ENTRY Not valid for this parameter. Used only for the
+** EntryID parameter. SAHPI_NO_MORE_ENTRIES No more entries in the log
+** before the one referenced by the EntryId parameter.
+** NextEntryId - [out] Handle of next (newer adjacent) entry in event
+** log. Reserved event log entry ID values: SAHPI_OLDEST_ENTRY Not valid
+** for this parameter. Used only for the EntryID parameter.
+** SAHPI_NEWEST_ENTRY Not valid for this parameter. Used only for the
+** EntryID parameter. SAHPI_NO_MORE_ENTRIES No more entries in the log
+** after the one referenced by the EntryId parameter.
+** EventLogEntry - [out] Pointer to retrieved event log entry.
+** Rdr - [in/out] Pointer to structure to receive resource data record
+** associated with the event, if available. If NULL, no RDR data will be
+** returned.
+** RptEntry - [in/out] Pointer to structure to receive RPT Entry
+** associated with the event, if available. If NULL, no RPT entry data
+** will be returned.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Event logs may include RPT entries and resource data records
+** associated with the resource and sensor issuing an event along with
+** the basic event data in the log. Because the system may be
+** reconfigured after the event was entered in the log, this stored
+** information may be important to interpret the event. If the event log
+** includes logged RPT Entries and/or RDRs, and if the caller provides a
+** pointer to a structure to receive this information, it will be
+** returned along with the event log entry. If the caller provides a
+** pointer for an RPT entry, but the event log does not include a logged
+** RPT entry for the event being returned, RptEntry->ResourceCapabilities
+** will be set to zero. No valid RPTEntry will have a zero value here. If
+** the caller provides a pointer for an RDR, but the event log does not
+** include a logged RDR for the event being returned, Rdr->RdrType will
+** be set to SAHPI_NO_RECORD.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogEntryGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSelEntryIdT EntryId,
+ SAHPI_OUT SaHpiSelEntryIdT *PrevEntryId,
+ SAHPI_OUT SaHpiSelEntryIdT *NextEntryId,
+ SAHPI_OUT SaHpiSelEntryT *EventLogEntry,
+ SAHPI_INOUT SaHpiRdrT *Rdr,
+ SAHPI_INOUT SaHpiRptEntryT *RptEntry
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogEntryAdd
+**
+** Description:
+** This function enables system management software to add entries to the
+** system event log.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource that contains the system
+** event log to be managed. Set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the Domain System Event Log.
+** EvtEntry - [in] Pointer to event log entry data to write to the system
+** event log.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** This function forces a write of the event to the addressed event log.
+** Nothing else is done with the event. Specific implementations of HPI
+** may have restrictions on how much data may be passed to the
+** saHpiEventLogEntryAdd() function. These restrictions should be
+** documented by the provider of the HPI interface. If more event log
+** data is provided than can be written, an error will be returned.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogEntryAdd (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSelEntryT *EvtEntry
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogEntryDelete
+**
+** Description:
+** This function deletes an event log entry. This operation is only valid
+** if so indicated by saHpiEventLogInfoGet(), via the
+** DeleteEntrySupported field in the SaHpiSelInfoT structure.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] ResourceID of the resource that contains the system
+** event log to be managed. Set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the domain system event log.
+** EntryId - [in] Entry ID on the event log entry to delete. Reserved
+** event log entry ID values: SAHPI_OLDEST_ENTRY - Oldest entry in the
+** log. SAHPI_NEWEST_ENTRY - Newest entry in the log.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_INVALID_CMD is returned if this log does not
+** support this operation.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogEntryDelete (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSelEntryIdT EntryId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogClear
+**
+** Description:
+** This function erases the contents of the specified system event log.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] ResourceID of the resource that contains the system
+** event log to be managed. Set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the domain system event log.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Note that all event logs must support the "clear" operation,
+** regardless of the setting of the DeleteEntrySupported field in the
+** SaHpiSelInfoT structure returned by saHpiEventLogInfoGet().
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogClear (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogTimeGet
+**
+** Description:
+** This function retrieves the current time from the event log's own time
+** clock. The value of this clock is used to timestamp log entries
+** written into the log.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] ResourceID of the resource that contains the System
+** Event Log to be managed. Set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the Domain System Event Log.
+** Time - [out] Pointer to the returned SEL current time. If the
+** implementation cannot supply an absolute time value, then it may
+** supply a time relative to some system-defined epoch, such as system
+** boot. If the time value is less than or equal to
+** SAHPI_TIME_MAX_RELATIVE, but not SAHPI_TIME_UNSPECIFIED, then it is
+** relative; if it is greater than SAHPI_TIME_MAX_RELATIVE, then it is
+** absolute. The value SAHPI_TIME_UNSPECIFIED indicates that the time is
+** not set, or cannot be determined.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogTimeGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiTimeT *Time
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogTimeSet
+**
+** Description:
+** This function sets the event log's time clock, which is used to
+** timestamp events written into the log.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource that contains the system
+** event log to be managed. set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the domain system event log.
+** Time - [in] time to set the SEL clock to. If the implementation cannot
+** supply an absolute time, then it may supply a time relative to some
+** system-defined epoch, such as system boot. If the timestamp value is
+** less than or equal to SAHPI_TIME_MAX_RELATIVE, but not
+** SAHPI_TIME_UNSPECIFIED, then it is relative; if it is greater than
+** SAHPI_TIME_MAX_RELATIVE, then it is absolute. The value
+** SAHPI_TIME_UNSPECIFIED indicates that the time of the event cannot be
+** determined.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogTimeSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiTimeT Time
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogStateGet
+**
+** Description:
+** This function enables system management software to get the event log
+** state. If the event log is "disabled" no events generated within the
+** HPI implementation will be added to the event log. Events may still be
+** added to the event log with the saHpiEventLogEntryAdd() function. When
+** the event log is "enabled" events may be automatically added to the
+** event log as they are generated in a resource or a domain, however, it
+** is implementation-specific which events are automatically added to any
+** event log.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] ResourceID of the resource that contains the System
+** Event Log to be managed. Set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the Domain System Event Log.
+** Enable - [out] Pointer to the current SEL state. True indicates that
+** the SEL is enabled; false indicates that it is disabled.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiBoolT *Enable
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogStateSet
+**
+** Description:
+** This function enables system management software to set the event log
+** enabled state. If the event log is "disabled" no events generated
+** within the HPI implementation will be added to the event log. Events
+** may still be added to the event log using the saHpiEventLogEntryAdd()
+** function. When the event log is "enabled" events may be automatically
+** added to the event log as they are generated in a resource or a
+** domain. The actual set of events that are automatically added to any
+** event log is implementation-specific. Typically, the HPI
+** implementation will provide an appropriate default value for this
+** parameter, which may vary by resource. This function is provided so
+** that management software can override the default, if desired. Note:
+** If a resource hosting an event log is re-initialized (e.g., because of
+** a hot-swap action), the HPI implementation may reset the value of this
+** parameter.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource that contains the system
+** event log to be managed. Set to SAHPI_DOMAIN_CONTROLLER_ID to address
+** the domain system event log.
+** Enable - [in] SEL state to be set. True indicates that the SEL is to
+** be enabled; false indicates that it is to be disabled.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogStateSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiBoolT Enable
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSubscribe
+**
+** Description:
+** This function allows the caller to subscribe for session events. This
+** single call provides subscription to all session events, regardless of
+** event type or event severity. Only one subscription is allowed per
+** session, and additional subscribers will receive an appropriate error
+** code. No event filtering will be done by the underlying management
+** service.
+**
+** Parameters:
+** SessionId - [in] Session for which event subscription will be opened.
+** ProvideActiveAlarms - [in] Indicates whether or not alarms which are
+** active at the time of subscription should be queued for future
+** retrieval via the saHpiEventGet() function.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_DUPLICATE is returned when a subscription is
+** already in place for this session.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSubscribe (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiBoolT ProvideActiveAlarms
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiUnsubscribe
+**
+** Description:
+** This function removes the event subscription for the session. After
+** removal of a subscription, additional saHpiEventGet() calls will not
+** be allowed unless the caller re-subscribes for events first. Any
+** events that are still in the event queue when this function is called
+** will be cleared from it.
+**
+** Parameters:
+** SessionId - [in] Session for which event subscription will be closed.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_INVALID_REQUEST is returned if the caller is
+** not currently subscribed for events in this session.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiUnsubscribe (
+ SAHPI_IN SaHpiSessionIdT SessionId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEventGet
+**
+** Description:
+** This function allows the caller to get an event. This call is only
+** valid within a session, which has subscribed for events. If the
+** ProvideActiveAlarms parameter was set in the subscription, the first
+** events retrieved will reflect the state of currently active alarms for
+** the resources belonging to the domain. After all active alarms are
+** retrieved this function will begin returning newly generated events as
+** the domain controller receives them. If there are one or more events
+** on the event queue when this function is called, it will immediately
+** return the next event on the queue. Otherwise, if the Timeout
+** parameter is SAHPI_TIMEOUT_IMMEDIATE, it will return
+** SA_ERR_HPI_TIMEOUT immediately. Otherwise, it will block for a time
+** specified by the timeout parameter; if an event is added to the queue
+** within that time, it will be returned immediately; if not,
+** saHpiEventGet() will return SA_ERR_HPI_TIMEOUT. If the Timeout
+** parameter is SAHPI_TIMEOUT_BLOCK, then saHpiEventGet() will block
+** indefinitely, until an event becomes available, and then return that
+** event. This provides for notification of events as they occur.
+**
+** Parameters:
+** SessionId - [in] Session for which events are retrieved.
+** Timeout - [in] The number of nanoseconds to wait for an event to
+** arrive. Reserved time out values: SAHPI_TIMEOUT_IMMEDIATE Time out
+** immediately if there are no events available (non-blocking call).
+** SAHPI_TIMEOUT_BLOCK Call should not return until an event is
+** retrieved.
+** Event - [out] Pointer to the next available event.
+** Rdr - [in/out] Pointer to structure to receive the resource data
+** associated with the event. If NULL, no RDR will be returned.
+** RptEntry - [in/out] Pointer to structure to receive the RPT entry
+** associated with the resource that generated the event. If NULL, no RPT
+** entry will be returned.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_TIMEOUT is returned if no event is available
+** to return within the timeout period. If SAHPI_TIMEOUT_IMMEDIATE is
+** passed in the Timeout parameter, this error return will be used if
+** there is no event queued when the function is called.
+**
+** Remarks:
+** If the caller provides a pointer for an RPT entry, but the event does
+** not include a valid resource ID for a resource in the domain (possible
+** on OEM or USER type event), then the ResourceCapabilities field in
+** *RptEntry will be set to zero. No valid RPT entry will have a zero
+** value here. If the caller provides a pointer for an RDR, but there is
+** no valid RDR associated with the event being returned (e.g., returned
+** event is not a sensor event), Rdr->RdrType will be set to
+** SAHPI_NO_RECORD. The timestamp reported in the returned event
+** structure is the best approximation an implementation has to when the
+** event actually occurred. The implementation may need to make an
+** approximation (such as the time the event was placed on the event
+** queue) because it may not have access to the actual time the event
+** occurred. The value SAHPI_TIME_UNSPECIFIED indicates that the time of
+** the event cannot be determined. If the implementation cannot supply an
+** absolute timestamp, then it may supply a timestamp relative to some
+** system-defined epoch, such as system boot. If the timestamp value is
+** less than or equal to SAHPI_TIME_MAX_RELATIVE, but not
+** SAHPI_TIME_UNSPECIFIED, then it is relative; if it is greater than
+** SAHPI_TIME_MAX_RELATIVE, then it is absolute. 6 Resource Functions
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiTimeoutT Timeout,
+ SAHPI_OUT SaHpiEventT *Event,
+ SAHPI_INOUT SaHpiRdrT *Rdr,
+ SAHPI_INOUT SaHpiRptEntryT *RptEntry
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiRdrGet
+**
+** Description:
+** This function returns a resource data record from the addressed
+** resource. Submitting an EntryId of SAHPI_FIRST_ENTRY results in the
+** first RDR being read. A returned NextEntryID of SAHPI_LAST_ENTRY
+** indicates the last RDR has been returned. A successful retrieval will
+** include the next valid EntryId. To retrieve the entire list of RDRs,
+** call this function first with an EntryId of SAHPI_FIRST_ENTRY and then
+** use the returned NextEntryId in the next call. Proceed until the
+** NextEntryId returned is SAHPI_LAST_ENTRY.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** EntryId - [in] Handle of the RDR to retrieve. Reserved entry ID
+** values: SAHPI_FIRST_ENTRY Get first entry SAHPI_LAST_ENTRY Reserved as
+** delimiter for end of list. Not a valid entry identifier.
+** NextEntryId - [out] Pointer to location to store Entry ID of next
+** entry in RDR repository.
+** Rdr - [out] Pointer to the structure to receive the requested resource
+** data record.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** A resource's RDR repository is static over the lifetime of the
+** resource; therefore no precautions are required against changes to the
+** content of the RDR repository while it is being accessed.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiRdrGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiEntryIdT EntryId,
+ SAHPI_OUT SaHpiEntryIdT *NextEntryId,
+ SAHPI_OUT SaHpiRdrT *Rdr
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSensorReadingGet
+**
+** Description:
+** This function is used to retrieve a sensor reading.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** SensorNum - [in] Sensor number for which the sensor reading is being
+** retrieved.
+** Reading - [out] Pointer to a structure to receive sensor reading
+** values.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorReadingGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_OUT SaHpiSensorReadingT *Reading
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSensorReadingConvert
+**
+** Description:
+** This function converts between raw and interpreted sensor reading
+** values. The type of conversion done depends on the passed-in
+** ReadingInput parameter. If it contains only a raw value, then this is
+** converted to an interpreted value in ConvertedReading; if it contains
+** only an interpreted value, then this is converted to a raw value in
+** ConvertedReading. If it contains neither type of value, or both, then
+** an error is returned. The ReadingInput parameter is not altered in any
+** case. If the sensor does not use raw values - i.e., it directly
+** returns interpreted values - then this routine returns an error.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** SensorNum - [in] Sensor number for which reading is associated.
+** ReadingInput - [in] Pointer to the structure that contains raw or
+** interpreted reading to be converted.
+** ConvertedReading - [out] Pointer to structure to hold converted
+** reading.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_HPI_INVALID_PARAMS is returned if the ReadingInput
+** parameter is invalid; e.g. if it contains neither a raw nor an
+** interpreted value; or if it contains both; or if it contains an
+** invalid value. SA_ERR_HPI_INVALID_DATA is returned if the sensor does
+** not support raw readings. SA_ERR_HPI_NOT_PRESENT is returned if the
+** sensor is not present.
+**
+** Remarks:
+** The EventStatus field in ReadingInput is not used by this function. To
+** make conversions, sensor-specific data may be required. Thus, the
+** function references a particular sensor in the system through the
+** SessionID/ResourceID/SensorNum parameters. If this sensor is not
+** present, and sensor- specific information is required, the conversion
+** will fail and SA_ERR_HPI_NOT_PRESENT will be returned.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorReadingConvert (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_IN SaHpiSensorReadingT *ReadingInput,
+ SAHPI_OUT SaHpiSensorReadingT *ConvertedReading
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSensorThresholdsGet
+**
+** Description:
+** This function retrieves the thresholds for the given sensor.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** SensorNum - [in] Sensor number for which threshold values are being
+** retrieved.
+** SensorThresholds - [out] Pointer to returned sensor thresholds.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorThresholdsGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_OUT SaHpiSensorThresholdsT *SensorThresholds
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSensorThresholdsSet
+**
+** Description:
+** This function sets the specified thresholds for the given sensor.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of addressed resource.
+** SensorNum - [in] Sensor number for which threshold values are being
+** set.
+** SensorThresholds - [in] Pointer to the sensor thresholds values being
+** set.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** For each threshold or hysteresis value to be set, the corresponding
+** sensor reading structure must indicate whether a raw or interpreted
+** value is present. If neither are present, then that threshold or
+** hysteresis value will not be set. Each sensor may require settings to
+** be done with raw, or interpreted values, or may permit either; this is
+** defined by the field ThresholdDefn.TholdCapabilities in the sensor's
+** RDR (saHpiSensorRecT). If the interpreted value and raw value are both
+** provided, and both are legal for the sensor, the interpreted value
+** will be ignored and the raw value will be used.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorThresholdsSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_IN SaHpiSensorThresholdsT *SensorThresholds
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSensorTypeGet
+**
+** Description:
+** This function retrieves the sensor type and event category for the
+** specified sensor.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** SensorNum - [in] Sensor number for which the type is being retrieved
+** Type - [out] Pointer to returned enumerated sensor type for the
+** specified sensor.
+** Category - [out] Pointer to location to receive the returned sensor
+** event category.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorTypeGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_OUT SaHpiSensorTypeT *Type,
+ SAHPI_OUT SaHpiEventCategoryT *Category
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSensorEventEnablesGet
+**
+** Description:
+** This function provides the ability to get the disable or enable event
+** message generation status for individual sensor events. The sensor
+** event states are relative to the event category specified by the
+** sensor. See the SaHpiEventCategoryT definition in section 7.3,
+** "Events, Part 1," on page 83 for more information. Within the
+** structure returned, there are two elements that contain bit flags; one
+** for assertion events and one for de-assertion events. A bit set to '1'
+** in the "AssertEvents" element in the structure indicates that an event
+** will be generated when the corresponding event state changes from
+** de-asserted to asserted on that sensor. A bit set to '1' in the
+** "DeassertEvents" element in the structure indicates that an event will
+** be generated when the corresponding event state changes from asserted
+** to de-asserted on that sensor. The saHpiSensorEventEnablesGet()
+** function also returns the general sensor status - whether the sensor
+** is completely disabled, or event generation is completely disabled.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** SensorNum - [in] Sensor number for which the event enable
+** configuration is being requested
+** Enables - [out] Pointer to the structure for returning sensor status
+** and event enable information.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Disabling events means that events are disabled for all sessions, not
+** just the session referenced by the SessionId parameter. For sensors
+** hosted by resources that have the "SAHPI_CAPABILITY_EVT_DEASSERTS"
+** flag set in its RPT entry, the "AssertEvents" element and the
+** "DeassertsEvents" element will always have same value.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorEventEnablesGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_OUT SaHpiSensorEvtEnablesT *Enables
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSensorEventEnablesSet
+**
+** Description:
+** This function provides the ability to set the disable or enable event
+** message generation status for individual sensor events. The sensor
+** event states are relative to the event category specified by the
+** sensor. See the SaHpiEventCategoryT definition for more information.
+** Within the structure passed, there are two elements, which contain bit
+** flags; one for assertion events and one for de-assertion events.
+** However, the use of these two elements depends on whether the resource
+** addressed has the "SAHPI_CAPABILITY_EVT_DEASSERTS" flag set in its RPT
+** entry. This capability, if set, advertises that all sensors hosted by
+** the resource will always send a "de-assert" event when any state is
+** de-asserted whose assertion generates an "assert" event. Thus, for
+** sensors hosted by resources that advertise this behavior, it is not
+** meaningful to control assert events and de-assert events separately.
+** For sensors on resources that do not have the
+** "SAHPI_CAPABILITY_EVT_DEASSERTS" flag set, a bit set to '1' in the
+** "AssertEvents" element in the structure indicates that an event will
+** be generated when the corresponding event state changes from
+** de-asserted to asserted on that sensor., and a bit set to '1' in the
+** "DeassertEvents" element in the structure indicates that an event will
+** be generated when the corresponding event state changes from asserted
+** to de-asserted on that sensor. For sensors on resources, which do have
+** the "SAHPI_CAPABILITY_EVT_DEASSERTS" flag set, the "DeassertEvents"
+** element is not used. For sensors on these resources, a bit set to '1'
+** in the "AssertEvents" element in the structure indicates that an event
+** will be generated when the corresponding event state changes in either
+** direction (de-asserted to asserted or asserted to de-asserted). The
+** saHpiSensorEventEnablesSet() function also allows setting of general
+** sensor status - whether the sensor is completely disabled, or event
+** generation is completely disabled.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** SensorNum - [in] Sensor number for which the event enables are being
+** set.
+** Enables - [in] Pointer to the structure containing the enabled status
+** for each event.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Disabling events means that events are disabled for all sessions, not
+** just the session referenced by the SessionId parameter.
+** saHpiSensorEventEnablesGet () will return the values which were last
+** set by saHpiSensorEventEnablesSet() for the "AssertEvents" and
+** "DeassertEvents" elements in the passed data structures. However, for
+** sensors hosted by any resource that has the
+** SAHPI_CAPABILITY_EVT_DEASSERTS flag set in its RPT entry, the passed
+** "AssertEvents" element on the saHpiSensorEventEnablesSet () function
+** is used for both assertion and de-assertion event enable flags. In
+** this case, this value will be returned in both the "AssertEvents" and
+** "DeassertEvents" elements on a subsequent saHpiSensorEventEnablesGet
+** () call.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorEventEnablesSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_IN SaHpiSensorEvtEnablesT *Enables
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiControlTypeGet
+**
+** Description:
+** This function retrieves the control type of a control object.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** CtrlNum - [in] Control number
+** Type - [out] Pointer to SaHpiCtrlTypeT variable to receive the
+** enumerated control type for the specified control.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** The Type parameter must point to a variable of type SaHpiCtrlTypeT.
+** Upon successful completion, the enumerated control type is returned in
+** the variable pointed to by Type.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiControlTypeGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiCtrlNumT CtrlNum,
+ SAHPI_OUT SaHpiCtrlTypeT *Type
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiControlStateGet
+**
+** Description:
+** This function retrieves the current state (generally the last state
+** set) of a control object.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of addressed resource.
+** CtrlNum - [in] Number of the control for which the state is being
+** retrieved.
+** CtrlState - [in/out] Pointer to a control data structure into which
+** the current control state will be placed. For text controls, the line
+** number to read is passed in via CtrlState->StateUnion.Text.Line.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Note that Text controls are unique in that they have a state
+** associated with each line of the control - the state being the text on
+** that line. The line number to be read is passed in to
+** sahpiControlStateGet()via CtrlState- >StateUnion.Text.Line; the
+** contents of that line of the control will be returned in CtrlState-
+** >StateUnion.Text.Text. If the line number passed in is
+** SAHPI_TLN_ALL_LINES, then sahpiControlStateGet() will return the
+** entire text of the control, or as much of it as will fit in a single
+** SaHpiTextBufferT, in CtrlState- >StateUnion.Text.Text. This value will
+** consist of the text of all the lines concatenated, using the maximum
+** number of characters for each line (no trimming of trailing blanks).
+** Note that depending on the data type and language, the text may be
+** encoded in 2-byte Unicode, which requires two bytes of data per
+** character. Note that the number of lines and columns in a text control
+** can be obtained from the control's Resource Data Record.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiControlStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiCtrlNumT CtrlNum,
+ SAHPI_INOUT SaHpiCtrlStateT *CtrlState
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiControlStateSet
+**
+** Description:
+** This function is used for setting the state of the specified control
+** object.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** CtrlNum - [in] Number of the control for which the state is being set.
+**
+** CtrlState - [in] Pointer to a control state data structure holding the
+** state to be set
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** The CtrlState parameter must be of the correct type for the specified
+** control. Text controls include a line number and a line of text in the
+** CtrlState parameter, allowing update of just a single line of a text
+** control. If less than a full line of data is written, the control will
+** clear all spaces beyond those written on the line. Thus writing a
+** zero-length string will clear the addressed line. It is also possible
+** to include more characters in the text passed in the CtrlState
+** structure than will fit on one line; in this case, the control will
+** "wrap" to the next line (still clearing the trailing characters on the
+** last line written). Thus, there are two ways to write multiple lines
+** to a text control: (a) call saHpiControlStateSet() repeatedly for each
+** line, or (b) call saHpiControlStateSet() once and send more characters
+** than will fit on one line. The caller should not assume any "cursor
+** positioning" characters are available to use, but rather should always
+** write full lines and allow "wrapping" to occur. When calling
+** saHpiControlStateSet() for a text control, the caller may set the line
+** number to SAHPI_TLN_ALL_LINES; in this case, the entire control will
+** be cleared, and the data will be written starting on line 0. (This is
+** different from simply writing at line 0, which only alters the lines
+** written to.) This feature may be used to clear the entire control,
+** which can be accomplished by setting: CtrlState->StateUnion.Text.Line
+** = SAHPI_TLN_ALL_LINES; CtrlState->StateUnion.Text.Text.DataLength = 0;
+** Note that the number of lines and columns in a text control can be
+** obtained from the control's Resource Data Record.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiControlStateSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiCtrlNumT CtrlNum,
+ SAHPI_IN SaHpiCtrlStateT *CtrlState
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEntityInventoryDataRead
+**
+** Description:
+** This function returns inventory data for a particular entity
+** associated with a resource.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** EirId - [in] Identifier for the entity inventory repository.
+** BufferSize - [in] Size of the InventData buffer passed in.
+** InventData - [out] Pointer to the buffer for the returned data.
+** ActualSize - [out] Pointer to size of the actual amount of data
+** returned.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned. SA_ERR_INVENT_DATA_TRUNCATED is returned if the buffer
+** passed in the InventData structure is not large enough (as indicated
+** by the "BufferSize" parameter) to hold the entire InventData
+** structure.
+**
+** Remarks:
+** Before calling saHpiEntityInventoryDataRead() the caller should
+** allocate a sufficiently large buffer to hold the data, and pass the
+** size of the buffer in the "BufferSize" parameter. The
+** saHpiEntityInventoryDataRead() function will return, at the location
+** pointed to by the ActualSize parameter, the actual space used in the
+** buffer to hold the returned data. If the data will not fit in the
+** buffer, as much as will fit will be returned, *ActualSize will be set
+** to indicated a suggested buffer size for the entire inventory data,
+** the "Validity" field in the InventData buffer will be set to
+** "SAHPI_INVENT_DATA_OVERFLOW," and an error return will be made. Since
+** it is impossible to know how large the inventory data may be without
+** actually reading and processing it from the entity inventory
+** repository, it may be advisable to err on the large side in allocating
+** the buffer. Note that the data includes many pointers to
+** SaHpiTextBufferT structures. The implementation of
+** saHpiEntityInventoryDataRead() may not reserve space for the maximum
+** size of each of these structures when formatting the data in the
+** returned buffer. Thus, if a user wishes to lengthen the data in one of
+** these structures, a new SaHpiTextBufferT structure should be
+** allocated, and the appropriate pointer reset to point to this new
+** structure in memory. See the description of the SaHpiInventoryDataT
+** structure in section 7.9, "Entity Inventory Data," on page 94, for
+** details on the format of the returned data.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEntityInventoryDataRead (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiEirIdT EirId,
+ SAHPI_IN SaHpiUint32T BufferSize,
+ SAHPI_OUT SaHpiInventoryDataT *InventData,
+ SAHPI_OUT SaHpiUint32T *ActualSize
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiEntityInventoryDataWrite
+**
+** Description:
+** This function writes the specified data to the inventory information
+** area. Note: If the resource hosting the inventory data is
+** re-initialized, or if the entity itself is removed and reinserted, the
+** inventory data may be reset to its default settings, losing data
+** written to the repository with this function.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** EirId - [in] Identifier for the entity inventory repository.
+** InventData - [in] Pointer to data to write to the repository.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** The SaHpiInventoryDataT structure consists of a Validity field and
+** then a set of pointers to record structures. It is not required that
+** all pointers point to data within a single contiguous buffer. The
+** "Validity" field in the SaHpiInventoryDataT structure must be set to
+** "SAHPI_INVENT_DATA_VALID," or else the saHpiEntityInventoryDataWrite()
+** function will take no action and return an error. This is to help
+** prevent invalid data returned by a saHpiEntityInventoryDataRead()
+** function from being inadvertently written to the resource. For this
+** protection to work, the caller should not change the value of the
+** "Validity" field in the SaHpiInventoryDataT structure unless building
+** an entire Inventory Data set from scratch. Some implementations may
+** impose limitations on the languages of the strings passed in within
+** the InventData parameter. Implementation-specific documentation
+** should identify these restrictions.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEntityInventoryDataWrite (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiEirIdT EirId,
+ SAHPI_IN SaHpiInventoryDataT *InventData
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiWatchdogTimerGet
+**
+** Description:
+** This function retrieves the current watchdog timer settings and
+** configuration.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource, which contains the
+** watchdog timer being addressed.
+** WatchdogNum - [in] The watchdog number that specifies the watchdog
+** timer on a resource.
+** Watchdog - [out] Pointer to watchdog data structure.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** See the description of the SaHpiWatchdogT structure in 7.11,
+** "Watchdogs" on page 96 for details on what information is returned by
+** this function.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiWatchdogTimerGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiWatchdogNumT WatchdogNum,
+ SAHPI_OUT SaHpiWatchdogT *Watchdog
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiWatchdogTimerSet
+**
+** Description:
+** This function provides a method for initializing the watchdog timer
+** configuration. Once the appropriate configuration has be set using
+** saHpiWatchdogTimerSet(), the user must then call
+** saHpiWatchdogTimerReset() to initially start the watchdog timer.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the resource that contains the
+** watchdog timer being addressed.
+** WatchdogNum - [in] The watchdog number specifying the specific
+** watchdog timer on a resource.
+** Watchdog - [in] Pointer to watchdog data structure.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** If the initial counter value in the SaHpiWatchdogT structure is set to
+** 0, the Watchdog will immediately time out and take the pre-timeout and
+** timeout actions, as well as log an event. This provides a mechanism
+** for software to force an immediate recovery action should that be
+** dependent on a Watchdog timeout occurring. See the description of the
+** SaHpiWatchdogT structure for more details on the effects of this
+** command related to specific data passed in that structure.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiWatchdogTimerSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiWatchdogNumT WatchdogNum,
+ SAHPI_IN SaHpiWatchdogT *Watchdog
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiWatchdogTimerReset
+**
+** Description:
+** This function provides a method to start or restart the watchdog timer
+** from the initial countdown value.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID for the resource that contains the
+** watchdog timer being addressed.
+** WatchdogNum - [in] The watchdog number specifying the specific
+** watchdog timer on a resource.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** If the Watchdog has been configured to issue a Pre-Timeout interrupt,
+** and that interrupt has already occurred, the saHpiWatchdogTimerReset()
+** function will not reset the watchdog counter. The only way to stop a
+** Watchdog from timing out once a Pre-Timeout interrupt has occurred is
+** to use the saHpiWatchdogTimerSet() function to reset and/or stop the
+** timer.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiWatchdogTimerReset (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiWatchdogNumT WatchdogNum
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiHotSwapControlRequest
+**
+** Description:
+** A resource supporting hot swap typically supports default policies for
+** insertion and extraction. On insertion, the default policy may be for
+** the resource to turn the associated FRU's local power on and to
+** de-assert reset. On extraction, the default policy may be for the
+** resource to immediately power off the FRU and turn on a hot swap
+** indicator. This function allows a caller, after receiving a hot swap
+** event with HotSwapState equal to SAHPI_HS_STATE_INSERTION_PENDING or
+** SAHPI_HS_STATE_EXTRACTION_PENDING, to request control of the hot swap
+** policy and prevent the default policy from being invoked. Because a
+** resource that supports the simplified hot swap model will never
+** transition into Insertion Pending or Extraction Pending states, this
+** function is not applicable to those resources.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiHotSwapControlRequest (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourceActiveSet
+**
+** Description:
+** During insertion, a resource supporting hot swap will generate an
+** event to indicate that it is in the INSERTION PENDING state. If the
+** management middleware or other user software calls
+** saHpiHotSwapControlRequest() before the resource begins an auto-insert
+** operation, then the resource will remain in INSERTION PENDING state
+** while the user acts on the resource to integrate it into the system.
+** During this state, the user can instruct the resource to power on the
+** associated FRU, to de-assert reset, or to turn off its hot swap
+** indicator using the saHpiResourcePowerStateSet(),
+** saHpiResourceResetStateSet(), or saHpiHotSwapIndicatorStateSet()
+** functions, respectively. Once the user has completed with the
+** integration of the FRU, this function must be called to signal that
+** the resource should now transition into ACTIVE/HEALTHY or
+** ACTIVE/UNHEALTHY state (depending on whether or not there are active
+** faults). The user may also use this function to request a resource to
+** return to the ACTIVE/HEALTHY or ACTIVE/UNHEALTHY state from the
+** EXTRACTION PENDING state in order to reject an extraction request.
+** Because a resource that supports the simplified hot swap model will
+** never transition into Insertion Pending or Extraction Pending states,
+** this function is not applicable to those resources.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Only valid if resource is in INSERTION PENDING or EXTRACTION PENDING
+** state and an auto-insert or auto-extract policy action has not been
+** initiated.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceActiveSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourceInactiveSet
+**
+** Description:
+** During extraction, a resource supporting hot swap will generate an
+** event to indicate that it is in the EXTRACTION PENDING state. If the
+** management middleware or other user software calls
+** saHpiHotSwapControlRequest() before the resource begins an
+** auto-extract operation, then the resource will remain in EXTRACTION
+** PENDING state while the user acts on the resource to isolate the
+** associated FRU from the system. During this state, the user can
+** instruct the resource to power off the FRU, to assert reset, or to
+** turn on its hot swap indicator using the saHpiResourcePowerStateSet(),
+** saHpiResourceResetStateSet(), or saHpiHotSwapIndicatorStateSet()
+** functions, respectively. Once the user has completed the shutdown of
+** the FRU, this function must be called to signal that the resource
+** should now transition into INACTIVE state. The user may also use this
+** function to request a resource to return to the INACTIVE state from
+** the INSERTION PENDING state to abort a hot-swap insertion action.
+** Because a resource that supports the simplified hot swap model will
+** never transition into Insertion Pending or Extraction Pending states,
+** this function is not applicable to those resources.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Only valid if resource is in EXTRACTION PENDING or INSERTION PENDING
+** state and an auto-extract or auto-insert policy action has not been
+** initiated.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceInactiveSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiAutoInsertTimeoutGet
+**
+** Description:
+** This function allows the caller to request the auto-insert timeout
+** value. This value indicates how long the HPI implementation will wait
+** before the default auto-insertion policy is invoked. Further
+** information on the auto-insert timeout can be found in the function
+** saHpiAutoInsertTimeoutSet().
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** Timeout - [out] Pointer to location to store the number of nanoseconds
+** to wait before autonomous handling of the hotswap event. Reserved time
+** out values: SAHPI_TIMEOUT_IMMEDIATE indicates autonomous handling is
+** immediate. SAHPI_TIMEOUT_BLOCK indicates autonomous handling does not
+** occur.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAutoInsertTimeoutGet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_OUT SaHpiTimeoutT *Timeout
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiAutoInsertTimeoutSet
+**
+** Description:
+** This function allows the caller to configure a timeout for how long to
+** wait before the default auto-insertion policy is invoked. This
+** function accepts a parameter instructing the implementation to impose
+** a delay before a resource will perform its default hot swap policy for
+** auto-insertion. The parameter may be set to SAHPI_TIMEOUT_IMMEDIATE to
+** direct resources to proceed immediately to auto-insertion, or to
+** SAHPI_TIMEOUT_BLOCK to prevent auto-insertion from ever occurring. If
+** the parameter is set to another value, then it defines the number of
+** nanoseconds between the time a hot swap event with HotSwapState =
+** SAHPI_HS_STATE_INSERTION_PENDING is generated, and the time that the
+** auto-insertion policy will be invoked for that resource. If, during
+** this time period, a saHpiHotSwapControlRequest() function is
+** processed, the timer will be stopped, and the auto-insertion policy
+** will not be invoked. Once the auto-insertion process begins, the user
+** software will not be allowed to take control of the insertion process;
+** hence, the timeout should be set appropriately to allow for this
+** condition. Note that the timeout period begins when the hot swap event
+** with HotSwapState = SAHPI_HS_STATE_INSERTION_PENDING is initially
+** generated; not when it is received by a caller with a saHpiEventGet()
+** function call, or even when it is placed in a session event queue.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** Timeout - [in] The number of nanoseconds to wait before autonomous
+** handling of the hotswap event. Reserved time out values:
+** SAHPI_TIMEOUT_IMMEDIATE indicates proceed immediately to autonomous
+** handling. SAHPI_TIMEOUT_BLOCK indicates prevent autonomous handling.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAutoInsertTimeoutSet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiTimeoutT Timeout
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiAutoExtractTimeoutGet
+**
+** Description:
+** This function allows the caller to request the timeout for how long
+** the implementation will wait before the default auto-extraction policy
+** is invoked. Further information on auto-extract time outs is detailed
+** in saHpiAutoExtractTimeoutSet().
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** Timeout - [out] Pointer to location to store the number of nanoseconds
+** to wait before autonomous handling of the hotswap event. Reserved time
+** out values: SAHPI_TIMEOUT_IMMEDIATE indicates autonomous handling is
+** immediate. SAHPI_TIMEOUT_BLOCK indicates autonomous handling does not
+** occur.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAutoExtractTimeoutGet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiTimeoutT *Timeout
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiAutoExtractTimeoutSet
+**
+** Description:
+** This function allows the caller to configure a timeout for how long to
+** wait before the default auto-extraction policy is invoked. This
+** function accepts a parameter instructing the implementation to impose
+** a delay before a resource will perform its default hot swap policy for
+** auto-extraction. The parameter may be set to SAHPI_TIMEOUT_IMMEDIATE
+** to direct the resource to proceed immediately to auto-extraction, or
+** to SAHPI_TIMEOUT_BLOCK to prevent auto-extraction from ever occurring
+** on a resource. If the parameter is set to another value, then it
+** defines the number of nanoseconds between the time a hot swap event
+** with HotSwapState = SAHPI_HS_STATE_EXTRACTION_PENDING is generated,
+** and the time that the auto- extraction policy will be invoked for the
+** resource. If, during this time period, a saHpiHotSwapControlRequest()
+** function is processed, the timer will be stopped, and the
+** auto-extraction policy will not be invoked. Once the auto-extraction
+** process begins, the user software will not be allowed to take control
+** of the extraction process; hence, the timeout should be set
+** appropriately to allow for this condition. Note that the timeout
+** period begins when the hot swap event with HotSwapState =
+** SAHPI_HS_STATE_EXTRACTION_PENDING is initially generated; not when it
+** is received by a caller with a saHpiEventGet() function call, or even
+** when it is placed in a session event queue. The auto-extraction policy
+** is set at the resource level and is only supported by resources
+** supporting the "Managed Hot Swap" capability. After discovering that a
+** newly inserted resource supports "Managed Hot Swap," middleware or
+** other user software may use this function to change the default
+** auto-extraction policy for that resource. If a resource supports the
+** simplified hot-swap model, setting this timer has no effect since the
+** resource will transition directly to "Not Present" state on an
+** extraction.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** Timeout - [in] The number of nanoseconds to wait before autonomous
+** handling of the hotswap event. Reserved time out values:
+** SAHPI_TIMEOUT_IMMEDIATE indicates proceed immediately to autonomous
+** handling. SAHPI_TIMEOUT_BLOCK indicates prevent autonomous handling.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAutoExtractTimeoutSet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiTimeoutT Timeout
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiHotSwapStateGet
+**
+** Description:
+** This function allows the caller to retrieve the current hot swap state
+** of a resource. The returned state will be one of the following five
+** states: ? SAHPI_HS_STATE_INSERTION_PENDING ?
+** SAHPI_HS_STATE_ACTIVE_HEALTHY ? SAHPI_HS_STATE_ACTIVE_UNHEALTHY ?
+** SAHPI_HS_STATE_EXTRACTION_PENDING ? SAHPI_HS_STATE_INACTIVE The state
+** SAHPI_HS_STATE_NOT_PRESENT will never be returned, because a resource
+** that is not present cannot be addressed by this function in the first
+** place.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** State - [out] Pointer to location to store returned state information.
+**
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiHotSwapStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiHsStateT *State
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiHotSwapActionRequest
+**
+** Description:
+** A resource supporting hot swap typically requires a physical action on
+** the associated FRU to invoke an insertion or extraction process. An
+** insertion process is invoked by physically inserting the FRU into a
+** chassis. Physically opening an ejector latch or pressing a button
+** invokes the extraction process. This function allows the caller to
+** invoke an insertion or extraction process via software.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** Action - [in] Requested action: SAHPI_HS_ACTION_INSERTION or
+** SAHPI_HS_ACTION_EXTRACTION
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** There may be limitations on when saHpiHotSwapActionRequest() may be
+** called, and what value may be used for the "Action" parameter
+** depending on what state the resource is currently in. At the least,
+** this function may be called: ? To request an Insertion action when the
+** resource is in INACTIVE state ? To request an Extraction action when
+** the resource is in the ACTIVE/HEALTHY or ACTIVE/ UNHEALTHY state.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiHotSwapActionRequest (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiHsActionT Action
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourcePowerStateGet
+**
+** Description:
+** A typical resource supporting hot swap will have the ability to
+** control local power on the FRU associated with the resource. During
+** insertion, the FRU can be instructed to power on. During extraction
+** the FRU can be requested to power off. This function allows the caller
+** to retrieve the current power state of the FRU associated with the
+** specified resource.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** State - [out] The current power state of the resource.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** This function returns the actual low-level power state of the FRU,
+** regardless of what hot-swap state the resource is in. Not all
+** resources supporting managed hot swap will necessarily support this
+** function. In particular, resources that use the simplified hot swap
+** model may not have the ability to control FRU power. An appropriate
+** error code will be returned if the resource does not support power
+** control on the FRU.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourcePowerStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiHsPowerStateT *State
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourcePowerStateSet
+**
+** Description:
+** A typical resource supporting hot swap will have to ability to control
+** local power on the FRU associated with the resource. During insertion,
+** the FRU can be instructed to power on. During extraction the FRU can
+** be requested to power off. This function allows the caller to set the
+** current power state of the FRU associated with the specified resource.
+**
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** State - [in] the new power state that the specified resource will be
+** set to.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** This function controls the hardware power on the FRU of what hot-swap
+** state the resource is in. For example, it is legal (and may be
+** desirable) to cycle power on the FRU even while it is in ACTIVE state
+** in order to attempt to clear a fault condition. Similarly, a resource
+** could be instructed to power on a FRU even while it is in INACTIVE
+** state, for example, in order to run off-line diagnostics. Not all
+** resources supporting managed hot swap will necessarily support this
+** function. In particular, resources that use the simplified hot swap
+** model may not have the ability to control FRU power. An appropriate
+** error code will be returned if the resource does not support power
+** control on the FRU.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourcePowerStateSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiHsPowerStateT State
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiHotSwapIndicatorStateGet
+**
+** Description:
+** A FRU associated with a hot-swappable resource may include a hot swap
+** indicator such as a blue LED. This indicator signifies that the FRU is
+** ready for removal.. This function allows the caller to retrieve the
+** state of this indicator. The returned state is either
+** SAHPI_HS_INDICATOR_OFF or SAHPI_HS_INDICATOR_ON. This function will
+** return the state of the indicator, regardless of what hot swap state
+** the resource is in.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** State - [out] Pointer to location to store state of hot swap
+** indicator.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Not all resources supporting managed hot swap will necessarily support
+** this function. In particular, resources that use the simplified hot
+** swap model may not have the ability to control a FRU hot swap
+** indicator (it is likely that none exists). An appropriate error code
+** will be returned if the resource does not support control of a hot
+** swap indicator on the FRU.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiHotSwapIndicatorStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiHsIndicatorStateT *State
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiHotSwapIndicatorStateSet
+**
+** Description:
+** A FRU associated with a hot-swappable resource may include a hot swap
+** indicator such as a blue LED. This indicator signifies that the FRU is
+** ready for removal. This function allows the caller to set the state of
+** this indicator. Valid states include SAHPI_HS_INDICATOR_OFF or
+** SAHPI_HS_INDICATOR_ON. This function will set the indicator regardless
+** of what hot swap state the resource is in, though it is recommended
+** that this function be used only in conjunction with moving the
+** resource to the appropriate hot swap state.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource
+** State - [in] State of hot swap indicator to be set.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Not all resources supporting managed hot swap will necessarily support
+** this function. In particular, resources that use the simplified hot
+** swap model may not have the ability to control a FRU hot swap
+** indicator (it is likely that none exists). An appropriate error code
+** will be returned if the resource does not support control of a hot
+** swap indicator on the FRU.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiHotSwapIndicatorStateSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiHsIndicatorStateT State
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiParmControl
+**
+** Description:
+** This function allows the user to save and restore parameters
+** associated with a specific resource. Valid actions for this function
+** include: SAHPI_DEFAULT_PARM Restores the factory default settings for
+** a specific resource. Factory defaults include sensor thresholds and
+** configurations, and resource- specific configuration parameters.
+** SAHPI_SAVE_PARM Stores the resource configuration parameters in
+** non-volatile storage. Resource configuration parameters stored in
+** non-volatile storage will survive power cycles and resource resets.
+** SAHPI_RESTORE_PARM Restores resource configuration parameters from
+** non-volatile storage. Resource configuration parameters include sensor
+** thresholds and sensor configurations, as well as resource-specific
+** parameters.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** Action - [in] Action to perform on resource parameters.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code
+** is returned.
+**
+** Remarks:
+** Resource-specific parameters should be documented in an implementation
+** guide for the HPI implementation.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiParmControl (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiParmActionT Action
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourceResetStateGet
+**
+** Description:
+** This function gets the reset state of an entity, allowing the user to
+** determine if the entity is being held with its reset asserted. If a
+** resource manages multiple entities, this function will address the
+** entity which is identified in the RPT entry for the resource.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** ResetAction - [out] The current reset state of the entity. Valid reset
+** states are: SAHPI_RESET_ASSERT: The entity's reset is asserted, e.g.,
+** for hot swap insertion/extraction purposes SAHPI_RESET_DEASSERT: The
+** entity's reset is not asserted
+**
+** Return Value:
+** SA_OK is returned if the resource has reset control, and the reset
+** state has successfully been determined; otherwise, an error code is
+** returned. SA_ERR_HPI_INVALID_CMD is returned if the resource has no
+** reset control.
+**
+** Remarks:
+** SAHPI_RESET_COLD and SAHPI_RESET_WARM are pulsed resets, and are not
+** valid return values for ResetAction. If the entity is not being held
+** in reset (using SAHPI_RESET_ASSERT), the appropriate return value is
+** SAHPI_RESET_DEASSERT.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceResetStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiResetActionT *ResetAction
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiResourceResetStateSet
+**
+** Description:
+** This function directs the resource to perform the specified reset type
+** on the entity that it manages. If a resource manages multiple
+** entities, this function addresses the entity that is identified in the
+** RPT entry for the resource. Entities may be reset for a variety of
+** reasons. A misbehaving entity may be reset to bring it to a known
+** state. In these cases, either a warm reset or a cold reset may be
+** performed. A warm reset preserves entity state, whereas a cold reset
+** does not. Both of these reset types are pulsed asserted and then
+** de-asserted by the HPI implementation. This allows the HPI
+** implementation to hold the reset asserted for the appropriate length
+** of time, as needed by each entity. saHpiResourceResetStateSet() can
+** also be used for insertion and extraction scenarios. A typical
+** resource supporting hot swap will have to ability to control local
+** reset within the FRU. During insertion, a resource can be instructed
+** to assert reset, while the FRU powers on. During extraction a resource
+** can be requested to assert reset before the FRU is powered off. This
+** function allows the caller to set the reset state of the specified
+** FRU. SAHPI_RESET_ASSERT is used to hold the resource in reset; the FRU
+** is brought out of the reset state by using either SAHPI_COLD_RESET or
+** SAHPI_WARM_RESET.
+**
+** Parameters:
+** SessionId - [in] Handle to session context.
+** ResourceId - [in] Resource ID of the addressed resource.
+** ResetAction - [in] Type of reset to perform on the entity. Valid reset
+** actions are: SAHPI_COLD_RESET: Perform a 'Cold Reset' on the entity
+** (pulse), leaving reset de-asserted SAHPI_WARM_RESET: Perform a 'Warm
+** Reset' on the entity (pulse), leaving reset de-asserted
+** SAHPI_RESET_ASSERT: Put the entity into reset state and hold reset
+** asserted, e.g., for hot swap insertion/extraction purposes
+**
+** Return Value:
+** SA_OK is returned if the resource has reset control, and the requested
+** reset action has succeeded; otherwise, an error code is returned.
+** SA_ERR_HPI_INVALID_CMD is returned if the resource has no reset
+** control, or if the requested reset action is not supported by the
+** resource.
+**
+** Remarks:
+** Some resources may not support reset, or may only support a subset of
+** the defined reset action types. Also, on some resources, cold and warm
+** resets may be equivalent. 7 Data Type Definitions
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceResetStateSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiResetActionT ResetAction
+);
+
+
+
+#endif
+
diff --git a/hpiutil/SaHpi.h-B b/hpiutil/SaHpi.h-B
new file mode 100644
index 0000000..38d666b
--- /dev/null
+++ b/hpiutil/SaHpi.h-B
@@ -0,0 +1,6785 @@
+/*******************************************************************************
+**
+** FILE:
+** SaHpi.h
+**
+** DESCRIPTION:
+** This file provides the C language binding for the Service
+** Availability(TM) Forum Platform Interface. It contains all of
+** the prototypes and type definitions. Note, this file was
+** generated from the Platform Interface specification document.
+**
+** SPECIFICATION VERSION:
+** SAI-HPI-B.01.01
+**
+** DATE:
+** Tue Jun 1 2004 09:33
+**
+** LEGAL:
+** OWNERSHIP OF SPECIFICATION AND COPYRIGHTS.
+** The Specification and all worldwide copyrights therein are
+** the exclusive property of Licensor. You may not remove, obscure, or
+** alter any copyright or other proprietary rights notices that are in or
+** on the copy of the Specification you download. You must reproduce all
+** such notices on all copies of the Specification you make. Licensor
+** may make changes to the Specification, or to items referenced therein,
+** at any time without notice. Licensor is not obligated to support or
+** update the Specification.
+**
+** Copyright(c) 2004, Service Availability(TM) Forum. All rights
+** reserved.
+**
+*******************************************************************************/
+
+#ifndef __SAHPI_H
+#define __SAHPI_H
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Basic Data Types and Values **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* General Types - need to be specified correctly for the host architecture */
+
+/*
+** It is recommended that these types be defined such that the data sizes
+** and alignment of each data type are as indicated. The only requirement
+** for source compatibility is that the types be defined to be able to
+** contain at least the required data (e.g., at least signed 8-bit values
+** must be contained in the data type defined as SaHpiInt8T, etc.)
+** Following the full recommendations for data size and alignment, however,
+** may promote more binary compatibility.
+*/
+
+/* The following definitions produce the recommended sizes and alignments
+** using the gcc compiler for the i386 (IA-32) platform.
+**
+** Note, some recent versions of the gcc compiler exhibit an apparent bug
+** that makes the __attribute__ statements applied to the typdef's on
+** the 64-bit types below ineffective when those types are used in structures.
+** To workaround that bug, it may be required to add similar __attribute__
+** statements on the typedefs of the derived types SaHpiTimeT and
+** SaHpiTimeoutT, plus on individual 64-bit data items within structure and
+** union definitions in order to align the HPI structures as recommended.
+** The structures and unions that contain 64-bit data items are:
+** SaHpiSensorReadingUnionT, SaHpiSensorDataFormatT, SaHpiEventT,
+** SaHpiAnnouncementT, SaHpiDomainInfoT, SaHpiAlarmT, SaHpiEventLogInfoT,
+** and SaHpiEventLogEntryT. For more information, see:
+** https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=109911
+*/
+
+
+/* unsigned 8-bit data, 1-byte alignment */
+typedef unsigned char SaHpiUint8T;
+
+/* unsigned 16-bit data, 2-byte alignment */
+typedef unsigned short SaHpiUint16T;
+
+/* unsigned 32-bit data, 4-byte alignment */
+typedef unsigned int SaHpiUint32T;
+
+/* unsigned 64-bit data, 8-byte alignment */
+typedef unsigned long long int SaHpiUint64T __attribute__((__aligned__(8)));
+
+/* signed 8-bit data, 1-byte alignment */
+typedef signed char SaHpiInt8T;
+
+/* signed 16-bit data, 2-byte alignment */
+typedef signed short SaHpiInt16T;
+
+/* signed 32-bit data, 4-byte alignment */
+typedef signed int SaHpiInt32T;
+
+/* signed 64-bit data, 8-byte alignment */
+typedef signed long long int SaHpiInt64T __attribute__((__aligned__(8)));
+
+/* 64-bit floating point, 8-byte alignment */
+typedef double SaHpiFloat64T __attribute__((__aligned__(8)));
+
+
+typedef SaHpiUint8T SaHpiBoolT;
+#define SAHPI_TRUE 1 /* While SAHPI_TRUE = 1, any non-zero
+ value is also considered to be True
+ and HPI Users/Implementers of this
+ specification should not test for
+ equality against SAHPI_TRUE. */
+
+#define SAHPI_FALSE 0
+
+/* Platform, O/S, or Vendor dependent */
+#define SAHPI_API
+#define SAHPI_IN
+#define SAHPI_OUT
+#define SAHPI_INOUT
+
+/*
+** Identifier for the manufacturer
+**
+** This is the IANA-assigned private enterprise number for the
+** manufacturer of the resource or FRU, or of the manufacturer
+** defining an OEM control or event type. A list of current
+** IANA-assigned private enterprise numbers may be obtained at
+**
+** http://www.iana.org/assignments/enterprise-numbers
+**
+** If a manufacturer does not currently have an assigned number, one
+** may be obtained by following the instructions located at
+**
+** http://www.iana.org/cgi-bin/enterprise.pl
+*/
+typedef SaHpiUint32T SaHpiManufacturerIdT;
+#define SAHPI_MANUFACTURER_ID_UNSPECIFIED (SaHpiManufacturerIdT)0
+
+/* Version Types */
+typedef SaHpiUint32T SaHpiVersionT;
+
+/*
+** Interface Version
+**
+** The interface version is the version of the actual interface and not the
+** version of the implementation. It is a 24 bit value where
+** the most significant 8 bits represent the compatibility level
+** (with letters represented as the corresponding numbers);
+** the next 8 bits represent the major version number; and
+** the least significant 8 bits represent the minor version number.
+*/
+#define SAHPI_INTERFACE_VERSION (SaHpiVersionT)0x020101 /* B.01.01 */
+
+/*
+** Return Codes
+**
+** SaErrorT is defined in the HPI specification. In the future a
+** common SAF types definition may be created to contain this type. At
+** that time, this typedef should be removed. Each of the return codes
+** is defined in Section 4.1 of the specification.
+*/
+typedef SaHpiInt32T SaErrorT; /* Return code */
+
+/*
+** SA_OK:
+*/
+#define SA_OK (SaErrorT)0x0000
+
+/* This value is the base for all HPI-specific error codes. */
+#define SA_HPI_ERR_BASE -1000
+
+#define SA_ERR_HPI_ERROR (SaErrorT)(SA_HPI_ERR_BASE - 1)
+#define SA_ERR_HPI_UNSUPPORTED_API (SaErrorT)(SA_HPI_ERR_BASE - 2)
+#define SA_ERR_HPI_BUSY (SaErrorT)(SA_HPI_ERR_BASE - 3)
+#define SA_ERR_HPI_INTERNAL_ERROR (SaErrorT)(SA_HPI_ERR_BASE - 4)
+#define SA_ERR_HPI_INVALID_CMD (SaErrorT)(SA_HPI_ERR_BASE - 5)
+#define SA_ERR_HPI_TIMEOUT (SaErrorT)(SA_HPI_ERR_BASE - 6)
+#define SA_ERR_HPI_OUT_OF_SPACE (SaErrorT)(SA_HPI_ERR_BASE - 7)
+#define SA_ERR_HPI_OUT_OF_MEMORY (SaErrorT)(SA_HPI_ERR_BASE - 8)
+#define SA_ERR_HPI_INVALID_PARAMS (SaErrorT)(SA_HPI_ERR_BASE - 9)
+#define SA_ERR_HPI_INVALID_DATA (SaErrorT)(SA_HPI_ERR_BASE - 10)
+#define SA_ERR_HPI_NOT_PRESENT (SaErrorT)(SA_HPI_ERR_BASE - 11)
+#define SA_ERR_HPI_NO_RESPONSE (SaErrorT)(SA_HPI_ERR_BASE - 12)
+#define SA_ERR_HPI_DUPLICATE (SaErrorT)(SA_HPI_ERR_BASE - 13)
+#define SA_ERR_HPI_INVALID_SESSION (SaErrorT)(SA_HPI_ERR_BASE - 14)
+#define SA_ERR_HPI_INVALID_DOMAIN (SaErrorT)(SA_HPI_ERR_BASE - 15)
+#define SA_ERR_HPI_INVALID_RESOURCE (SaErrorT)(SA_HPI_ERR_BASE - 16)
+#define SA_ERR_HPI_INVALID_REQUEST (SaErrorT)(SA_HPI_ERR_BASE - 17)
+#define SA_ERR_HPI_ENTITY_NOT_PRESENT (SaErrorT)(SA_HPI_ERR_BASE - 18)
+#define SA_ERR_HPI_READ_ONLY (SaErrorT)(SA_HPI_ERR_BASE - 19)
+#define SA_ERR_HPI_CAPABILITY (SaErrorT)(SA_HPI_ERR_BASE - 20)
+#define SA_ERR_HPI_UNKNOWN (SaErrorT)(SA_HPI_ERR_BASE - 21)
+
+/*
+** Domain, Session and Resource Type Definitions
+*/
+
+/* Domain ID. */
+typedef SaHpiUint32T SaHpiDomainIdT;
+
+/* The SAHPI_UNSPECIFIED_DOMAIN_ID value is used to specify the default
+** domain.
+*/
+#define SAHPI_UNSPECIFIED_DOMAIN_ID (SaHpiDomainIdT) 0xFFFFFFFF
+
+/* Session ID. */
+typedef SaHpiUint32T SaHpiSessionIdT;
+
+/* Resource identifier. */
+typedef SaHpiUint32T SaHpiResourceIdT;
+
+/* The SAHPI_UNSPECIFIED_RESOURCE_ID value is used to specify the Domain
+** Event Log and to specify that there is no resource for such things as HPI
+** User events/alarms.
+*/
+#define SAHPI_UNSPECIFIED_RESOURCE_ID (SaHpiResourceIdT) 0xFFFFFFFF
+
+/* Table Related Type Definitions */
+typedef SaHpiUint32T SaHpiEntryIdT;
+#define SAHPI_FIRST_ENTRY (SaHpiEntryIdT)0x00000000
+#define SAHPI_LAST_ENTRY (SaHpiEntryIdT)0xFFFFFFFF
+#define SAHPI_ENTRY_UNSPECIFIED SAHPI_FIRST_ENTRY
+
+/*
+** Time Related Type Definitions
+**
+** An HPI time value represents the local time as the number of nanoseconds
+** from 00:00:00, January 1, 1970, in a 64-bit signed integer. This format
+** is sufficient to represent times with nano-second resolution from the
+** year 1678 to 2262. Every API which deals with time values must define
+** the timezone used.
+**
+** It should be noted that although nano-second resolution is supported
+** in the data type, the actual resolution provided by an implementation
+** may be more limited than this.
+**
+** The value -2**63, which is 0x8000000000000000, is used to indicate
+** "unknown/unspecified time".
+**
+** Conversion to/from POSIX and other common time representations is
+** relatively straightforward. The following code framgment converts
+** between SaHpiTimeT and time_t:
+**
+** time_t tt1, tt2;
+** SaHpiTimeT saHpiTime;
+**
+** time(&tt1);
+** saHpiTime = (SaHpiTimeT) tt1 * 1000000000;
+** tt2 = saHpiTime / 1000000000;
+**
+** The following fragment converts between SaHpiTimeT and a struct timeval:
+**
+** struct timeval tv1, tv2;
+** SaHpiTimeT saHpiTime;
+**
+** gettimeofday(&tv1, NULL);
+** saHpiTime = (SaHpiTimeT) tv1.tv_sec * 1000000000 + tv1.tv_usec * 1000;
+** tv2.tv_sec = saHpiTime / 1000000000;
+** tv2.tv_usec = saHpiTime % 1000000000 / 1000;
+**
+** The following fragment converts between SaHpiTimeT and a struct timespec:
+**
+** struct timespec ts1, ts2;
+** SaHpiTimeT saHpiTime;
+**
+** clock_gettime(CLOCK_REALTIME, &ts1);
+** saHpiTime = (SaHpiTimeT) ts1.tv_sec * 1000000000 + ts1.tv_nsec;
+** ts2.tv_sec = saHpiTime / 1000000000;
+** ts2.tv_nsec = saHpiTime % 1000000000;
+**
+** Note, however, that since time_t is (effectively) universally 32 bits,
+** all of these conversions will cease to work on January 18, 2038.
+**
+** Some subsystems may need the flexibility to report either absolute or
+** relative (eg. to system boot) times. This will typically be in the
+** case of a board which may or may not, depending on the system setup,
+** have an idea of absolute time. For example, some boards may have
+** "time of day" clocks which start at zero, and never get set to the
+** time of day.
+**
+** In these cases, times which represent "current" time (in events, for
+** example) can be reported based on the clock value, whether it has been
+** set to the actual date/time, or whether it represents the elapsed time
+** since boot. If it is the time since boot, the value will be (for 27
+** years) less than 0x0C00000000000000, which is Mon May 26 16:58:48 1997.
+** If the value is greater than this, then it can be assumed to be an
+** absolute time.
+**
+** There is no practical need within the interface for expressing dates prior
+** to the publication of this specification (which is more than five years
+** after the "break point" between relative and absolute time). Thus, in all
+** instances a time value should be interpreted as "relative" times if the
+** value is less than or equal to SAHPI_TIME_MAX_RELATIVE (but not equal to
+** SAHPI_TIME_UNSPECIFIED which always means the time is not available), or
+** "absolute" times if the value is greater than SAHPI_TIME_MAX_RELATIVE.
+*/
+typedef SaHpiInt64T SaHpiTimeT; /* Time in nanoseconds */
+
+/* Unspecified or unknown time */
+#define SAHPI_TIME_UNSPECIFIED (SaHpiTimeT) 0x8000000000000000LL
+
+/* Maximum time that can be specified as relative */
+#define SAHPI_TIME_MAX_RELATIVE (SaHpiTimeT) 0x0C00000000000000LL
+typedef SaHpiInt64T SaHpiTimeoutT; /* Timeout in nanoseconds */
+
+/* Non-blocking call */
+#define SAHPI_TIMEOUT_IMMEDIATE (SaHpiTimeoutT) 0x0000000000000000LL
+
+/* Blocking call, wait indefinitely for call to complete */
+#define SAHPI_TIMEOUT_BLOCK (SaHpiTimeoutT) -1LL
+
+/*
+** Language
+**
+** This enumeration lists all of the languages that can be associated with text.
+**
+** SAHPI_LANG_UNDEF indicates that the language is unspecified or
+** unknown.
+*/
+typedef enum {
+ SAHPI_LANG_UNDEF = 0, SAHPI_LANG_AFAR, SAHPI_LANG_ABKHAZIAN,
+ SAHPI_LANG_AFRIKAANS, SAHPI_LANG_AMHARIC, SAHPI_LANG_ARABIC,
+ SAHPI_LANG_ASSAMESE, SAHPI_LANG_AYMARA, SAHPI_LANG_AZERBAIJANI,
+ SAHPI_LANG_BASHKIR, SAHPI_LANG_BYELORUSSIAN, SAHPI_LANG_BULGARIAN,
+ SAHPI_LANG_BIHARI, SAHPI_LANG_BISLAMA, SAHPI_LANG_BENGALI,
+ SAHPI_LANG_TIBETAN, SAHPI_LANG_BRETON, SAHPI_LANG_CATALAN,
+ SAHPI_LANG_CORSICAN, SAHPI_LANG_CZECH, SAHPI_LANG_WELSH,
+ SAHPI_LANG_DANISH, SAHPI_LANG_GERMAN, SAHPI_LANG_BHUTANI,
+ SAHPI_LANG_GREEK, SAHPI_LANG_ENGLISH, SAHPI_LANG_ESPERANTO,
+ SAHPI_LANG_SPANISH, SAHPI_LANG_ESTONIAN, SAHPI_LANG_BASQUE,
+ SAHPI_LANG_PERSIAN, SAHPI_LANG_FINNISH, SAHPI_LANG_FIJI,
+ SAHPI_LANG_FAEROESE, SAHPI_LANG_FRENCH, SAHPI_LANG_FRISIAN,
+ SAHPI_LANG_IRISH, SAHPI_LANG_SCOTSGAELIC, SAHPI_LANG_GALICIAN,
+ SAHPI_LANG_GUARANI, SAHPI_LANG_GUJARATI, SAHPI_LANG_HAUSA,
+ SAHPI_LANG_HINDI, SAHPI_LANG_CROATIAN, SAHPI_LANG_HUNGARIAN,
+ SAHPI_LANG_ARMENIAN, SAHPI_LANG_INTERLINGUA, SAHPI_LANG_INTERLINGUE,
+ SAHPI_LANG_INUPIAK, SAHPI_LANG_INDONESIAN, SAHPI_LANG_ICELANDIC,
+ SAHPI_LANG_ITALIAN, SAHPI_LANG_HEBREW, SAHPI_LANG_JAPANESE,
+ SAHPI_LANG_YIDDISH, SAHPI_LANG_JAVANESE, SAHPI_LANG_GEORGIAN,
+ SAHPI_LANG_KAZAKH, SAHPI_LANG_GREENLANDIC, SAHPI_LANG_CAMBODIAN,
+ SAHPI_LANG_KANNADA, SAHPI_LANG_KOREAN, SAHPI_LANG_KASHMIRI,
+ SAHPI_LANG_KURDISH, SAHPI_LANG_KIRGHIZ, SAHPI_LANG_LATIN,
+ SAHPI_LANG_LINGALA, SAHPI_LANG_LAOTHIAN, SAHPI_LANG_LITHUANIAN,
+ SAHPI_LANG_LATVIANLETTISH, SAHPI_LANG_MALAGASY, SAHPI_LANG_MAORI,
+ SAHPI_LANG_MACEDONIAN, SAHPI_LANG_MALAYALAM, SAHPI_LANG_MONGOLIAN,
+ SAHPI_LANG_MOLDAVIAN, SAHPI_LANG_MARATHI, SAHPI_LANG_MALAY,
+ SAHPI_LANG_MALTESE, SAHPI_LANG_BURMESE, SAHPI_LANG_NAURU,
+ SAHPI_LANG_NEPALI, SAHPI_LANG_DUTCH, SAHPI_LANG_NORWEGIAN,
+ SAHPI_LANG_OCCITAN, SAHPI_LANG_AFANOROMO, SAHPI_LANG_ORIYA,
+ SAHPI_LANG_PUNJABI, SAHPI_LANG_POLISH, SAHPI_LANG_PASHTOPUSHTO,
+ SAHPI_LANG_PORTUGUESE, SAHPI_LANG_QUECHUA, SAHPI_LANG_RHAETOROMANCE,
+ SAHPI_LANG_KIRUNDI, SAHPI_LANG_ROMANIAN, SAHPI_LANG_RUSSIAN,
+ SAHPI_LANG_KINYARWANDA, SAHPI_LANG_SANSKRIT, SAHPI_LANG_SINDHI,
+ SAHPI_LANG_SANGRO, SAHPI_LANG_SERBOCROATIAN, SAHPI_LANG_SINGHALESE,
+ SAHPI_LANG_SLOVAK, SAHPI_LANG_SLOVENIAN, SAHPI_LANG_SAMOAN,
+ SAHPI_LANG_SHONA, SAHPI_LANG_SOMALI, SAHPI_LANG_ALBANIAN,
+ SAHPI_LANG_SERBIAN, SAHPI_LANG_SISWATI, SAHPI_LANG_SESOTHO,
+ SAHPI_LANG_SUDANESE, SAHPI_LANG_SWEDISH, SAHPI_LANG_SWAHILI,
+ SAHPI_LANG_TAMIL, SAHPI_LANG_TELUGU, SAHPI_LANG_TAJIK,
+ SAHPI_LANG_THAI, SAHPI_LANG_TIGRINYA, SAHPI_LANG_TURKMEN,
+ SAHPI_LANG_TAGALOG, SAHPI_LANG_SETSWANA, SAHPI_LANG_TONGA,
+ SAHPI_LANG_TURKISH, SAHPI_LANG_TSONGA, SAHPI_LANG_TATAR,
+ SAHPI_LANG_TWI, SAHPI_LANG_UKRAINIAN, SAHPI_LANG_URDU,
+ SAHPI_LANG_UZBEK, SAHPI_LANG_VIETNAMESE, SAHPI_LANG_VOLAPUK,
+ SAHPI_LANG_WOLOF, SAHPI_LANG_XHOSA, SAHPI_LANG_YORUBA,
+ SAHPI_LANG_CHINESE, SAHPI_LANG_ZULU
+} SaHpiLanguageT;
+
+/*
+** Text Buffers
+**
+** These structures are used for defining the type of data in the text buffer
+** and the length of the buffer. Text buffers are used in the inventory data,
+** RDR, RPT, etc. for variable length strings of data.
+**
+** The encoding of the Data field in the SaHpiTextBufferT structure is defined
+** by the value of the DataType field in the buffer. The following table
+** describes the various encodings:
+**
+** DataType Encoding
+** -------- --------
+**
+** SAHPI_TL_TYPE_UNICODE 16-bit Unicode, least significant byte first.
+** Buffer must contain even number of bytes.
+**
+** SAHPI_TL_TYPE_BCDPLUS 8-bit ASCII, '0'-'9' or space, dash, period,
+** colon, comma, or underscore only.
+**
+** SAHPI_TL_TYPE_ASCII6 8-bit ASCII, reduced set, 0x20=0x5f only.
+**
+** SAHPI_TL_TYPE_TEXT 8-bit ASCII+Latin 1
+**
+** SAHPI_TL_TYPE_BINARY 8-bit bytes, any values legal
+**
+** Note: "ASCII+Latin 1" is derived from the first 256 characters of
+** Unicode 2.0. The first 256 codes of Unicode follow ISO 646 (ASCII)
+** and ISO 8859/1 (Latin 1). The Unicode "C0 Controls and Basic Latin"
+** set defines the first 128 8-bit characters (00h-7Fh) and the
+** "C1 Controls and Latin 1 Supplement" defines the second 128 (80h-FFh).
+**
+** Note: The SAHPI_TL_TYPE_BCDPLUS and SAHPI_TL_TYPE_ASCII6 encodings
+** use normal ASCII character encodings, but restrict the allowed
+** characters to a subset of the entire ASCII character set. These
+** encodings are used when the target device contains restrictions
+** on which characters it can store or display. SAHPI_TL_TYPE_BCDPLUS
+** data may be stored externally as 4-bit values, and
+** SAHPI_TL_TYPE_ASCII6 may be stored externally as 6-bit values.
+** But, regardless of how the data is stored externally, it is
+** encoded as 8-bit ASCII in the SaHpiTextBufferT structure passed
+** across the HPI.
+*/
+
+#define SAHPI_MAX_TEXT_BUFFER_LENGTH 255
+
+typedef enum {
+ SAHPI_TL_TYPE_UNICODE = 0, /* 2-byte UNICODE characters; DataLength
+ must be even. */
+ SAHPI_TL_TYPE_BCDPLUS, /* String of ASCII characters, '0'-'9', space,
+ dash, period, colon, comma or underscore
+ ONLY */
+ SAHPI_TL_TYPE_ASCII6, /* Reduced ASCII character set: 0x20-0x5F
+ ONLY */
+ SAHPI_TL_TYPE_TEXT, /* ASCII+Latin 1 */
+ SAHPI_TL_TYPE_BINARY /* Binary data, any values legal */
+} SaHpiTextTypeT;
+
+typedef struct {
+ SaHpiTextTypeT DataType;
+ SaHpiLanguageT Language; /* Language the text is in. */
+ SaHpiUint8T DataLength; /* Bytes used in Data buffer */
+ SaHpiUint8T Data[SAHPI_MAX_TEXT_BUFFER_LENGTH]; /* Data buffer */
+} SaHpiTextBufferT;
+
+/*
+** Instrument Id
+**
+** The following data type is used for all management instrument identifiers -
+** sensor numbers, control numbers, watchdog timer numbers, etc.
+**
+*/
+
+typedef SaHpiUint32T SaHpiInstrumentIdT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Entities **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+/*
+** Entity Types
+**
+** Entities are used to associate specific hardware components with sensors,
+** controls, watchdogs, or resources. Entities are defined with an entity
+** type enumeration, and an entity location number (to identify
+** the physical location of a particular type of entity).
+**
+** Entities are uniquely identified in a system with an ordered series of
+** Entity Type / Entity Location pairs called an "Entity Path". Each subsequent
+** Entity Type/Entity Location in the path is the next higher "containing"
+** entity. The "root" of the Entity Path (the outermost level of containment)
+** is designated with an Entity Type of SAHPI_ENT_ROOT if the entire Entity Path
+** is fewer than SAHPI_MAX_ENTITY_PATH entries in length.
+**
+** Enumerated Entity Types include those types enumerated by the IPMI Consortium
+** for IPMI-managed entities, as well as additional types defined by the
+** HPI specification. Room is left in the enumeration for the inclusion of
+** Entity Types taken from other lists, if needed in the future.
+*/
+/* Base values for entity types from various sources. */
+#define SAHPI_ENT_IPMI_GROUP 0
+#define SAHPI_ENT_SAFHPI_GROUP 0x10000
+#define SAHPI_ENT_ROOT_VALUE 0xFFFF
+typedef enum
+{
+ SAHPI_ENT_UNSPECIFIED = SAHPI_ENT_IPMI_GROUP,
+ SAHPI_ENT_OTHER,
+ SAHPI_ENT_UNKNOWN,
+ SAHPI_ENT_PROCESSOR,
+ SAHPI_ENT_DISK_BAY, /* Disk or disk bay */
+ SAHPI_ENT_PERIPHERAL_BAY,
+ SAHPI_ENT_SYS_MGMNT_MODULE, /* System management module */
+ SAHPI_ENT_SYSTEM_BOARD, /* Main system board, may also be
+ processor board and/or internal
+ expansion board */
+ SAHPI_ENT_MEMORY_MODULE, /* Board holding memory devices */
+ SAHPI_ENT_PROCESSOR_MODULE, /* Holds processors, use this
+ designation when processors are not
+ mounted on system board */
+ SAHPI_ENT_POWER_SUPPLY, /* Main power supply (supplies) for the
+ system */
+ SAHPI_ENT_ADD_IN_CARD,
+ SAHPI_ENT_FRONT_PANEL_BOARD, /* Control panel */
+ SAHPI_ENT_BACK_PANEL_BOARD,
+ SAHPI_ENT_POWER_SYSTEM_BOARD,
+ SAHPI_ENT_DRIVE_BACKPLANE,
+ SAHPI_ENT_SYS_EXPANSION_BOARD, /* System internal expansion board
+ (contains expansion slots). */
+ SAHPI_ENT_OTHER_SYSTEM_BOARD, /* Part of board set */
+ SAHPI_ENT_PROCESSOR_BOARD, /* Holds 1 or more processors. Includes
+ boards that hold SECC modules) */
+ SAHPI_ENT_POWER_UNIT, /* Power unit / power domain (typically
+ used as a pre-defined logical entity
+ for grouping power supplies)*/
+ SAHPI_ENT_POWER_MODULE, /* Power module / DC-to-DC converter.
+ Use this value for internal
+ converters. Note: You should use
+ entity ID (power supply) for the
+ main power supply even if the main
+ supply is a DC-to-DC converter */
+ SAHPI_ENT_POWER_MGMNT, /* Power management/distribution
+ board */
+ SAHPI_ENT_CHASSIS_BACK_PANEL_BOARD,
+ SAHPI_ENT_SYSTEM_CHASSIS,
+ SAHPI_ENT_SUB_CHASSIS,
+ SAHPI_ENT_OTHER_CHASSIS_BOARD,
+ SAHPI_ENT_DISK_DRIVE_BAY,
+ SAHPI_ENT_PERIPHERAL_BAY_2,
+ SAHPI_ENT_DEVICE_BAY,
+ SAHPI_ENT_COOLING_DEVICE, /* Fan/cooling device */
+ SAHPI_ENT_COOLING_UNIT, /* Can be used as a pre-defined logical
+ entity for grouping fans or other
+ cooling devices. */
+ SAHPI_ENT_INTERCONNECT, /* Cable / interconnect */
+ SAHPI_ENT_MEMORY_DEVICE, /* This Entity ID should be used for
+ replaceable memory devices, e.g.
+ DIMM/SIMM. It is recommended that
+ Entity IDs not be used for
+ individual non-replaceable memory
+ devices. Rather, monitoring and
+ error reporting should be associated
+ with the FRU [e.g. memory card]
+ holding the memory. */
+ SAHPI_ENT_SYS_MGMNT_SOFTWARE, /* System Management Software */
+ SAHPI_ENT_BIOS,
+ SAHPI_ENT_OPERATING_SYSTEM,
+ SAHPI_ENT_SYSTEM_BUS,
+ SAHPI_ENT_GROUP, /* This is a logical entity for use with
+ Entity Association records. It is
+ provided to allow a sensor data
+ record to point to an entity-
+ association record when there is no
+ appropriate pre-defined logical
+ entity for the entity grouping.
+ This Entity should not be used as a
+ physical entity. */
+ SAHPI_ENT_REMOTE, /* Out of band management communication
+ device */
+ SAHPI_ENT_EXTERNAL_ENVIRONMENT,
+ SAHPI_ENT_BATTERY,
+ SAHPI_ENT_CHASSIS_SPECIFIC = SAHPI_ENT_IPMI_GROUP + 0x90,
+ SAHPI_ENT_BOARD_SET_SPECIFIC = SAHPI_ENT_IPMI_GROUP + 0xB0,
+ SAHPI_ENT_OEM_SYSINT_SPECIFIC = SAHPI_ENT_IPMI_GROUP + 0xD0,
+ SAHPI_ENT_ROOT = SAHPI_ENT_ROOT_VALUE,
+ SAHPI_ENT_RACK = SAHPI_ENT_SAFHPI_GROUP,
+ SAHPI_ENT_SUBRACK,
+ SAHPI_ENT_COMPACTPCI_CHASSIS,
+ SAHPI_ENT_ADVANCEDTCA_CHASSIS,
+ SAHPI_ENT_RACK_MOUNTED_SERVER,
+ SAHPI_ENT_SYSTEM_BLADE,
+ SAHPI_ENT_SWITCH, /* Network switch, such as a
+ rack-mounted ethernet or fabric
+ switch. */
+ SAHPI_ENT_SWITCH_BLADE, /* Network switch, as above, but in
+ a bladed system. */
+ SAHPI_ENT_SBC_BLADE,
+ SAHPI_ENT_IO_BLADE,
+ SAHPI_ENT_DISK_BLADE,
+ SAHPI_ENT_DISK_DRIVE,
+ SAHPI_ENT_FAN,
+ SAHPI_ENT_POWER_DISTRIBUTION_UNIT,
+ SAHPI_ENT_SPEC_PROC_BLADE, /* Special Processing Blade,
+ including DSP */
+ SAHPI_ENT_IO_SUBBOARD, /* I/O Sub-Board, including
+ PMC I/O board */
+ SAHPI_ENT_SBC_SUBBOARD, /* SBC Sub-Board, including PMC
+ SBC board */
+ SAHPI_ENT_ALARM_MANAGER, /* Chassis alarm manager board */
+ SAHPI_ENT_SHELF_MANAGER, /* Blade-based shelf manager */
+ SAHPI_ENT_DISPLAY_PANEL, /* Display panel, such as an
+ alarm display panel. */
+ SAHPI_ENT_SUBBOARD_CARRIER_BLADE, /* Includes PMC Carrier Blade --
+ Use only if "carrier" is only
+ function of blade. Else use
+ primary function (SBC_BLADE,
+ DSP_BLADE, etc.). */
+ SAHPI_ENT_PHYSICAL_SLOT /* Indicates the physical slot into
+ which a blade is inserted. */
+} SaHpiEntityTypeT;
+
+typedef SaHpiUint32T SaHpiEntityLocationT;
+
+typedef struct {
+ SaHpiEntityTypeT EntityType;
+ SaHpiEntityLocationT EntityLocation;
+} SaHpiEntityT;
+
+
+#define SAHPI_MAX_ENTITY_PATH 16
+
+typedef struct {
+ SaHpiEntityT Entry[SAHPI_MAX_ENTITY_PATH];
+} SaHpiEntityPathT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Events, part 1 **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+/*
+** Category
+**
+** Sensor events contain an event category and event state. Depending on the
+** event category, the event states take on different meanings for events
+** generated by specific sensors.
+**
+** It is recommended that implementations map their sensor specific
+** event categories into the set of categories listed here. When such a mapping
+** is impractical or impossible, the SAHPI_EC_SENSOR_SPECIFIC category should
+** be used.
+**
+** The SAHPI_EC_GENERIC category can be used for discrete sensors which have
+** state meanings other than those identified with other event categories.
+*/
+typedef SaHpiUint8T SaHpiEventCategoryT;
+
+#define SAHPI_EC_UNSPECIFIED (SaHpiEventCategoryT)0x00 /* Unspecified */
+#define SAHPI_EC_THRESHOLD (SaHpiEventCategoryT)0x01 /* Threshold
+ events */
+#define SAHPI_EC_USAGE (SaHpiEventCategoryT)0x02 /* Usage state
+ events */
+#define SAHPI_EC_STATE (SaHpiEventCategoryT)0x03 /* Generic state
+ events */
+#define SAHPI_EC_PRED_FAIL (SaHpiEventCategoryT)0x04 /* Predictive fail
+ events */
+#define SAHPI_EC_LIMIT (SaHpiEventCategoryT)0x05 /* Limit events */
+#define SAHPI_EC_PERFORMANCE (SaHpiEventCategoryT)0x06 /* Performance
+ events */
+#define SAHPI_EC_SEVERITY (SaHpiEventCategoryT)0x07 /* Severity
+ indicating
+ events */
+#define SAHPI_EC_PRESENCE (SaHpiEventCategoryT)0x08 /* Device presence
+ events */
+#define SAHPI_EC_ENABLE (SaHpiEventCategoryT)0x09 /* Device enabled
+ events */
+#define SAHPI_EC_AVAILABILITY (SaHpiEventCategoryT)0x0A /* Availability
+ state events */
+#define SAHPI_EC_REDUNDANCY (SaHpiEventCategoryT)0x0B /* Redundancy
+ state events */
+#define SAHPI_EC_SENSOR_SPECIFIC (SaHpiEventCategoryT)0x7E /* Sensor-
+ specific events */
+#define SAHPI_EC_GENERIC (SaHpiEventCategoryT)0x7F /* OEM defined
+ events */
+
+/*
+** Event States
+**
+** The following event states are specified relative to the categories listed
+** above. The event types are only valid for their given category. Each set of
+** events is labeled as to which category it belongs to.
+** Each event will have only one event state associated with it. When retrieving
+** the event status or event enabled status a bit mask of all applicable event
+** states is used. Similarly, when setting the event enabled status a bit mask
+** of all applicable event states is used.
+*/
+typedef SaHpiUint16T SaHpiEventStateT;
+
+/*
+** SaHpiEventCategoryT == <any>
+*/
+#define SAHPI_ES_UNSPECIFIED (SaHpiEventStateT)0x0000
+
+/*
+** SaHpiEventCategoryT == SAHPI_EC_THRESHOLD
+** When using these event states, the event state should match
+** the event severity (for example SAHPI_ES_LOWER_MINOR should have an
+** event severity of SAHPI_MINOR).
+*/
+#define SAHPI_ES_LOWER_MINOR (SaHpiEventStateT)0x0001
+#define SAHPI_ES_LOWER_MAJOR (SaHpiEventStateT)0x0002
+#define SAHPI_ES_LOWER_CRIT (SaHpiEventStateT)0x0004
+#define SAHPI_ES_UPPER_MINOR (SaHpiEventStateT)0x0008
+#define SAHPI_ES_UPPER_MAJOR (SaHpiEventStateT)0x0010
+#define SAHPI_ES_UPPER_CRIT (SaHpiEventStateT)0x0020
+
+/* SaHpiEventCategoryT == SAHPI_EC_USAGE */
+#define SAHPI_ES_IDLE (SaHpiEventStateT)0x0001
+#define SAHPI_ES_ACTIVE (SaHpiEventStateT)0x0002
+#define SAHPI_ES_BUSY (SaHpiEventStateT)0x0004
+
+/* SaHpiEventCategoryT == SAHPI_EC_STATE */
+#define SAHPI_ES_STATE_DEASSERTED (SaHpiEventStateT)0x0001
+#define SAHPI_ES_STATE_ASSERTED (SaHpiEventStateT)0x0002
+
+/* SaHpiEventCategoryT == SAHPI_EC_PRED_FAIL */
+#define SAHPI_ES_PRED_FAILURE_DEASSERT (SaHpiEventStateT)0x0001
+#define SAHPI_ES_PRED_FAILURE_ASSERT (SaHpiEventStateT)0x0002
+
+/* SaHpiEventCategoryT == SAHPI_EC_LIMIT */
+#define SAHPI_ES_LIMIT_NOT_EXCEEDED (SaHpiEventStateT)0x0001
+#define SAHPI_ES_LIMIT_EXCEEDED (SaHpiEventStateT)0x0002
+
+/* SaHpiEventCategoryT == SAHPI_EC_PERFORMANCE */
+#define SAHPI_ES_PERFORMANCE_MET (SaHpiEventStateT)0x0001
+#define SAHPI_ES_PERFORMANCE_LAGS (SaHpiEventStateT)0x0002
+
+/*
+** SaHpiEventCategoryT == SAHPI_EC_SEVERITY
+** When using these event states, the event state should match
+** the event severity
+*/
+#define SAHPI_ES_OK (SaHpiEventStateT)0x0001
+#define SAHPI_ES_MINOR_FROM_OK (SaHpiEventStateT)0x0002
+#define SAHPI_ES_MAJOR_FROM_LESS (SaHpiEventStateT)0x0004
+#define SAHPI_ES_CRITICAL_FROM_LESS (SaHpiEventStateT)0x0008
+#define SAHPI_ES_MINOR_FROM_MORE (SaHpiEventStateT)0x0010
+#define SAHPI_ES_MAJOR_FROM_CRITICAL (SaHpiEventStateT)0x0020
+#define SAHPI_ES_CRITICAL (SaHpiEventStateT)0x0040
+#define SAHPI_ES_MONITOR (SaHpiEventStateT)0x0080
+#define SAHPI_ES_INFORMATIONAL (SaHpiEventStateT)0x0100
+
+/* SaHpiEventCategoryT == SAHPI_EC_PRESENCE */
+#define SAHPI_ES_ABSENT (SaHpiEventStateT)0x0001
+#define SAHPI_ES_PRESENT (SaHpiEventStateT)0x0002
+
+/* SaHpiEventCategoryT == SAHPI_EC_ENABLE */
+#define SAHPI_ES_DISABLED (SaHpiEventStateT)0x0001
+#define SAHPI_ES_ENABLED (SaHpiEventStateT)0x0002
+
+/* SaHpiEventCategoryT == SAHPI_EC_AVAILABILITY */
+#define SAHPI_ES_RUNNING (SaHpiEventStateT)0x0001
+#define SAHPI_ES_TEST (SaHpiEventStateT)0x0002
+#define SAHPI_ES_POWER_OFF (SaHpiEventStateT)0x0004
+#define SAHPI_ES_ON_LINE (SaHpiEventStateT)0x0008
+#define SAHPI_ES_OFF_LINE (SaHpiEventStateT)0x0010
+#define SAHPI_ES_OFF_DUTY (SaHpiEventStateT)0x0020
+#define SAHPI_ES_DEGRADED (SaHpiEventStateT)0x0040
+#define SAHPI_ES_POWER_SAVE (SaHpiEventStateT)0x0080
+#define SAHPI_ES_INSTALL_ERROR (SaHpiEventStateT)0x0100
+
+/* SaHpiEventCategoryT == SAHPI_EC_REDUNDANCY */
+#define SAHPI_ES_FULLY_REDUNDANT (SaHpiEventStateT)0x0001
+#define SAHPI_ES_REDUNDANCY_LOST (SaHpiEventStateT)0x0002
+#define SAHPI_ES_REDUNDANCY_DEGRADED (SaHpiEventStateT)0x0004
+#define SAHPI_ES_REDUNDANCY_LOST_SUFFICIENT_RESOURCES \
+ (SaHpiEventStateT)0x0008
+#define SAHPI_ES_NON_REDUNDANT_SUFFICIENT_RESOURCES \
+ (SaHpiEventStateT)0x0010
+#define SAHPI_ES_NON_REDUNDANT_INSUFFICIENT_RESOURCES \
+ (SaHpiEventStateT)0x0020
+#define SAHPI_ES_REDUNDANCY_DEGRADED_FROM_FULL (SaHpiEventStateT)0x0040
+#define SAHPI_ES_REDUNDANCY_DEGRADED_FROM_NON (SaHpiEventStateT)0x0080
+
+/*
+** SaHpiEventCategoryT == SAHPI_EC_GENERIC || SAHPI_EC_SENSOR_SPECIFIC
+** These event states are implementation-specific.
+*/
+#define SAHPI_ES_STATE_00 (SaHpiEventStateT)0x0001
+#define SAHPI_ES_STATE_01 (SaHpiEventStateT)0x0002
+#define SAHPI_ES_STATE_02 (SaHpiEventStateT)0x0004
+#define SAHPI_ES_STATE_03 (SaHpiEventStateT)0x0008
+#define SAHPI_ES_STATE_04 (SaHpiEventStateT)0x0010
+#define SAHPI_ES_STATE_05 (SaHpiEventStateT)0x0020
+#define SAHPI_ES_STATE_06 (SaHpiEventStateT)0x0040
+#define SAHPI_ES_STATE_07 (SaHpiEventStateT)0x0080
+#define SAHPI_ES_STATE_08 (SaHpiEventStateT)0x0100
+#define SAHPI_ES_STATE_09 (SaHpiEventStateT)0x0200
+#define SAHPI_ES_STATE_10 (SaHpiEventStateT)0x0400
+#define SAHPI_ES_STATE_11 (SaHpiEventStateT)0x0800
+#define SAHPI_ES_STATE_12 (SaHpiEventStateT)0x1000
+#define SAHPI_ES_STATE_13 (SaHpiEventStateT)0x2000
+#define SAHPI_ES_STATE_14 (SaHpiEventStateT)0x4000
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Sensors **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* Sensor Number */
+typedef SaHpiInstrumentIdT SaHpiSensorNumT;
+/* The following specifies the named range for standard sensor numbers. */
+#define SAHPI_STANDARD_SENSOR_MIN (SaHpiSensorNumT)0x00000100
+#define SAHPI_STANDARD_SENSOR_MAX (SaHpiSensorNumT)0x000001FF
+
+/* Type of Sensor */
+typedef enum {
+ SAHPI_TEMPERATURE = 0x01,
+ SAHPI_VOLTAGE,
+ SAHPI_CURRENT,
+ SAHPI_FAN,
+ SAHPI_PHYSICAL_SECURITY,
+ SAHPI_PLATFORM_VIOLATION,
+ SAHPI_PROCESSOR,
+ SAHPI_POWER_SUPPLY,
+ SAHPI_POWER_UNIT,
+ SAHPI_COOLING_DEVICE,
+ SAHPI_OTHER_UNITS_BASED_SENSOR,
+ SAHPI_MEMORY,
+ SAHPI_DRIVE_SLOT,
+ SAHPI_POST_MEMORY_RESIZE,
+ SAHPI_SYSTEM_FW_PROGRESS,
+ SAHPI_EVENT_LOGGING_DISABLED,
+ SAHPI_RESERVED1,
+ SAHPI_SYSTEM_EVENT,
+ SAHPI_CRITICAL_INTERRUPT,
+ SAHPI_BUTTON,
+ SAHPI_MODULE_BOARD,
+ SAHPI_MICROCONTROLLER_COPROCESSOR,
+ SAHPI_ADDIN_CARD,
+ SAHPI_CHASSIS,
+ SAHPI_CHIP_SET,
+ SAHPI_OTHER_FRU,
+ SAHPI_CABLE_INTERCONNECT,
+ SAHPI_TERMINATOR,
+ SAHPI_SYSTEM_BOOT_INITIATED,
+ SAHPI_BOOT_ERROR,
+ SAHPI_OS_BOOT,
+ SAHPI_OS_CRITICAL_STOP,
+ SAHPI_SLOT_CONNECTOR,
+ SAHPI_SYSTEM_ACPI_POWER_STATE,
+ SAHPI_RESERVED2,
+ SAHPI_PLATFORM_ALERT,
+ SAHPI_ENTITY_PRESENCE,
+ SAHPI_MONITOR_ASIC_IC,
+ SAHPI_LAN,
+ SAHPI_MANAGEMENT_SUBSYSTEM_HEALTH,
+ SAHPI_BATTERY,
+ SAHPI_OPERATIONAL = 0xA0,
+ SAHPI_OEM_SENSOR=0xC0
+} SaHpiSensorTypeT;
+
+/*
+** Sensor Reading Type
+**
+** These definitions list the available data types that can be
+** used for sensor readings.
+**
+*/
+
+#define SAHPI_SENSOR_BUFFER_LENGTH 32
+
+typedef enum {
+ SAHPI_SENSOR_READING_TYPE_INT64,
+ SAHPI_SENSOR_READING_TYPE_UINT64,
+ SAHPI_SENSOR_READING_TYPE_FLOAT64,
+ SAHPI_SENSOR_READING_TYPE_BUFFER /* 32 byte array. The format of
+ the buffer is implementation-
+ specific. Sensors that use
+ this reading type may not have
+ thresholds that are settable
+ or readable. */
+} SaHpiSensorReadingTypeT;
+
+typedef union {
+ SaHpiInt64T SensorInt64;
+ SaHpiUint64T SensorUint64;
+ SaHpiFloat64T SensorFloat64;
+ SaHpiUint8T SensorBuffer[SAHPI_SENSOR_BUFFER_LENGTH];
+} SaHpiSensorReadingUnionT;
+
+/*
+** Sensor Reading
+**
+** The sensor reading data structure is returned from a call to get
+** sensor reading. The structure is also used when setting and getting sensor
+** threshold values and reporting sensor ranges.
+**
+** IsSupported is set when a sensor reading/threshold value is available.
+** Otherwise, if no reading or threshold is supported, this flag is set to
+** False.
+**
+*/
+
+typedef struct {
+ SaHpiBoolT IsSupported;
+ SaHpiSensorReadingTypeT Type;
+ SaHpiSensorReadingUnionT Value;
+} SaHpiSensorReadingT;
+
+
+/* Sensor Event Mask Actions - used with saHpiSensorEventMasksSet() */
+
+typedef enum {
+ SAHPI_SENS_ADD_EVENTS_TO_MASKS,
+ SAHPI_SENS_REMOVE_EVENTS_FROM_MASKS
+} SaHpiSensorEventMaskActionT;
+
+/* Value to use for AssertEvents or DeassertEvents parameter
+ in saHpiSensorEventMasksSet() to set or clear all supported
+ event states for a sensor in the mask */
+
+#define SAHPI_ALL_EVENT_STATES (SaHpiEventStateT)0xFFFF
+
+/*
+** Threshold Values
+** This structure encompasses all of the thresholds that can be set.
+** These are set and read with the same units as sensors report in
+** saHpiSensorReadingGet(). When hysteresis is not constant over the
+** range of sensor values, it is calculated at the nominal sensor reading,
+** as given in the Range field of the sensor RDR.
+**
+** Thresholds are required to be set in-order (such that the setting for
+** UpCritical is greater than or equal to the setting for UpMajor, etc.).*/
+
+typedef struct {
+ SaHpiSensorReadingT LowCritical; /* Lower Critical Threshold */
+ SaHpiSensorReadingT LowMajor; /* Lower Major Threshold */
+ SaHpiSensorReadingT LowMinor; /* Lower Minor Threshold */
+ SaHpiSensorReadingT UpCritical; /* Upper critical Threshold */
+ SaHpiSensorReadingT UpMajor; /* Upper major Threshold */
+ SaHpiSensorReadingT UpMinor; /* Upper minor Threshold */
+ SaHpiSensorReadingT PosThdHysteresis; /* Positive Threshold Hysteresis */
+ SaHpiSensorReadingT NegThdHysteresis; /* Negative Threshold Hysteresis */
+}SaHpiSensorThresholdsT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Sensor Resource Data Records **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** Sensor Range
+** Sensor range values can include minimum, maximum, normal minimum, normal
+** maximum, and nominal values.
+**
+** Sensor thresholds cannot be set outside of the range defined by SAHPI_SRF_MIN
+** through SAHPI_SRF_MAX, if these limits are present (as indicated by the
+** SaHpiSensorRangeFlagsT). If the MIN limit is not present, no lower bound
+** will be enforced on sensor thresholds. If the MAX limit is not present, no
+** upper bound will be enforced on sensor thresholds.
+*/
+typedef SaHpiUint8T SaHpiSensorRangeFlagsT;
+#define SAHPI_SRF_MIN (SaHpiSensorRangeFlagsT)0x10
+#define SAHPI_SRF_MAX (SaHpiSensorRangeFlagsT)0x08
+#define SAHPI_SRF_NORMAL_MIN (SaHpiSensorRangeFlagsT)0x04
+#define SAHPI_SRF_NORMAL_MAX (SaHpiSensorRangeFlagsT)0x02
+#define SAHPI_SRF_NOMINAL (SaHpiSensorRangeFlagsT)0x01
+
+typedef struct {
+ SaHpiSensorRangeFlagsT Flags;
+ SaHpiSensorReadingT Max;
+ SaHpiSensorReadingT Min;
+ SaHpiSensorReadingT Nominal;
+ SaHpiSensorReadingT NormalMax;
+ SaHpiSensorReadingT NormalMin;
+} SaHpiSensorRangeT;
+
+/*
+** Sensor Units
+** This is a list of all the sensor units supported by HPI.
+*/
+typedef enum {
+ SAHPI_SU_UNSPECIFIED = 0, SAHPI_SU_DEGREES_C, SAHPI_SU_DEGREES_F,
+ SAHPI_SU_DEGREES_K, SAHPI_SU_VOLTS, SAHPI_SU_AMPS,
+ SAHPI_SU_WATTS, SAHPI_SU_JOULES, SAHPI_SU_COULOMBS,
+ SAHPI_SU_VA, SAHPI_SU_NITS, SAHPI_SU_LUMEN,
+ SAHPI_SU_LUX, SAHPI_SU_CANDELA, SAHPI_SU_KPA,
+ SAHPI_SU_PSI, SAHPI_SU_NEWTON, SAHPI_SU_CFM,
+ SAHPI_SU_RPM, SAHPI_SU_HZ, SAHPI_SU_MICROSECOND,
+ SAHPI_SU_MILLISECOND, SAHPI_SU_SECOND, SAHPI_SU_MINUTE,
+ SAHPI_SU_HOUR, SAHPI_SU_DAY, SAHPI_SU_WEEK,
+ SAHPI_SU_MIL, SAHPI_SU_INCHES, SAHPI_SU_FEET,
+ SAHPI_SU_CU_IN, SAHPI_SU_CU_FEET, SAHPI_SU_MM,
+ SAHPI_SU_CM, SAHPI_SU_M, SAHPI_SU_CU_CM,
+ SAHPI_SU_CU_M, SAHPI_SU_LITERS, SAHPI_SU_FLUID_OUNCE,
+ SAHPI_SU_RADIANS, SAHPI_SU_STERADIANS, SAHPI_SU_REVOLUTIONS,
+ SAHPI_SU_CYCLES, SAHPI_SU_GRAVITIES, SAHPI_SU_OUNCE,
+ SAHPI_SU_POUND, SAHPI_SU_FT_LB, SAHPI_SU_OZ_IN,
+ SAHPI_SU_GAUSS, SAHPI_SU_GILBERTS, SAHPI_SU_HENRY,
+ SAHPI_SU_MILLIHENRY, SAHPI_SU_FARAD, SAHPI_SU_MICROFARAD,
+ SAHPI_SU_OHMS, SAHPI_SU_SIEMENS, SAHPI_SU_MOLE,
+ SAHPI_SU_BECQUEREL, SAHPI_SU_PPM, SAHPI_SU_RESERVED,
+ SAHPI_SU_DECIBELS, SAHPI_SU_DBA, SAHPI_SU_DBC,
+ SAHPI_SU_GRAY, SAHPI_SU_SIEVERT, SAHPI_SU_COLOR_TEMP_DEG_K,
+ SAHPI_SU_BIT, SAHPI_SU_KILOBIT, SAHPI_SU_MEGABIT,
+ SAHPI_SU_GIGABIT, SAHPI_SU_BYTE, SAHPI_SU_KILOBYTE,
+ SAHPI_SU_MEGABYTE, SAHPI_SU_GIGABYTE, SAHPI_SU_WORD,
+ SAHPI_SU_DWORD, SAHPI_SU_QWORD, SAHPI_SU_LINE,
+ SAHPI_SU_HIT, SAHPI_SU_MISS, SAHPI_SU_RETRY,
+ SAHPI_SU_RESET, SAHPI_SU_OVERRUN, SAHPI_SU_UNDERRUN,
+ SAHPI_SU_COLLISION, SAHPI_SU_PACKETS, SAHPI_SU_MESSAGES,
+ SAHPI_SU_CHARACTERS, SAHPI_SU_ERRORS, SAHPI_SU_CORRECTABLE_ERRORS,
+ SAHPI_SU_UNCORRECTABLE_ERRORS
+} SaHpiSensorUnitsT;
+
+/*
+** Modifier Unit Use
+** This type defines how the modifier unit is used. For example: base unit ==
+** meter, modifier unit == seconds, and modifier unit use ==
+** SAHPI_SMUU_BASIC_OVER_MODIFIER. The resulting unit would be meters per
+** second.
+*/
+typedef enum {
+ SAHPI_SMUU_NONE = 0,
+ SAHPI_SMUU_BASIC_OVER_MODIFIER, /* Basic Unit / Modifier Unit */
+ SAHPI_SMUU_BASIC_TIMES_MODIFIER /* Basic Unit * Modifier Unit */
+} SaHpiSensorModUnitUseT;
+
+/*
+** Data Format
+** When IsSupported is False, the sensor does not support data readings
+** (it only supports event states). A False setting for this flag
+** indicates that the rest of the structure is not meaningful.
+**
+** This structure encapsulates all of the various types that make up the
+** definition of sensor data. For reading type of
+** SAHPI_SENSOR_READING_TYPE_BUFFER, the rest of the structure
+** (beyond ReadingType) is not meaningful.
+**
+** The Accuracy Factor is expressed as a floating point percentage
+** (e.g. 0.05 = 5%) and represents statistically how close the measured
+** reading is to the actual value. It is an interpreted value that
+** figures in all sensor accuracies, resolutions, and tolerances.
+*/
+
+typedef struct {
+ SaHpiBoolT IsSupported; /* Indicates if sensor data
+ readings are supported.*/
+ SaHpiSensorReadingTypeT ReadingType; /* Type of value for sensor
+ reading. */
+ SaHpiSensorUnitsT BaseUnits; /* Base units (meters, etc.) */
+ SaHpiSensorUnitsT ModifierUnits; /* Modifier unit (second, etc.)*/
+ SaHpiSensorModUnitUseT ModifierUse; /* Modifier use(m/sec, etc.) */
+ SaHpiBoolT Percentage; /* Is value a percentage */
+ SaHpiSensorRangeT Range; /* Valid range of sensor */
+ SaHpiFloat64T AccuracyFactor; /* Accuracy */
+} SaHpiSensorDataFormatT;
+
+/*
+** Threshold Support
+**
+** These types define what threshold values are readable and writable.
+** Thresholds are read/written in the same ReadingType as is used for sensor
+** readings.
+*/
+typedef SaHpiUint8T SaHpiSensorThdMaskT;
+#define SAHPI_STM_LOW_MINOR (SaHpiSensorThdMaskT)0x01
+#define SAHPI_STM_LOW_MAJOR (SaHpiSensorThdMaskT)0x02
+#define SAHPI_STM_LOW_CRIT (SaHpiSensorThdMaskT)0x04
+#define SAHPI_STM_UP_MINOR (SaHpiSensorThdMaskT)0x08
+#define SAHPI_STM_UP_MAJOR (SaHpiSensorThdMaskT)0x10
+#define SAHPI_STM_UP_CRIT (SaHpiSensorThdMaskT)0x20
+#define SAHPI_STM_UP_HYSTERESIS (SaHpiSensorThdMaskT)0x40
+#define SAHPI_STM_LOW_HYSTERESIS (SaHpiSensorThdMaskT)0x80
+
+typedef struct {
+ SaHpiBoolT IsAccessible; /* True if the sensor
+ supports readable or writable
+ thresholds. If False,
+ rest of structure is not
+ meaningful. Sensors that have the
+ IsAccessible flag set must also
+ support the threshold event category
+ A sensor of reading type SAHPI_
+ SENSOR_READING_TYPE_BUFFER cannot
+ have accessible thresholds.*/
+ SaHpiSensorThdMaskT ReadThold; /* Readable thresholds */
+ SaHpiSensorThdMaskT WriteThold; /* Writable thresholds */
+ SaHpiBoolT Nonlinear; /* If this flag is set, hysteresis
+ values are calculated at the nominal
+ sensor value. */
+} SaHpiSensorThdDefnT;
+
+/*
+** Event Control
+**
+** This type defines how sensor event messages can be controlled (can be turned
+** off and on for each type of event, etc.).
+*/
+typedef enum {
+ SAHPI_SEC_PER_EVENT = 0, /* Event message control per event,
+ or by entire sensor; sensor event enable
+ status can be changed, and assert/deassert
+ masks can be changed */
+ SAHPI_SEC_READ_ONLY_MASKS, /* Control for entire sensor only; sensor
+ event enable status can be changed, but
+ assert/deassert masks cannot be changed */
+ SAHPI_SEC_READ_ONLY /* Event control not supported; sensor event
+ enable status cannot be changed and
+ assert/deassert masks cannot be changed */
+} SaHpiSensorEventCtrlT;
+
+/*
+** Record
+**
+** This is the sensor resource data record which describes all of the static
+** data associated with a sensor.
+*/
+typedef struct {
+ SaHpiSensorNumT Num; /* Sensor Number/Index */
+ SaHpiSensorTypeT Type; /* General Sensor Type */
+ SaHpiEventCategoryT Category; /* Event category */
+ SaHpiBoolT EnableCtrl; /* True if HPI User can enable
+ or disable sensor via
+ saHpiSensorEnableSet() */
+ SaHpiSensorEventCtrlT EventCtrl; /* How events can be controlled */
+ SaHpiEventStateT Events; /* Bit mask of event states
+ supported */
+ SaHpiSensorDataFormatT DataFormat; /* Format of the data */
+ SaHpiSensorThdDefnT ThresholdDefn; /* Threshold Definition */
+ SaHpiUint32T Oem; /* Reserved for OEM use */
+} SaHpiSensorRecT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Aggregate Status **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* These are the default sensor numbers for aggregate status. */
+#define SAHPI_DEFAGSENS_OPER (SaHpiSensorNumT)0x00000100
+#define SAHPI_DEFAGSENS_PWR (SaHpiSensorNumT)0x00000101
+#define SAHPI_DEFAGSENS_TEMP (SaHpiSensorNumT)0x00000102
+
+/* The following specifies the named range for aggregate status. */
+#define SAHPI_DEFAGSENS_MIN (SaHpiSensorNumT)0x00000100
+#define SAHPI_DEFAGSENS_MAX (SaHpiSensorNumT)0x0000010F
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Controls **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* Control Number */
+typedef SaHpiInstrumentIdT SaHpiCtrlNumT;
+
+/*
+** Type of Control
+**
+** This enumerated type defines the different types of generic controls.
+*/
+typedef enum {
+ SAHPI_CTRL_TYPE_DIGITAL = 0x00,
+ SAHPI_CTRL_TYPE_DISCRETE,
+ SAHPI_CTRL_TYPE_ANALOG,
+ SAHPI_CTRL_TYPE_STREAM,
+ SAHPI_CTRL_TYPE_TEXT,
+ SAHPI_CTRL_TYPE_OEM = 0xC0
+} SaHpiCtrlTypeT;
+
+/*
+** Control State Type Definitions
+*/
+
+/*
+** Digital Control State Definition
+**
+** Defines the types of digital control states.
+** Any of the four states may be set using saHpiControlSet().
+** Only ON or OFF are appropriate returns from saHpiControlGet().
+** (PULSE_ON and PULSE_OFF are transitory and end in OFF and ON states,
+** respectively.)
+** OFF - the control is off
+** ON - the control is on
+** PULSE_OFF - the control is briefly turned off, and then turned back on
+** PULSE_ON - the control is briefly turned on, and then turned back off
+**
+*/
+typedef enum {
+ SAHPI_CTRL_STATE_OFF = 0,
+ SAHPI_CTRL_STATE_ON,
+ SAHPI_CTRL_STATE_PULSE_OFF,
+ SAHPI_CTRL_STATE_PULSE_ON
+} SaHpiCtrlStateDigitalT;
+
+/*
+** Discrete Control State Definition
+*/
+typedef SaHpiUint32T SaHpiCtrlStateDiscreteT;
+
+/*
+** Analog Control State Definition
+*/
+typedef SaHpiInt32T SaHpiCtrlStateAnalogT;
+
+/*
+** Stream Control State Definition
+*/
+#define SAHPI_CTRL_MAX_STREAM_LENGTH 4
+typedef struct {
+ SaHpiBoolT Repeat; /* Repeat flag */
+ SaHpiUint32T StreamLength; /* Length of the data, in bytes,
+ stored in the stream. */
+ SaHpiUint8T Stream[SAHPI_CTRL_MAX_STREAM_LENGTH];
+} SaHpiCtrlStateStreamT;
+
+/*
+** Text Control State Definition
+*/
+typedef SaHpiUint8T SaHpiTxtLineNumT;
+
+/* Reserved number for sending output to all lines */
+#define SAHPI_TLN_ALL_LINES (SaHpiTxtLineNumT)0x00
+
+typedef struct {
+ SaHpiTxtLineNumT Line; /* Operate on line # */
+ SaHpiTextBufferT Text; /* Text to display */
+} SaHpiCtrlStateTextT;
+
+/*
+** OEM Control State Definition
+*/
+#define SAHPI_CTRL_MAX_OEM_BODY_LENGTH 255
+typedef struct {
+ SaHpiManufacturerIdT MId;
+ SaHpiUint8T BodyLength;
+ SaHpiUint8T Body[SAHPI_CTRL_MAX_OEM_BODY_LENGTH]; /* OEM Specific */
+} SaHpiCtrlStateOemT;
+
+typedef union {
+ SaHpiCtrlStateDigitalT Digital;
+ SaHpiCtrlStateDiscreteT Discrete;
+ SaHpiCtrlStateAnalogT Analog;
+ SaHpiCtrlStateStreamT Stream;
+ SaHpiCtrlStateTextT Text;
+ SaHpiCtrlStateOemT Oem;
+} SaHpiCtrlStateUnionT;
+
+typedef struct {
+ SaHpiCtrlTypeT Type; /* Type of control */
+ SaHpiCtrlStateUnionT StateUnion; /* Data for control type */
+} SaHpiCtrlStateT;
+/*
+** Control Mode Type Definition
+**
+** Controls may be in either AUTO mode or MANUAL mode.
+**
+*/
+typedef enum {
+ SAHPI_CTRL_MODE_AUTO,
+ SAHPI_CTRL_MODE_MANUAL
+} SaHpiCtrlModeT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Control Resource Data Records **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** Output Type
+**
+** This enumeration defines the what the control's output will be.
+*/
+typedef enum {
+ SAHPI_CTRL_GENERIC = 0,
+ SAHPI_CTRL_LED,
+ SAHPI_CTRL_FAN_SPEED,
+ SAHPI_CTRL_DRY_CONTACT_CLOSURE,
+ SAHPI_CTRL_POWER_SUPPLY_INHIBIT,
+ SAHPI_CTRL_AUDIBLE,
+ SAHPI_CTRL_FRONT_PANEL_LOCKOUT,
+ SAHPI_CTRL_POWER_INTERLOCK,
+ SAHPI_CTRL_POWER_STATE,
+ SAHPI_CTRL_LCD_DISPLAY,
+ SAHPI_CTRL_OEM
+} SaHpiCtrlOutputTypeT;
+
+/*
+** Specific Record Types
+** These types represent the specific types of control resource data records.
+*/
+typedef struct {
+ SaHpiCtrlStateDigitalT Default;
+} SaHpiCtrlRecDigitalT;
+
+typedef struct {
+ SaHpiCtrlStateDiscreteT Default;
+} SaHpiCtrlRecDiscreteT;
+
+typedef struct {
+ SaHpiCtrlStateAnalogT Min; /* Minimum Value */
+ SaHpiCtrlStateAnalogT Max; /* Maximum Value */
+ SaHpiCtrlStateAnalogT Default;
+} SaHpiCtrlRecAnalogT;
+
+typedef struct {
+ SaHpiCtrlStateStreamT Default;
+} SaHpiCtrlRecStreamT;
+
+typedef struct {
+ SaHpiUint8T MaxChars; /* Maximum chars per line.
+ If the control DataType is
+ SAHPI_TL_TYPE_UNICODE, there will
+ be two bytes required for each
+ character. This field reports the
+ number of characters per line- not the
+ number of bytes. MaxChars must not be
+ larger than the number of characters
+ that can be placed in a single
+ SaHpiTextBufferT structure. */
+ SaHpiUint8T MaxLines; /* Maximum # of lines */
+ SaHpiLanguageT Language; /* Language Code */
+ SaHpiTextTypeT DataType; /* Permitted Data */
+ SaHpiCtrlStateTextT Default;
+} SaHpiCtrlRecTextT;
+
+#define SAHPI_CTRL_OEM_CONFIG_LENGTH 10
+typedef struct {
+ SaHpiManufacturerIdT MId;
+ SaHpiUint8T ConfigData[SAHPI_CTRL_OEM_CONFIG_LENGTH];
+ SaHpiCtrlStateOemT Default;
+} SaHpiCtrlRecOemT;
+
+typedef union {
+ SaHpiCtrlRecDigitalT Digital;
+ SaHpiCtrlRecDiscreteT Discrete;
+ SaHpiCtrlRecAnalogT Analog;
+ SaHpiCtrlRecStreamT Stream;
+ SaHpiCtrlRecTextT Text;
+ SaHpiCtrlRecOemT Oem;
+} SaHpiCtrlRecUnionT;
+
+/*
+** Default Control Mode Structure
+** This structure tells an HPI User if the control comes up in Auto mode or
+** in Manual mode, by default. It also indicates if the mode can be
+** changed (using saHpiControlSet()). When ReadOnly is False, the mode
+** can be changed from its default setting; otherwise attempting to
+** change the mode will result in an error.
+*/
+typedef struct {
+ SaHpiCtrlModeT Mode; /* Auto or Manual */
+ SaHpiBoolT ReadOnly; /* Indicates if mode is read-only */
+} SaHpiCtrlDefaultModeT;
+
+/*
+** Record Definition
+** Definition of the control resource data record.
+*/
+typedef struct {
+ SaHpiCtrlNumT Num; /* Control Number/Index */
+ SaHpiCtrlOutputTypeT OutputType;
+ SaHpiCtrlTypeT Type; /* Type of control */
+ SaHpiCtrlRecUnionT TypeUnion; /* Specific control record */
+ SaHpiCtrlDefaultModeT DefaultMode; /*Indicates if the control comes up
+ in Auto or Manual mode. */
+ SaHpiBoolT WriteOnly; /* Indicates if the control is
+ write-only. */
+ SaHpiUint32T Oem; /* Reserved for OEM use */
+} SaHpiCtrlRecT;
+
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Inventory Data Repositories **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+/*
+** These structures are used to read and write inventory data to entity
+** inventory data repositories within a resource.
+*/
+/*
+** Inventory Data Repository ID
+** Identifier for an inventory data repository.
+*/
+typedef SaHpiInstrumentIdT SaHpiIdrIdT;
+#define SAHPI_DEFAULT_INVENTORY_ID (SaHpiIdrIdT)0x00000000
+
+/* Inventory Data Area type definitions */
+typedef enum {
+ SAHPI_IDR_AREATYPE_INTERNAL_USE = 0xB0,
+ SAHPI_IDR_AREATYPE_CHASSIS_INFO,
+ SAHPI_IDR_AREATYPE_BOARD_INFO,
+ SAHPI_IDR_AREATYPE_PRODUCT_INFO,
+ SAHPI_IDR_AREATYPE_OEM = 0xC0,
+ SAHPI_IDR_AREATYPE_UNSPECIFIED = 0xFF
+} SaHpiIdrAreaTypeT;
+
+/* Inventory Data Field type definitions */
+typedef enum {
+ SAHPI_IDR_FIELDTYPE_CHASSIS_TYPE,
+ SAHPI_IDR_FIELDTYPE_MFG_DATETIME,
+ SAHPI_IDR_FIELDTYPE_MANUFACTURER,
+ SAHPI_IDR_FIELDTYPE_PRODUCT_NAME,
+ SAHPI_IDR_FIELDTYPE_PRODUCT_VERSION,
+ SAHPI_IDR_FIELDTYPE_SERIAL_NUMBER,
+ SAHPI_IDR_FIELDTYPE_PART_NUMBER,
+ SAHPI_IDR_FIELDTYPE_FILE_ID,
+ SAHPI_IDR_FIELDTYPE_ASSET_TAG,
+ SAHPI_IDR_FIELDTYPE_CUSTOM,
+ SAHPI_IDR_FIELDTYPE_UNSPECIFIED = 0xFF
+} SaHpiIdrFieldTypeT;
+
+/* Inventory Data Field structure definition */
+typedef struct {
+ SaHpiEntryIdT AreaId; /* AreaId for the IDA to which */
+ /* the Field belongs */
+ SaHpiEntryIdT FieldId; /* Field Identifier */
+ SaHpiIdrFieldTypeT Type; /* Field Type */
+ SaHpiBoolT ReadOnly; /* Describes if a field is read-only. */
+ /* All fields in a read-only area are */
+ /* flagged as read-only as well.*/
+ SaHpiTextBufferT Field; /* Field Data */
+} SaHpiIdrFieldT;
+
+/* Inventory Data Area header structure definition */
+typedef struct {
+ SaHpiEntryIdT AreaId; /* Area Identifier */
+ SaHpiIdrAreaTypeT Type; /* Type of area */
+ SaHpiBoolT ReadOnly; /* Describes if an area is read-only. */
+ /* All area headers in a read-only IDR */
+ /* are flagged as read-only as well.*/
+ SaHpiUint32T NumFields; /* Number of Fields contained in Area */
+} SaHpiIdrAreaHeaderT;
+
+/* Inventory Data Repository Information structure definition */
+typedef struct {
+ SaHpiIdrIdT IdrId; /* Repository Identifier */
+ SaHpiUint32T UpdateCount; /* The count is incremented any time the */
+ /* IDR is changed. It rolls over to zero */
+ /* when the maximum value is reached */
+ SaHpiBoolT ReadOnly; /* Describes if the IDR is read-only. */
+ /* All area headers and fields in a */
+ /* read-only IDR are flagged as */
+ /* read-only as well.*/
+ SaHpiUint32T NumAreas; /* Number of Area contained in IDR */
+} SaHpiIdrInfoT;
+
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Inventory Data Repository Resource Data Records **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** All inventory data contained in an inventory data repository
+** must be represented in the RDR repository
+** with an SaHpiInventoryRecT.
+*/
+typedef struct {
+ SaHpiIdrIdT IdrId;
+ SaHpiBoolT Persistent; /* True indicates that updates to IDR are
+ automatically and immediately persisted.
+ False indicates that updates are not
+ immediately persisted; but optionally may be
+ persisted via saHpiParmControl() function, as
+ defined in implementation documentation.*/
+ SaHpiUint32T Oem;
+} SaHpiInventoryRecT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Watchdogs **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** This section defines all of the data types associated with watchdog timers.
+*/
+
+/* Watchdog Number - Identifier for a watchdog timer. */
+typedef SaHpiInstrumentIdT SaHpiWatchdogNumT;
+#define SAHPI_DEFAULT_WATCHDOG_NUM (SaHpiWatchdogNumT)0x00000000
+
+/*
+** Watchdog Timer Action
+**
+** These enumerations represent the possible actions to be taken upon watchdog
+** timer timeout and the events that are generated for watchdog actions.
+*/
+typedef enum {
+ SAHPI_WA_NO_ACTION = 0,
+ SAHPI_WA_RESET,
+ SAHPI_WA_POWER_DOWN,
+ SAHPI_WA_POWER_CYCLE
+} SaHpiWatchdogActionT;
+
+typedef enum {
+ SAHPI_WAE_NO_ACTION = 0,
+ SAHPI_WAE_RESET,
+ SAHPI_WAE_POWER_DOWN,
+ SAHPI_WAE_POWER_CYCLE,
+ SAHPI_WAE_TIMER_INT=0x08 /* Used if Timer Preinterrupt only */
+} SaHpiWatchdogActionEventT;
+
+/*
+** Watchdog Pre-timer Interrupt
+**
+** These enumerations represent the possible types of interrupts that may be
+** triggered by a watchdog pre-timer event. The actual meaning of these
+** operations may differ depending on the hardware architecture.
+*/
+typedef enum {
+ SAHPI_WPI_NONE = 0,
+ SAHPI_WPI_SMI,
+ SAHPI_WPI_NMI,
+ SAHPI_WPI_MESSAGE_INTERRUPT,
+ SAHPI_WPI_OEM = 0x0F
+} SaHpiWatchdogPretimerInterruptT;
+
+/*
+** Watchdog Timer Use
+**
+** These enumerations represent the possible watchdog users that may have caused
+** the watchdog to expire. For instance, if watchdog is being used during power
+** on self test (POST), and it expires, the SAHPI_WTU_BIOS_POST expiration type
+** will be set. Most specific uses for Watchdog timer by users of HPI should
+** indicate SAHPI_WTU_SMS_OS if the use is to provide an OS-healthy heartbeat,
+** or SAHPI_WTU_OEM if it is used for some other purpose.
+*/
+typedef enum {
+ SAHPI_WTU_NONE = 0,
+ SAHPI_WTU_BIOS_FRB2,
+ SAHPI_WTU_BIOS_POST,
+ SAHPI_WTU_OS_LOAD,
+ SAHPI_WTU_SMS_OS, /* System Management System providing
+ heartbeat for OS */
+ SAHPI_WTU_OEM,
+ SAHPI_WTU_UNSPECIFIED = 0x0F
+} SaHpiWatchdogTimerUseT;
+
+/*
+** Timer Use Expiration Flags
+** These values are used for the Watchdog Timer Use Expiration flags in the
+** SaHpiWatchdogT structure.
+*/
+typedef SaHpiUint8T SaHpiWatchdogExpFlagsT;
+#define SAHPI_WATCHDOG_EXP_BIOS_FRB2 (SaHpiWatchdogExpFlagsT)0x02
+#define SAHPI_WATCHDOG_EXP_BIOS_POST (SaHpiWatchdogExpFlagsT)0x04
+#define SAHPI_WATCHDOG_EXP_OS_LOAD (SaHpiWatchdogExpFlagsT)0x08
+#define SAHPI_WATCHDOG_EXP_SMS_OS (SaHpiWatchdogExpFlagsT)0x10
+#define SAHPI_WATCHDOG_EXP_OEM (SaHpiWatchdogExpFlagsT)0x20
+
+/*
+** Watchdog Structure
+**
+** This structure is used by the saHpiWatchdogTimerGet() and
+** saHpiWatchdogTimerSet() functions. The use of the structure varies slightly
+** by each function.
+**
+** For saHpiWatchdogTimerGet() :
+**
+** Log - indicates whether or not the Watchdog is configured to
+** issue events. True=events will be generated.
+** Running - indicates whether or not the Watchdog is currently
+** running or stopped. True=Watchdog is running.
+** TimerUse - indicates the current use of the timer; one of the
+** enumerated preset uses which was included on the last
+** saHpiWatchdogTimerSet() function call, or through some
+** other implementation-dependent means to start the
+** Watchdog timer.
+** TimerAction - indicates what action will be taken when the Watchdog
+** times out.
+** PretimerInterrupt - indicates which action will be taken
+** "PreTimeoutInterval" milliseconds prior to Watchdog
+** timer expiration.
+** PreTimeoutInterval - indicates how many milliseconds prior to timer time
+** out the PretimerInterrupt action will be taken. If
+** "PreTimeoutInterval" = 0, the PretimerInterrupt action
+** will occur concurrently with "TimerAction." HPI
+** implementations may not be able to support millisecond
+** resolution, and because of this may have rounded the
+** set value to whatever resolution could be supported.
+** The HPI implementation will return this rounded value.
+** TimerUseExpFlags - set of five bit flags which indicate that a Watchdog
+** timer timeout has occurred while the corresponding
+** TimerUse value was set. Once set, these flags stay
+** set until specifically cleared with a
+** saHpiWatchdogTimerSet() call, or by some other
+** implementation-dependent means.
+** InitialCount - The time, in milliseconds, before the timer will time
+** out after the watchdog is started/restarted, or some
+** other implementation-dependent strobe is
+** sent to the Watchdog. HPI implementations may not be
+** able to support millisecond resolution, and because
+** of this may have rounded the set value to whatever
+** resolution could be supported. The HPI implementation
+** will return this rounded value.
+** PresentCount - The remaining time in milliseconds before the timer
+** will time out unless a saHpiWatchdogTimerReset()
+** function call is made, or some other implementation-
+** dependent strobe is sent to the Watchdog.
+** HPI implementations may not be able to support
+** millisecond resolution on watchdog timers, but will
+** return the number of clock ticks remaining times the
+** number of milliseconds between each tick.
+**
+** For saHpiWatchdogTimerSet():
+**
+** Log - indicates whether or not the Watchdog should issue
+** events. True=event will be generated.
+** Running - indicates whether or not the Watchdog should be
+** stopped before updating.
+** True = Watchdog is not stopped. If it is
+** already stopped, it will remain stopped,
+** but if it is running, it will continue
+** to run, with the countown timer reset
+** to the new InitialCount. Note that
+** there is a race condition possible
+** with this setting, so it should be used
+** with care.
+** False = Watchdog is stopped. After
+** saHpiWatchdogTimerSet() is called, a
+** subsequent call to
+** saHpiWatchdogTimerReset() is required
+** to start the timer.
+** TimerUse - indicates the current use of the timer. Will control
+** which TimerUseExpFlag is set if the timer expires.
+** TimerAction - indicates what action will be taken when the Watchdog
+** times out.
+** PretimerInterrupt - indicates which action will be taken
+** "PreTimeoutInterval" milliseconds prior to Watchdog
+** timer expiration.
+** PreTimeoutInterval - indicates how many milliseconds prior to timer time
+** out the PretimerInterrupt action will be taken. If
+** "PreTimeoutInterval" = 0, the PretimerInterrupt action
+** will occur concurrently with "TimerAction." HPI
+** implementations may not be able to support millisecond
+** resolution and may have a maximum value restriction.
+** These restrictions should be documented by the
+** provider of the HPI interface.
+** TimerUseExpFlags - Set of five bit flags corresponding to the five
+** TimerUse values. For each bit set, the corresponding
+** Timer Use Expiration Flag will be CLEARED. Generally,
+** a program should only clear the Timer Use Expiration
+** Flag corresponding to its own TimerUse, so that other
+** software, which may have used the timer for another
+** purpose in the past can still read its TimerUseExpFlag
+** to determine whether or not the timer expired during
+** that use.
+** InitialCount - The time, in milliseconds, before the timer will time
+** out after a saHpiWatchdogTimerReset() function call is
+** made, or some other implementation-dependent strobe is
+** sent to the Watchdog. HPI implementations may not be
+** able to support millisecond resolution and may have a
+** maximum value restriction. These restrictions should
+** be documented by the provider of the HPI interface.
+** PresentCount - Not used on saHpiWatchdogTimerSet() function. Ignored.
+**
+*/
+
+typedef struct {
+ SaHpiBoolT Log;
+ SaHpiBoolT Running;
+ SaHpiWatchdogTimerUseT TimerUse;
+ SaHpiWatchdogActionT TimerAction;
+ SaHpiWatchdogPretimerInterruptT PretimerInterrupt;
+ SaHpiUint32T PreTimeoutInterval;
+ SaHpiWatchdogExpFlagsT TimerUseExpFlags;
+ SaHpiUint32T InitialCount;
+ SaHpiUint32T PresentCount;
+} SaHpiWatchdogT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Watchdog Resource Data Records **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** When the "Watchdog" capability is set in a resource, a watchdog with an
+** identifier of SAHPI_DEFAULT_WATCHDOG_NUM is required. All watchdogs must be
+** represented in the RDR repository with an SaHpiWatchdogRecT, including the
+** watchdog with an identifier of SAHPI_DEFAULT_WATCHDOG_NUM.
+*/
+typedef struct {
+ SaHpiWatchdogNumT WatchdogNum;
+ SaHpiUint32T Oem;
+} SaHpiWatchdogRecT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Hot Swap **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* Hot Swap Indicator State */
+typedef enum {
+ SAHPI_HS_INDICATOR_OFF = 0,
+ SAHPI_HS_INDICATOR_ON
+} SaHpiHsIndicatorStateT;
+
+/* Hot Swap Action */
+typedef enum {
+ SAHPI_HS_ACTION_INSERTION = 0,
+ SAHPI_HS_ACTION_EXTRACTION
+} SaHpiHsActionT;
+
+/* Hot Swap State */
+typedef enum {
+ SAHPI_HS_STATE_INACTIVE = 0,
+ SAHPI_HS_STATE_INSERTION_PENDING,
+ SAHPI_HS_STATE_ACTIVE,
+ SAHPI_HS_STATE_EXTRACTION_PENDING,
+ SAHPI_HS_STATE_NOT_PRESENT
+} SaHpiHsStateT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Events, Part 2 **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* Event Data Structures */
+
+typedef enum {
+ SAHPI_CRITICAL = 0,
+ SAHPI_MAJOR,
+ SAHPI_MINOR,
+ SAHPI_INFORMATIONAL,
+ SAHPI_OK,
+ SAHPI_DEBUG = 0xF0,
+ SAHPI_ALL_SEVERITIES = 0xFF /* Only used with DAT and Annunciator */
+ /* functions. This is not a valid */
+ /* severity for events or alarms */
+} SaHpiSeverityT;
+
+
+typedef enum {
+ SAHPI_RESE_RESOURCE_FAILURE,
+ SAHPI_RESE_RESOURCE_RESTORED,
+ SAHPI_RESE_RESOURCE_ADDED
+} SaHpiResourceEventTypeT;
+
+
+typedef struct {
+ SaHpiResourceEventTypeT ResourceEventType;
+} SaHpiResourceEventT;
+
+
+/*
+** Domain events are used to announce the addition of domain references
+** and the removal of domain references to the DRT.
+*/
+typedef enum {
+ SAHPI_DOMAIN_REF_ADDED,
+ SAHPI_DOMAIN_REF_REMOVED
+} SaHpiDomainEventTypeT;
+
+typedef struct {
+ SaHpiDomainEventTypeT Type; /* Type of domain event */
+ SaHpiDomainIdT DomainId; /* Domain Id of domain added
+ to or removed from DRT. */
+} SaHpiDomainEventT;
+
+
+/*
+** Sensor Optional Data
+**
+** Sensor events may contain optional data items passed and stored with the
+** event. If these optional data items are present, they will be included with
+** the event data returned in response to a saHpiEventGet() or
+** saHpiEventLogEntryGet() function call. Also, the optional data items may be
+** included with the event data passed to the saHpiEventLogEntryAdd() function.
+**
+** Specific implementations of HPI may have restrictions on how much data may
+** be passed to saHpiEventLogEntryAdd(). These restrictions should be documented
+** by the provider of the HPI interface.
+*/
+typedef SaHpiUint8T SaHpiSensorOptionalDataT;
+
+#define SAHPI_SOD_TRIGGER_READING (SaHpiSensorOptionalDataT)0x01
+#define SAHPI_SOD_TRIGGER_THRESHOLD (SaHpiSensorOptionalDataT)0x02
+#define SAHPI_SOD_OEM (SaHpiSensorOptionalDataT)0x04
+#define SAHPI_SOD_PREVIOUS_STATE (SaHpiSensorOptionalDataT)0x08
+#define SAHPI_SOD_CURRENT_STATE (SaHpiSensorOptionalDataT)0x10
+#define SAHPI_SOD_SENSOR_SPECIFIC (SaHpiSensorOptionalDataT)0x20
+typedef struct {
+ SaHpiSensorNumT SensorNum;
+ SaHpiSensorTypeT SensorType;
+ SaHpiEventCategoryT EventCategory;
+ SaHpiBoolT Assertion; /* True = Event State
+ asserted
+ False = deasserted */
+ SaHpiEventStateT EventState; /* single state being asserted
+ or deasserted*/
+ SaHpiSensorOptionalDataT OptionalDataPresent;
+ /* the following fields are only valid if the corresponding flag is set
+ in the OptionalDataPresent field */
+ SaHpiSensorReadingT TriggerReading; /* Reading that triggered
+ the event */
+ SaHpiSensorReadingT TriggerThreshold; /* Value of the threshold
+ that was crossed. Will not
+ be present if threshold is
+ not readable. */
+ SaHpiEventStateT PreviousState; /* Previous set of asserted
+ event states. If multiple
+ event states change at once,
+ multiple events may be
+ generated for each changing
+ event state. This field
+ should indicate the status of
+ the sensor event states prior
+ to any of the simultaneous
+ changes.
+
+ Thus, it will be the same in
+ each event generated due to
+ multiple simultaneous event
+ state changes. */
+
+ SaHpiEventStateT CurrentState; /* Current set of asserted
+ event states. */
+ SaHpiUint32T Oem;
+ SaHpiUint32T SensorSpecific;
+} SaHpiSensorEventT;
+
+typedef SaHpiUint8T SaHpiSensorEnableOptDataT;
+
+#define SAHPI_SEOD_CURRENT_STATE (SaHpiSensorEnableOptDataT)0x10
+
+typedef struct {
+ SaHpiSensorNumT SensorNum;
+ SaHpiSensorTypeT SensorType;
+ SaHpiEventCategoryT EventCategory;
+ SaHpiBoolT SensorEnable; /* current sensor enable status */
+ SaHpiBoolT SensorEventEnable; /* current evt enable status */
+ SaHpiEventStateT AssertEventMask; /* current assert event mask */
+ SaHpiEventStateT DeassertEventMask; /* current deassert evt mask */
+ SaHpiSensorEnableOptDataT OptionalDataPresent;
+ /* the following fields are only valid if the corresponding flag is set
+ in the OptionalDataPresent field */
+ SaHpiEventStateT CurrentState; /* Current set of asserted
+ Event states. */
+} SaHpiSensorEnableChangeEventT;
+
+typedef struct {
+ SaHpiHsStateT HotSwapState;
+ SaHpiHsStateT PreviousHotSwapState;
+} SaHpiHotSwapEventT;
+
+typedef struct {
+ SaHpiWatchdogNumT WatchdogNum;
+ SaHpiWatchdogActionEventT WatchdogAction;
+ SaHpiWatchdogPretimerInterruptT WatchdogPreTimerAction;
+ SaHpiWatchdogTimerUseT WatchdogUse;
+} SaHpiWatchdogEventT;
+
+/*
+** The following type defines the types of events that can be reported
+** by the HPI software implementation.
+**
+** Audit events report a discrepancy in the audit process. Audits are typically
+** performed by HA software to detect problems. Audits may look for such things
+** as corrupted data stores, inconsistent RPT information, or improperly managed
+** queues.
+**
+** Startup events report a failure to start-up properly, or inconsistencies in
+** persisted data.
+*/
+typedef enum {
+ SAHPI_HPIE_AUDIT,
+ SAHPI_HPIE_STARTUP,
+ SAHPI_HPIE_OTHER
+} SaHpiSwEventTypeT;
+
+typedef struct {
+ SaHpiManufacturerIdT MId;
+ SaHpiSwEventTypeT Type;
+ SaHpiTextBufferT EventData;
+} SaHpiHpiSwEventT;
+
+typedef struct {
+ SaHpiManufacturerIdT MId;
+ SaHpiTextBufferT OemEventData;
+} SaHpiOemEventT;
+
+/*
+** User events may be used for storing custom events created by an HPI User
+** when injecting events into the Event Log using saHpiEventLogEntryAdd().
+*/
+typedef struct {
+ SaHpiTextBufferT UserEventData;
+} SaHpiUserEventT;
+
+typedef enum {
+ SAHPI_ET_RESOURCE,
+ SAHPI_ET_DOMAIN,
+ SAHPI_ET_SENSOR,
+ SAHPI_ET_SENSOR_ENABLE_CHANGE,
+ SAHPI_ET_HOTSWAP,
+ SAHPI_ET_WATCHDOG,
+ SAHPI_ET_HPI_SW,
+ SAHPI_ET_OEM,
+ SAHPI_ET_USER
+} SaHpiEventTypeT;
+
+typedef union {
+ SaHpiResourceEventT ResourceEvent;
+ SaHpiDomainEventT DomainEvent;
+ SaHpiSensorEventT SensorEvent;
+ SaHpiSensorEnableChangeEventT SensorEnableChangeEvent;
+ SaHpiHotSwapEventT HotSwapEvent;
+ SaHpiWatchdogEventT WatchdogEvent;
+ SaHpiHpiSwEventT HpiSwEvent;
+ SaHpiOemEventT OemEvent;
+ SaHpiUserEventT UserEvent;
+} SaHpiEventUnionT;
+
+typedef struct {
+ SaHpiResourceIdT Source;
+ SaHpiEventTypeT EventType;
+ SaHpiTimeT Timestamp; /*Equal to SAHPI_TIME_UNSPECIFED if time is
+ not available; Absolute time if greater
+ than SAHPI_TIME_MAX_RELATIVE, Relative
+ time if less than or equal to
+ SAHPI_TIME_MAX_RELATIVE */
+ SaHpiSeverityT Severity;
+ SaHpiEventUnionT EventDataUnion;
+} SaHpiEventT;
+
+/*
+** Event Queue Status
+**
+** This status word is returned to HPI Users that request it
+** when saHpiEventGet() is called.
+**
+*/
+
+typedef SaHpiUint32T SaHpiEvtQueueStatusT;
+
+#define SAHPI_EVT_QUEUE_OVERFLOW (SaHpiEvtQueueStatusT)0x0001
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Annunciators **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** Annunciator Number
+** Identifier for an Annunciator management instrument.
+*/
+typedef SaHpiInstrumentIdT SaHpiAnnunciatorNumT;
+
+/*
+** The following data type is equivalent to the AIS data type SaNameT.
+** it is defined in this header file, so that inclusion of the AIS
+** header file is not required. This data type is based on version 1.0
+** of the AIS specification
+*/
+#define SA_HPI_MAX_NAME_LENGTH 256
+
+typedef struct {
+ SaHpiUint16T Length;
+ unsigned char Value[SA_HPI_MAX_NAME_LENGTH];
+} SaHpiNameT;
+
+/*
+** Enumeration of Announcement Types
+*/
+typedef enum {
+ SAHPI_STATUS_COND_TYPE_SENSOR,
+ SAHPI_STATUS_COND_TYPE_RESOURCE,
+ SAHPI_STATUS_COND_TYPE_OEM,
+ SAHPI_STATUS_COND_TYPE_USER
+} SaHpiStatusCondTypeT;
+
+
+/* Condition structure definition */
+typedef struct {
+
+ SaHpiStatusCondTypeT Type; /* Status Condition Type */
+ SaHpiEntityPathT Entity; /* Entity assoc. with status condition */
+ SaHpiDomainIdT DomainId; /* Domain associated with status.
+ May be SAHPI_UNSPECIFIED_DOMAIND_ID
+ meaning current domain, or domain
+ not meaningful for status condition*/
+ SaHpiResourceIdT ResourceId; /* Resource associated with status.
+ May be SAHPI_UNSPECIFIED_RESOURCE_ID
+ if Type is SAHPI_STATUS_COND_USER.
+ Must be set to valid ResourceId in
+ domain specified by DomainId,
+ or in current domain, if DomainId
+ is SAHPI_UNSPECIFIED_DOMAIN_ID */
+ SaHpiSensorNumT SensorNum; /* Sensor associated with status
+ Only valid if Type is
+ SAHPI_STATUS_COND_TYPE_SENSOR */
+ SaHpiEventStateT EventState; /* Sensor event state.
+ Only valid if Type is
+ SAHPI_STATUS_COND_TYPE_SENSOR. */
+ SaHpiNameT Name; /* AIS compatible identifier associated
+ with Status condition */
+ SaHpiManufacturerIdT Mid; /* Manufacturer Id associated with
+ status condition, required when type
+ is SAHPI_STATUS_COND_TYPE_OEM. */
+ SaHpiTextBufferT Data; /* Optional Data associated with
+ Status condition */
+} SaHpiConditionT;
+
+
+/* Announcement structure definition */
+typedef struct {
+ SaHpiEntryIdT EntryId; /* Announcment Entry Id */
+ SaHpiTimeT Timestamp; /* Time when announcement added to set */
+ SaHpiBoolT AddedByUser; /* True if added to set by HPI User,
+ False if added automatically by
+ HPI implementation */
+ SaHpiSeverityT Severity; /* Severity of announcement */
+ SaHpiBoolT Acknowledged; /* Acknowledged flag */
+ SaHpiConditionT StatusCond; /* Detailed status condition */
+} SaHpiAnnouncementT;
+
+
+/* Annunciator Mode - defines who may add or delete entries in set. */
+
+typedef enum {
+ SAHPI_ANNUNCIATOR_MODE_AUTO,
+ SAHPI_ANNUNCIATOR_MODE_USER,
+ SAHPI_ANNUNCIATOR_MODE_SHARED
+} SaHpiAnnunciatorModeT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Annunciator Resource Data Records **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** The following enumerated type defines the possible output types
+** which can be associated with an Annunciator Management Instrument
+*/
+typedef enum {
+ SAHPI_ANNUNCIATOR_TYPE_LED = 0,
+ SAHPI_ANNUNCIATOR_TYPE_DRY_CONTACT_CLOSURE,
+ SAHPI_ANNUNCIATOR_TYPE_AUDIBLE,
+ SAHPI_ANNUNCIATOR_TYPE_LCD_DISPLAY,
+ SAHPI_ANNUNCIATOR_TYPE_MESSAGE,
+ SAHPI_ANNUNCIATOR_TYPE_COMPOSITE,
+ SAHPI_ANNUNCIATOR_TYPE_OEM
+} SaHpiAnnunciatorTypeT;
+
+
+/*
+** All annunciator management instruments
+** must be represented in the RDR repository
+** with an SaHpiAnnunciatorRecT.
+*/
+typedef struct {
+ SaHpiAnnunciatorNumT AnnunciatorNum;
+ SaHpiAnnunciatorTypeT AnnunciatorType; /* Annunciator Output Type */
+ SaHpiBoolT ModeReadOnly; /* if True, Mode may
+ not be changed by HPI User */
+ SaHpiUint32T MaxConditions; /* maximum number of conditions
+ that can be held in current
+ set. 0 means no fixed
+ limit. */
+ SaHpiUint32T Oem;
+} SaHpiAnnunciatorRecT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Resource Data Record **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/*
+** The following describes the different types of records that exist within a
+** RDR repository and the RDR super-structure to all of the specific RDR types
+** (sensor, inventory data, watchdog, etc.).
+*/
+typedef enum {
+ SAHPI_NO_RECORD,
+ SAHPI_CTRL_RDR,
+ SAHPI_SENSOR_RDR,
+ SAHPI_INVENTORY_RDR,
+ SAHPI_WATCHDOG_RDR,
+ SAHPI_ANNUNCIATOR_RDR
+} SaHpiRdrTypeT;
+
+typedef union {
+ SaHpiCtrlRecT CtrlRec;
+ SaHpiSensorRecT SensorRec;
+ SaHpiInventoryRecT InventoryRec;
+ SaHpiWatchdogRecT WatchdogRec;
+ SaHpiAnnunciatorRecT AnnunciatorRec;
+} SaHpiRdrTypeUnionT;
+
+typedef struct {
+ SaHpiEntryIdT RecordId;
+ SaHpiRdrTypeT RdrType;
+ SaHpiEntityPathT Entity; /* Entity to which this RDR relates. */
+ SaHpiBoolT IsFru; /* Entity is a FRU. This field is
+ Only valid if the Entity path given
+ in the "Entity" field is different
+ from the Entity path in the RPT
+ entry for the resource. */
+ SaHpiRdrTypeUnionT RdrTypeUnion;
+ SaHpiTextBufferT IdString;
+} SaHpiRdrT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Parameter Control **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+typedef enum {
+ SAHPI_DEFAULT_PARM = 0,
+ SAHPI_SAVE_PARM,
+ SAHPI_RESTORE_PARM
+} SaHpiParmActionT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Reset **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+typedef enum {
+ SAHPI_COLD_RESET = 0,
+ SAHPI_WARM_RESET,
+ SAHPI_RESET_ASSERT,
+ SAHPI_RESET_DEASSERT
+} SaHpiResetActionT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Power **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+typedef enum {
+ SAHPI_POWER_OFF = 0,
+ SAHPI_POWER_ON,
+ SAHPI_POWER_CYCLE
+} SaHpiPowerStateT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Resource Presence Table **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* This section defines the types associated with the RPT. */
+
+/*
+** GUID - Globally Unique Identifier
+**
+** The format if the ID follows that specified by the Wired for Management
+** Baseline, Version 2.0 specification. HPI uses version 1 of the GUID
+** format, with a 3-bit variant field of 10x (where x indicates 'don't care')
+*/
+typedef SaHpiUint8T SaHpiGuidT[16];
+
+/*
+** Resource Info Type Definitions
+**
+**
+** SaHpiResourceInfoT contains static configuration data concerning the
+** management controller associated with the resource, or the resource itself.
+** Note this information is used to describe the resource; that is, the piece of
+** infrastructure which manages an entity (or multiple entities) - NOT the
+** entities for which the resource provides management. The purpose of the
+** SaHpiResourceInfoT structure is to provide information that an HPI User may
+** need in order to interact correctly with the resource (e.g., recognize a
+** specific management controller which may have defined OEM fields in sensors,
+** OEM controls, etc.).
+**
+** The GUID is used to uniquely identify a Resource. A GUID value of zero is not
+** valid and indicates that the Resource does not have an associated GUID.
+**
+** All of the fields in the following structure may or may not be used by a
+** given resource.
+*/
+typedef struct {
+ SaHpiUint8T ResourceRev;
+ SaHpiUint8T SpecificVer;
+ SaHpiUint8T DeviceSupport;
+ SaHpiManufacturerIdT ManufacturerId;
+ SaHpiUint16T ProductId;
+ SaHpiUint8T FirmwareMajorRev;
+ SaHpiUint8T FirmwareMinorRev;
+ SaHpiUint8T AuxFirmwareRev;
+ SaHpiGuidT Guid;
+} SaHpiResourceInfoT;
+
+/*
+** Resource Capabilities
+**
+** This definition defines the capabilities of a given resource. One resource
+** may support any number of capabilities using the bit mask. Because each entry
+** in an RPT will have the SAHPI_CAPABILITY_RESOURCE bit set, zero is not a
+** valid value for the capability flag, and is thus used to indicate "no RPT
+** entry present" in some function calls.
+**
+** SAHPI_CAPABILITY_RESOURCE
+** SAHPI_CAPABILITY_EVT_DEASSERTS
+** Indicates that all sensors on the resource have the property that their
+** Assertion and Deassertion event enable flags are the same. That is,
+** for all event states whose assertion triggers an event, it is
+** guaranteed that the deassertion of that event will also
+** trigger an event. Thus, an HPI User may track the state of sensors on the
+** resource by monitoring events rather than polling for state changes.
+** SAHPI_CAPABILITY_AGGREGATE_STATUS
+** SAHPI_CAPABILITY_CONFIGURATION
+** SAHPI_CAPABILITY_MANAGED_HOTSWAP
+** Indicates that the resource supports the full managed hot swap model.
+** Since hot swap only makes sense for field-replaceable units, the
+** SAHPI_CAPABILITY_FRU capability bit must also be set for this resource.
+** SAHPI_CAPABILITY_WATCHDOG
+** SAHPI_CAPABILITY_CONTROL
+** SAHPI_CAPABILITY_FRU
+** Indicates that the resource is a field-replaceable unit; i.e., it is
+** capable of being removed and replaced in a live system. If
+** SAHPI_CAPABILITY_MANAGED_HOTSWAP is also set, the resource supports
+** the full hot swap model. If SAHPI_CAPABILITY_MANAGED_HOTSWAP is not
+** set, the resource supports the simplified hot swap model.
+** SAHPI_CAPABILITY_ANNUNCIATOR
+** SAHPI_CAPABILITY_POWER
+** SAHPI_CAPABILITY_RESET
+** SAHPI_CAPABILITY_INVENTORY_DATA
+** SAHPI_CAPABILITY_EVENT_LOG
+** SAHPI_CAPABILITY_RDR
+** Indicates that a resource data record (RDR) repository is supplied
+** by the resource. Since the existence of an RDR is mandatory for all
+** management instruments, this
+** capability must be asserted if the resource
+** contains any sensors, controls, watchdog timers, or inventory
+** data repositories.
+** SAHPI_CAPABILITY_SENSOR
+*/
+
+typedef SaHpiUint32T SaHpiCapabilitiesT;
+#define SAHPI_CAPABILITY_RESOURCE (SaHpiCapabilitiesT)0X40000000
+#define SAHPI_CAPABILITY_EVT_DEASSERTS (SaHpiCapabilitiesT)0x00008000
+#define SAHPI_CAPABILITY_AGGREGATE_STATUS (SaHpiCapabilitiesT)0x00002000
+#define SAHPI_CAPABILITY_CONFIGURATION (SaHpiCapabilitiesT)0x00001000
+#define SAHPI_CAPABILITY_MANAGED_HOTSWAP (SaHpiCapabilitiesT)0x00000800
+#define SAHPI_CAPABILITY_WATCHDOG (SaHpiCapabilitiesT)0x00000400
+#define SAHPI_CAPABILITY_CONTROL (SaHpiCapabilitiesT)0x00000200
+#define SAHPI_CAPABILITY_FRU (SaHpiCapabilitiesT)0x00000100
+#define SAHPI_CAPABILITY_ANNUNCIATOR (SaHpiCapabilitiesT)0x00000040
+#define SAHPI_CAPABILITY_POWER (SaHpiCapabilitiesT)0x00000020
+#define SAHPI_CAPABILITY_RESET (SaHpiCapabilitiesT)0x00000010
+#define SAHPI_CAPABILITY_INVENTORY_DATA (SaHpiCapabilitiesT)0x00000008
+#define SAHPI_CAPABILITY_EVENT_LOG (SaHpiCapabilitiesT)0x00000004
+#define SAHPI_CAPABILITY_RDR (SaHpiCapabilitiesT)0x00000002
+#define SAHPI_CAPABILITY_SENSOR (SaHpiCapabilitiesT)0x00000001
+
+/*
+** Resource Managed Hot Swap Capabilities
+**
+** This definition defines the managed hot swap capabilities of a given
+** resource.
+**
+** SAHPI_HS_CAPABILITY_AUTOEXTRACT_READ_ONLY
+** This capability indicates if the hot swap autoextract timer is read-only.
+** SAHPI_HS_CAPABILITY_INDICATOR_SUPPORTED
+** Indicates whether or not the resource has a hot swap indicator.
+*/
+
+typedef SaHpiUint32T SaHpiHsCapabilitiesT;
+#define SAHPI_HS_CAPABILITY_AUTOEXTRACT_READ_ONLY \
+ (SaHpiHsCapabilitiesT)0x80000000
+#define SAHPI_HS_CAPABILITY_INDICATOR_SUPPORTED \
+ (SaHpiHsCapabilitiesT)0X40000000
+/*
+** RPT Entry
+**
+** This structure is used to store the RPT entry information.
+**
+** The ResourceCapabilities field definies the capabilities of the resource.
+** This field must be non-zero for all valid resources.
+**
+** The HotSwapCapabilities field denotes the capabilities of the resource,
+** specifically related to hot swap. This field is only valid if the
+** resource supports managed hot swap, as indicated by the
+** SAHPI_CAPABILITY_MANAGED_HOT_SWAP resource capability.
+**
+** The ResourceTag is a data field within an RPT entry available to the HPI
+** User for associating application specific data with a resource. The HPI
+** User supplied data is purely informational and is not used by the HPI
+** implementation, domain, or associated resource. For example, an HPI User
+** can set the resource tag to a "descriptive" value, which can be used to
+** identify the resource in messages to a human operator.
+*/
+typedef struct {
+ SaHpiEntryIdT EntryId;
+ SaHpiResourceIdT ResourceId;
+ SaHpiResourceInfoT ResourceInfo;
+ SaHpiEntityPathT ResourceEntity; /* If resource manages a FRU, entity
+ path of the FRU */
+ /* If resource manages a single
+ entity, entity path of that
+ entity. */
+ /* If resource manages multiple
+ entities, the entity path of the
+ "primary" entity managed by the
+ resource */
+ /* Must be set to the same value in
+ every domain which contains this
+ resource */
+ SaHpiCapabilitiesT ResourceCapabilities; /* Must be non-0. */
+ SaHpiHsCapabilitiesT HotSwapCapabilities; /* Indicates the hot swap
+ capabilities of the resource */
+ SaHpiSeverityT ResourceSeverity; /* Indicates the criticality that
+ should be raised when the resource
+ is not responding */
+ SaHpiBoolT ResourceFailed; /* Indicates that the resource is not
+ currently functional */
+ SaHpiTextBufferT ResourceTag;
+} SaHpiRptEntryT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Domain Information **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+
+/* This section defines the types associated with the domain controller. */
+
+/*
+** Domain Capabilities
+**
+** This definition defines the capabilities of a given domain. A domain
+** may support any number of capabilities using the bit mask.
+**
+** SAHPI_DOMAIN_CAP_AUTOINSERT_READ_ONLY
+** Indicates that the domain auto insert timeout value is read-only
+** and may not be modified using the saHpiHotSwapAutoInsertTimeoutSet()
+** function.
+*/
+
+typedef SaHpiUint32T SaHpiDomainCapabilitiesT;
+#define SAHPI_DOMAIN_CAP_AUTOINSERT_READ_ONLY \
+ (SaHpiDomainCapabilitiesT)0X00000001
+
+/*
+** Domain Info
+**
+** This structure is used to store the information regarding the domain
+** including information regarding the domain reference table (DRT) and
+** the resource presence table (RPT).
+**
+** The DomainTag field is an informational value that supplies an HPI User
+** with naming information for the domain.
+**
+** NOTE: Regarding timestamps - If the implementation cannot supply an absolute
+** timestamp, then it may supply a timestamp relative to some system-defined
+** epoch, such as system boot. The value SAHPI_TIME_UNSPECIFIED indicates that
+** the time of the update cannot be determined. Otherwise, If the value is less
+** than or equal to SAHPI_TIME_MAX_RELATIVE, then it is relative; if it is
+** greater than SAHPI_TIME_MAX_RELATIVE, then it is absolute.
+**
+** The GUID is used to uniquely identify a domain. A GUID value of zero is not
+** valid and indicates that the domain does not have an associated GUID.
+*/
+
+typedef struct {
+ SaHpiDomainIdT DomainId; /* Unique Domain Id associated with
+ domain */
+ SaHpiDomainCapabilitiesT DomainCapabilities; /* Domain Capabilities */
+ SaHpiBoolT IsPeer; /* Indicates that this domain
+ participates in a peer
+ relationship. */
+ SaHpiTextBufferT DomainTag; /* Information tag associated with
+ domain */
+ SaHpiUint32T DrtUpdateCount; /* This count is incremented any time the
+ table is changed. It rolls over to
+ zero when the maximum value is
+ reached */
+ SaHpiTimeT DrtUpdateTimestamp; /* This timestamp is set any time the
+ DRT table is changed. */
+ SaHpiUint32T RptUpdateCount; /* This count is incremented any time
+ the RPT is changed. It rolls over
+ to zero when the maximum value is
+ reached */
+ SaHpiTimeT RptUpdateTimestamp; /* This timestamp is set any time the
+ RPT table is changed. */
+ SaHpiUint32T DatUpdateCount; /* This count is incremented any time
+ the DAT is changed. It rolls over to
+ zero when the maximum value is
+ reached */
+ SaHpiTimeT DatUpdateTimestamp; /* This timestamp is set any time the
+ DAT is changed. */
+ SaHpiUint32T ActiveAlarms; /* Count of active alarms in the DAT */
+ SaHpiUint32T CriticalAlarms; /* Count of active critical alarms in
+ the DAT */
+ SaHpiUint32T MajorAlarms; /* Count of active major alarms in the
+ DAT */
+ SaHpiUint32T MinorAlarms; /* Count of active minor alarms in the
+ DAT */
+ SaHpiUint32T DatUserAlarmLimit; /* Maximum User Alarms that can be
+ added to DAT. 0=no fixed limit */
+ SaHpiBoolT DatOverflow; /* Set to True if there are one
+ or more non-User Alarms that
+ are missing from the DAT because
+ of space limitations */
+ SaHpiGuidT Guid; /* GUID associated with domain.*/
+} SaHpiDomainInfoT;
+
+/*
+** DRT Entry
+**
+** This structure is used to store the DRT entry information.
+**
+*/
+typedef struct {
+ SaHpiEntryIdT EntryId;
+ SaHpiDomainIdT DomainId; /* The Domain ID referenced by this entry */
+ SaHpiBoolT IsPeer; /* Indicates if this domain reference
+ is a peer. If not, the domain reference
+ is a tier. */
+} SaHpiDrtEntryT;
+
+
+/*
+** DAT Entry
+**
+** This structure is used to store alarm informatin in the DAT
+**
+*/
+
+
+typedef SaHpiEntryIdT SaHpiAlarmIdT;
+
+typedef struct {
+ SaHpiAlarmIdT AlarmId; /* Alarm Id */
+ SaHpiTimeT Timestamp; /* Time when alarm added to DAT */
+ SaHpiSeverityT Severity; /* Severity of alarm */
+ SaHpiBoolT Acknowledged; /* Acknowledged flag */
+ SaHpiConditionT AlarmCond; /* Detailed alarm condition */
+} SaHpiAlarmT;
+
+/*******************************************************************************
+********************************************************************************
+********** **********
+********** Event Log **********
+********** **********
+********************************************************************************
+*******************************************************************************/
+/* This section defines the types associated with the Event Log. */
+/*
+** Event Log Information
+**
+** The Entries entry denotes the number of active entries contained in the Event
+** Log.
+** The Size entry denotes the total number of entries the Event Log is able to
+** hold.
+** The UserEventMaxSize entry indicates the maximum size of the text buffer
+** data field in an HPI User event that is supported by the Event Log
+** implementation. If the implementation does not enforce a more restrictive
+** data length, it should be set to SAHPI_MAX_TEXT_BUFFER_LENGTH.
+** The UpdateTimestamp entry denotes the time of the last update to the Event
+** Log.
+** The CurrentTime entry denotes the Event Log's idea of the current time; i.e
+** the timestamp that would be placed on an entry if it was added now.
+** The Enabled entry indicates whether the Event Log is enabled. If the Event
+** Log is "disabled" no events generated within the HPI implementation will be
+** added to the Event Log. Events may still be added to the Event Log with
+** the saHpiEventLogEntryAdd() function. When the Event Log is "enabled"
+** events may be automatically added to the Event Log as they are generated
+** in a resource or a domain, however, it is implementation-specific which
+** events are automatically added to any Event Log.
+** The OverflowFlag entry indicates the Event Log has overflowed. Events have
+** been dropped or overwritten due to a table overflow.
+** The OverflowAction entry indicates the behavior of the Event Log when an
+** overflow occurs.
+** The OverflowResetable entry indicates if the overflow flag can be
+** cleared by an HPI User with the saHpiEventLogOverflowReset() function.
+*/
+typedef enum {
+ SAHPI_EL_OVERFLOW_DROP, /* New entries are dropped when Event Log is
+ full*/
+ SAHPI_EL_OVERFLOW_OVERWRITE /* Event Log overwrites existing entries
+ when Event Log is full */
+} SaHpiEventLogOverflowActionT;
+
+typedef struct {
+ SaHpiUint32T Entries;
+ SaHpiUint32T Size;
+ SaHpiUint32T UserEventMaxSize;
+ SaHpiTimeT UpdateTimestamp;
+ SaHpiTimeT CurrentTime;
+ SaHpiBoolT Enabled;
+ SaHpiBoolT OverflowFlag;
+ SaHpiBoolT OverflowResetable;
+ SaHpiEventLogOverflowActionT OverflowAction;
+} SaHpiEventLogInfoT;
+/*
+** Event Log Entry
+** These types define the Event Log entry.
+*/
+typedef SaHpiUint32T SaHpiEventLogEntryIdT;
+/* Reserved values for Event Log entry IDs */
+#define SAHPI_OLDEST_ENTRY (SaHpiEventLogEntryIdT)0x00000000
+#define SAHPI_NEWEST_ENTRY (SaHpiEventLogEntryIdT)0xFFFFFFFF
+#define SAHPI_NO_MORE_ENTRIES (SaHpiEventLogEntryIdT)0xFFFFFFFE
+
+typedef struct {
+ SaHpiEventLogEntryIdT EntryId; /* Entry ID for record */
+ SaHpiTimeT Timestamp; /* Time at which the event was placed
+ in the Event Log. If less than or equal to
+ SAHPI_TIME_MAX_RELATIVE, then it is
+ relative; if it is greater than SAHPI_TIME_
+ MAX_RELATIVE, then it is absolute. */
+ SaHpiEventT Event; /* Logged Event */
+} SaHpiEventLogEntryT;
+
+
+/*******************************************************************************
+**
+** Name: saHpiVersionGet()
+**
+** Description:
+** This function returns the version identifier of the SaHpi specification
+** version supported by the HPI implementation.
+**
+** Parameters:
+** None.
+**
+** Return Value:
+** The interface version identifier, of type SaHpiVersionT is returned.
+**
+** Remarks:
+** This function differs from all other interface functions in that it
+** returns the version identifier rather than a standard return code. This is
+** because the version itself is necessary in order for an HPI User to
+** properly interpret subsequent API return codes. Thus, the
+** saHpiVersionGet() function returns the interface version identifier
+** unconditionally.
+**
+** This function returns the value of the header file symbol
+** SAHPI_INTERFACE_VERSION in the SaHpi.h header file used when the library
+** was compiled. An HPI User may compare the returned value to the
+** SAHPI_INTERFACE_VERSION symbol in the SaHpi.h header file used by the
+** calling program to determine if the accessed library is compatible with the
+** calling program.
+**
+*******************************************************************************/
+SaHpiVersionT SAHPI_API saHpiVersionGet ( void );
+
+/*******************************************************************************
+**
+** Name: saHpiSessionOpen()
+**
+** Description:
+** This function opens an HPI session for a given domain and set of security
+** characteristics (future).
+**
+** Parameters:
+** DomainId - [in] Domain identifier of the domain to be accessed by the HPI
+** User. A domain identifier of SAHPI_UNSPECIFIED_DOMAIN_ID requests that
+** a session be opened to a default domain.
+** SessionId - [out] Pointer to a location to store an identifier for the
+** newly opened session. This identifier is used for subsequent access to
+** domain resources and events.
+** SecurityParams - [in] Pointer to security and permissions data structure.
+** This parameter is reserved for future use, and must be set to NULL.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_DOMAIN is returned if no domain matching the specified
+** domain identifier exists.
+** SA_ERR_HPI_INVALID_PARAMS is returned if:
+** * A non-null SecurityParams pointer is passed.
+** * The SessionId pointer is passed in as NULL.
+** SA_ERR_HPI_OUT_OF_SPACE is returned if no more sessions can be opened.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSessionOpen (
+ SAHPI_IN SaHpiDomainIdT DomainId,
+ SAHPI_OUT SaHpiSessionIdT *SessionId,
+ SAHPI_IN void *SecurityParams
+);
+
+/*******************************************************************************
+**
+** Name: saHpiSessionClose()
+**
+** Description:
+** This function closes an HPI session. After closing a session, the SessionId
+** will no longer be valid.
+**
+** Parameters:
+** SessionId - [in] Session identifier previously obtained using
+** saHpiSessionOpen().
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSessionClose (
+ SAHPI_IN SaHpiSessionIdT SessionId
+);
+
+/*******************************************************************************
+**
+** Name: saHpiDiscover()
+**
+** Description:
+** This function requests the underlying management service to discover
+** information about resources and associated domains.
+**
+** This function may be called during operation to update the DRT table and
+** the RPT table. An HPI implementation may exhibit latency between when
+** hardware changes occur and when the domain DRT and RPT are updated. To
+** overcome this latency, the saHpiDiscover() function may be called. When
+** this function returns, the DRT and RPT should be updated to reflect the
+** current system configuration and status.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained
+** using saHpiSessionOpen().
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiDiscover (
+ SAHPI_IN SaHpiSessionIdT SessionId
+);
+
+/*******************************************************************************
+**
+** Name: saHpiDomainInfoGet()
+**
+** Description:
+** This function is used for requesting information about the domain, the
+** Domain Reference Table (DRT), the Resource Presence Table (RPT), and the
+** Domain Alarm Table (DAT), such as table update counters and timestamps, and
+** the unique domain identifier associated with the domain.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained
+** using saHpiSessionOpen().
+** DomainInfo - [out] Pointer to the information describing the domain and
+** DRT.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the DomainInfo pointer is passed
+** in as NULL.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiDomainInfoGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_OUT SaHpiDomainInfoT *DomainInfo
+);
+
+/*******************************************************************************
+**
+** Name: saHpiDrtEntryGet()
+**
+** Description:
+** This function retrieves domain information for the specified entry of the
+** DRT. This function allows an HPI User to read the DRT entry-by-entry.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** EntryId - [in] Identifier of the DRT entry to retrieve. Reserved EntryId
+** values:
+** * SAHPI_FIRST_ENTRY Get first entry
+** * SAHPI_LAST_ENTRY Reserved as delimiter for end of list. Not a
+** valid entry identifier.
+** NextEntryId - [out] Pointer to location to store the EntryId of next entry
+** in DRT.
+** DrtEntry - [out] Pointer to the structure to hold the returned DRT entry.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_NOT_PRESENT is returned if the:
+** * Entry identified by EntryId is not present.
+** * EntryId is SAHPI_FIRST_ENTRY and the DRT is empty.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the:
+** * DrtEntry pointer is passed in as NULL.
+** * NextEntryId pointer is passed in as NULL.
+** * EntryId is an invalid reserved value such as SAHPI_LAST_ENTRY.
+**
+** Remarks:
+** If the EntryId parameter is set to SAHPI_FIRST_ENTRY, the first entry in
+** the DRT will be returned. When an entry is successfully retrieved,
+** NextEntryId will be set to the identifier of the next valid entry; however,
+** when the last entry has been retrieved, NextEntryId will be set to
+** SAHPI_LAST_ENTRY. To retrieve an entire list of entries, call this function
+** first with an EntryId of SAHPI_FIRST_ENTRY and then use the returned
+** NextEntryId in the next call. Proceed until the NextEntryId returned is
+** SAHPI_LAST_ENTRY.
+**
+** If an HPI User has not subscribed to receive events and a DRT entry is
+** added while the DRT is being read, that new entry may be missed. The
+** update counter provides a means for insuring that no domains are missed
+** when stepping through the DRT. In order to use this feature, an HPI User
+** should call saHpiDomainInfoGet() to get the update counter value before
+** retrieving the first DRT entry. After reading the last entry, the HPI User
+** should again call saHpiDomainInfoGet() to get the update counter value. If
+** the update counter has not been incremented, no new entries have been
+** added.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiDrtEntryGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiEntryIdT EntryId,
+ SAHPI_OUT SaHpiEntryIdT *NextEntryId,
+ SAHPI_OUT SaHpiDrtEntryT *DrtEntry
+);
+
+/*******************************************************************************
+**
+** Name: saHpiDomainTagSet()
+**
+** Description:
+** This function allows an HPI User to set a descriptive tag for a particular
+** domain. The domain tag is an informational value that supplies an HPI User
+** with naming information for the domain.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** DomainTag - [in] Pointer to SaHpiTextBufferT containing the domain tag.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the SaHpiTextBufferT structure
+** passed as DomainTag is not valid. This would occur when:
+** * The DataType is not one of the enumerated values for that type, or
+** * The data field contains characters that are not legal according to
+** the value of DataType, or
+** * The Language is not one of the enumerated values for that type when
+** the DataType is SAHPI_TL_TYPE_UNICODE or SAHPI_TL_TYPE_TEXT.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the DomainTag pointer is passed in
+** as NULL.
+**
+** Remarks:
+** Typically, the HPI implementation will provide an appropriate default value
+** for the domain tag; this function is provided so that an HPI User can
+** override the default, if desired. The value of the domain tag may be
+** retrieved from the domain's information structure.
+**
+** The domain tag is not necessarily persistent, and may return to its default
+** value if the domain controller function for the domain restarts.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiDomainTagSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiTextBufferT *DomainTag
+);
+
+/*******************************************************************************
+**
+** Name: saHpiRptEntryGet()
+**
+** Description:
+** This function retrieves resource information for the specified entry of the
+** resource presence table. This function allows an HPI User to read the RPT
+** entry-by-entry.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** EntryId - [in] Identifier of the RPT entry to retrieve. Reserved EntryId
+** values:
+** * SAHPI_FIRST_ENTRY Get first entry.
+** * SAHPI_LAST_ENTRY Reserved as delimiter for end of list. Not a
+** valid entry identifier.
+** NextEntryId - [out] Pointer to location to store the EntryId of next entry
+** in RPT.
+** RptEntry - [out] Pointer to the structure to hold the returned RPT entry.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_NOT_PRESENT is returned when the:
+** * Entry identified by EntryId is not present.
+** * EntryId is SAHPI_FIRST_ENTRY and the RPT is empty.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the:
+** * RptEntry pointer is passed in as NULL.
+** * NextEntryId pointer is passed in as NULL.
+** * EntryId is an invalid reserved value such as SAHPI_LAST_ENTRY.
+**
+** Remarks:
+** If the EntryId parameter is set to SAHPI_FIRST_ENTRY, the first entry in
+** the RPT will be returned. When an entry is successfully retrieved,
+** NextEntryId will be set to the identifier of the next valid entry; however,
+** when the last entry has been retrieved, NextEntryId will be set to
+** SAHPI_LAST_ENTRY. To retrieve an entire list of entries, call this function
+** first with an EntryId of SAHPI_FIRST_ENTRY and then use the returned
+** NextEntryId in the next call. Proceed until the NextEntryId returned is
+** SAHPI_LAST_ENTRY.
+**
+** At initialization, an HPI User may not wish to turn on eventing, since the
+** context of the events, as provided by the RPT, is not known. In this
+** instance, if a FRU is inserted into the system while the RPT is being read
+** entry by entry, the resource associated with that FRU may be missed. (Keep
+** in mind that there is no specified ordering for the RPT entries.) The
+** update counter provides a means for insuring that no resources are missed
+** when stepping through the RPT. In order to use this feature, an HPI User
+** should invoke saHpiDomainInfoGet(), and get the update counter value before
+** retrieving the first RPT entry. After reading the last entry, an HPI User
+** should again invoke the saHpiDomainInfoGet() to get the RPT update counter
+** value. If the update counter has not been incremented, no new records have
+** been added.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiRptEntryGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiEntryIdT EntryId,
+ SAHPI_OUT SaHpiEntryIdT *NextEntryId,
+ SAHPI_OUT SaHpiRptEntryT *RptEntry
+);
+
+/*******************************************************************************
+**
+** Name: saHpiRptEntryGetByResourceId()
+**
+** Description:
+** This function retrieves resource information from the resource presence
+** table for the specified resource using its ResourceId.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained
+** using saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** RptEntry - [out] Pointer to structure to hold the returned RPT entry.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the RptEntry pointer is passed
+** in as NULL.
+**
+** Remarks:
+** Typically at start-up, the RPT is read entry-by-entry, using
+** saHpiRptEntryGet(). From this, an HPI User can establish the set of
+** ResourceIds to use for future calls to the HPI functions.
+**
+** However, there may be other ways of learning ResourceIds without first
+** reading the RPT. For example, resources may be added to the domain while
+** the system is running in response to a hot swap action. When a resource is
+** added, the application will receive a hot swap event containing the
+** ResourceId of the new resource. The application may then want to search the
+** RPT for more detailed information on the newly added resource. In this
+** case, the ResourceId can be used to locate the applicable RPT entry
+** information.
+**
+** Note that saHpiRptEntryGetByResourceId() is valid in any hot swap state,
+** except for SAHPI_HS_STATE_NOT_PRESENT.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiRptEntryGetByResourceId (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiRptEntryT *RptEntry
+);
+
+/*******************************************************************************
+**
+** Name: saHpiResourceSeveritySet()
+**
+** Description:
+** This function allows an HPI User to set the severity level applied to an
+** event issued if a resource unexpectedly becomes unavailable to the HPI. A
+** resource may become unavailable for several reasons including:
+** * The FRU associated with the resource is no longer present in the
+** system (a surprise extraction has occurred.)
+** * A catastrophic failure has occurred.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** Severity - [in] Severity level of event issued when the resource
+** unexpectedly becomes unavailable to the HPI.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the value for Severity is not
+** one of the valid enumerated values for this type.
+**
+** Remarks:
+** Typically, the HPI implementation will provide an appropriate default value
+** for the resource severity, which may vary by resource; an HPI User can
+** override this default value by use of this function.
+**
+** If a resource is removed from, then re-added to the RPT (e.g., because of a
+** hot swap action), the HPI implementation may reset the value of the
+** resource severity.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceSeveritySet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSeverityT Severity
+);
+
+/*******************************************************************************
+**
+** Name: saHpiResourceTagSet()
+**
+** Description:
+** This function allows an HPI User to set the resource tag of an RPT entry
+** for a particular resource.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** ResourceTag - [in] Pointer to SaHpiTextBufferT containing the resource tag.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the SaHpiTextBufferT structure
+** passed as ResourceTag is not valid. This would occur when:
+** * The DataType is not one of the enumerated values for that type, or
+** * The data field contains characters that are not legal according to the
+** value of DataType, or
+** * The Language is not one of the enumerated values for that type when
+** the DataType is SAHPI_TL_TYPE_UNICODE or SAHPI_TL_TYPE_TEXT.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the ResourceTag pointer is passed
+** in as NULL.
+**
+** Remarks:
+** The resource tag is a data field within an RPT entry available to an HPI
+** User for associating application specific data with a resource. HPI User
+** supplied data is purely informational and is not used by the HPI
+** implementation, domain, or associated resource. For example, an HPI User
+** can set the resource tag to a "descriptive" value, which can be used to
+** identify the resource in messages to a human operator.
+**
+** Since the resource tag is contained within an RPT entry, its scope is
+** limited to a single domain. A resource that exists in more than one domain
+** will have independent resource tags within each domain.
+**
+** Typically, the HPI implementation will provide an appropriate default value
+** for the resource tag; this function is provided so that an HPI User can
+** override the default, if desired. The value of the resource tag may be
+** retrieved from the resource's RPT entry.
+**
+** If a resource is removed from, then re-added to the RPT (e.g., because of a
+** hot swap action), the HPI implementation may reset the value of the
+** resource tag.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceTagSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiTextBufferT *ResourceTag
+);
+
+/*******************************************************************************
+**
+** Name: saHpiResourceIdGet()
+**
+** Description:
+** This function returns the ResourceId of the resource associated with the
+** entity upon which the HPI User is running.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [out] Pointer to location to hold the returned ResourceId.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the ResourceId pointer is passed
+** in as NULL.
+** SA_ERR_HPI_NOT_PRESENT is returned if the entity the HPI User is running on
+** is not manageable in the addressed domain.
+** SA_ERR_HPI_UNKNOWN is returned if the domain controller cannot determine an
+** appropriate response. That is, there may be an appropriate ResourceId in
+** the domain to return, but it cannot be determined.
+**
+** Remarks:
+** This function must be issued within a session to a domain that includes a
+** resource associated with the entity upon which the HPI User is running, or
+** the SA_ERR_HPI_NOT_PRESENT return will be issued.
+**
+** Since entities are contained within other entities, there may be multiple
+** possible resources that could be returned to this call. For example, if
+** there is a ResourceId associated with a particular compute blade upon which
+** the HPI User is running, and another associated with the chassis which
+** contains the compute blade, either could logically be returned as an
+** indication of a resource associated with the entity upon which the HPI User
+** was running. The function should return the ResourceId of the "smallest"
+** resource that is associated with the HPI User. So, in the example above,
+** the function should return the ResourceId of the compute blade.
+**
+** Once the function has returned the ResourceId, the HPI User may issue
+** further HPI calls using that ResourceId to learn the type of resource that
+** been identified.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceIdGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_OUT SaHpiResourceIdT *ResourceId
+);
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogInfoGet()
+**
+** Description:
+** This function retrieves the current number of entries in the Event Log,
+** total size of the Event Log, the time of the most recent update to the
+** Event Log, the current value of the Event Log's clock (i.e., timestamp that
+** would be placed on an entry at this moment), the enabled/disabled status of
+** the Event Log (see Section 6.4.8 on page 57), the overflow flag, and the
+** action taken by the Event Log if an overflow occurs.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Identifier for the Resource containing the Event Log.
+** Set to SAHPI_UNSPECIFIED_RESOURCE_ID to address the Domain Event Log.
+** Info - [out] Pointer to the returned Event Log information.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not have an Event
+** Log capability (SAHPI_CAPABILITY_EVENT_LOG) set. Note this condition
+** only applies to Resource Event Logs. Domain Event Logs are mandatory,
+** and should not return this code.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the Info pointer is passed in as
+** NULL.
+**
+** Remarks:
+** The size field in the returned Event Log information indicates the maximum
+** number of entries that can be held in the Event Log. This number should be
+** constant for a particular Event Log.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogInfoGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiEventLogInfoT *Info
+);
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogEntryGet()
+**
+** Description:
+** This function retrieves an Event Log entry.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Identifier for the Resource containing the Event Log.
+** Set to SAHPI_UNSPECIFIED_RESOURCE_ID to address the Domain Event Log.
+** EntryId - [in] Identifier of event log entry to retrieve. Reserved values:
+** * SAHPI_OLDEST_ENTRY Oldest entry in the Event Log.
+** * SAHPI_NEWEST_ENTRY Newest entry in the Event Log.
+** * SAHPI_NO_MORE_ENTRIES Not valid for this parameter. Used only when
+** retrieving the next and previous EntryIds.
+** PrevEntryId - [out] Event Log entry identifier for the previous (older
+** adjacent) entry. Reserved values:
+** * SAHPI_OLDEST_ENTRY Not valid for this parameter. Used only for
+** the EntryId parameter.
+** * SAHPI_NEWEST_ENTRY Not valid for this parameter. Used only for
+** the EntryId parameter.
+** * SAHPI_NO_MORE_ENTRIES No more entries in the Event Log before the
+** one referenced by the EntryId parameter.
+** NextEntryId - [out] Event Log entry identifier for the next (newer
+** adjacent) entry. Reserved values:
+** * SAHPI_OLDEST_ENTRY Not valid for this parameter. Used only for
+** the EntryId parameter.
+** * SAHPI_NEWEST_ENTRY Not valid for this parameter. Used only for
+** the EntryId parameter.
+** * SAHPI_NO_MORE_ENTRIES No more entries in the Event Log after the one
+** referenced by the EntryId parameter.
+** EventLogEntry - [out] Pointer to retrieved Event Log entry.
+** Rdr - [in/out] Pointer to structure to receive resource data record
+** associated with the Event Log entry, if available. If NULL, no RDR data
+** will be returned.
+** RptEntry - [in/out] Pointer to structure to receive RPT entry associated
+** with the Event Log entry, if available. If NULL, no RPT entry data will
+** be returned.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not have an Event
+** Log capability (SAHPI_CAPABILITY_EVENT_LOG) set. Note this condition
+** only applies to Resource Event Logs. Domain Event Logs are mandatory,
+** and should not return this code.
+** SA_ERR_HPI_NOT_PRESENT is returned when:
+** * The Event Log has no entries.
+** * The entry identified by EntryId is not present.
+** SA_ERR_HPI_INVALID_PARAMS is returned when:
+** * Any of PrevEntryId, NextEntryId and EventLogEntry pointers are passed
+** in as NULL.
+** * SAHPI_NO_MORE_ENTRIES is passed in to EntryId.
+**
+** Remarks:
+** The special EntryIds SAHPI_OLDEST_ENTRY and SAHPI_NEWEST_ENTRY are used to
+** select the oldest and newest entries, respectively, in the Event Log being
+** read. A returned NextEntryId of SAHPI_NO_MORE_ENTRIES indicates that the
+** newest entry has been returned; there are no more entries going forward
+** (time-wise) in the Event Log. A returned PrevEntryId of
+** SAHPI_NO_MORE_ENTRIES indicates that the oldest entry has been returned.
+**
+** To retrieve an entire list of entries going forward (oldest entry to newest
+** entry) in the Event Log, call this function first with an EntryId of
+** SAHPI_OLDEST_ENTRY and then use the returned NextEntryId as the EntryId in
+** the next call. Proceed until the NextEntryId returned is
+** SAHPI_NO_MORE_ENTRIES.
+**
+** To retrieve an entire list of entries going backward (newest entry to
+** oldest entry) in the Event Log, call this function first with an EntryId of
+** SAHPI_NEWEST_ENTRY and then use the returned PrevEntryId as the EntryId in
+** the next call. Proceed until the PrevEntryId returned is
+** SAHPI_NO_MORE_ENTRIES.
+**
+** Event Logs may include RPT entries and resource data records associated
+** with the resource and sensor issuing an event along with the basic event
+** data in the Event Log. Because the system may be reconfigured after the
+** event was entered in the Event Log, this stored information may be
+** important to interpret the event. If the Event Log includes logged RPT
+** entries and/or RDRs, and if an HPI User provides a pointer to a structure
+** to receive this information, it will be returned along with the Event Log
+** entry.
+**
+** If an HPI User provides a pointer for an RPT entry, but the Event Log does
+** not include a logged RPT entry for the Event Log entry being returned,
+** RptEntry->ResourceCapabilities will be set to zero. No valid RptEntry will
+** have a zero Capabilities field value.
+**
+** If an HPI User provides a pointer for an RDR, but the Event Log does not
+** include a logged RDR for the Event Log entry being returned, Rdr->RdrType
+** will be set to SAHPI_NO_RECORD.
+**
+** The EntryIds returned via the PrevEntryId and NextEntryId parameters may
+** not be in sequential order, but will reflect the previous and next entries
+** in a chronological ordering of the Event Log, respectively.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogEntryGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiEventLogEntryIdT EntryId,
+ SAHPI_OUT SaHpiEventLogEntryIdT *PrevEntryId,
+ SAHPI_OUT SaHpiEventLogEntryIdT *NextEntryId,
+ SAHPI_OUT SaHpiEventLogEntryT *EventLogEntry,
+ SAHPI_INOUT SaHpiRdrT *Rdr,
+ SAHPI_INOUT SaHpiRptEntryT *RptEntry
+);
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogEntryAdd()
+**
+** Description:
+** This function enables an HPI user to add entries to the Event Log.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Identifier for the Resource containing the Event Log.
+** Set to SAHPI_UNSPECIFIED_RESOURCE_ID to address the Domain Event Log.
+** EvtEntry - [in] Pointer to event data to write to the Event Log. The Event
+** field must be of type SAHPI_ET_USER, and the Source field must be
+** SAHPI_UNSPECIFIED_RESOURCE_ID.
+**
+** Return Value:
+** SA_OK is returned if the event is successfully written in the Event Log;
+** otherwise, an error code is returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not have an Event
+** Log capability (SAHPI_CAPABILITY_EVENT_LOG) set. Note this condition
+** only applies to Resource Event Logs. Domain Event Logs are mandatory,
+** and should not return this code.
+** SA_ERR_HPI_INVALID_DATA is returned if the event DataLength is larger than
+** that supported by the implementation and reported in the Event Log info
+** record.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the:
+** * EvtEntry pointer is passed in as NULL.
+** * Event structure passed via the EvtEntry parameter is not an event of
+** type SAHPI_ET_USER with the Source field set to
+** SAHPI_UNSPECIFIED_RESOURCE_ID.
+** * The Severity is not one of the valid enumerated values for this type.
+** * SaHpiTextBufferT structure passed as part of the User Event structure
+** is not valid. This would occur when:
+** * The DataType is not one of the enumerated values for that type, or
+** * The data field contains characters that are not legal according to
+** the value of DataType, or
+** * The Language is not one of the enumerated values for that type when
+** the DataType is SAHPI_TL_TYPE_UNICODE or SAHPI_TL_TYPE_TEXT.
+** SA_ERR_HPI_OUT_OF_SPACE is returned if the event cannot be written to the
+** Event Log because the Event Log is full, and the Event Log
+** OverflowAction is SAHPI_EL_OVERFLOW_DROP.
+**
+** Remarks:
+** This function writes an event in the addressed Event Log. Nothing else is
+** done with the event.
+**
+** If the Event Log is full, overflow processing occurs as defined by the
+** Event Log's OverflowAction setting, reported in the Event Log info record.
+** If, due to an overflow condition, the event is not written, or if existing
+** events are overwritten, then the OverflowFlag in the Event Log info record
+** will be set, just as it would be if an internally generated event caused
+** an overflow condition. If the Event Log's OverflowAction is
+** SAHPI_EL_OVERFLOW_DROP, then an error will be returned
+** (SA_ERR_HPI_OUT_OF_SPACE) indicating that the saHpiEventLogEntryAdd()
+** function did not add the event to the Event Log. If the Event Log's
+** OverflowAction is SAHPI_EL_OVERFLOW_OVERWRITE, then the
+** saHpiEventLogEntryAdd() function will return SA_OK, indicating that the
+** event was added to the Event Log, even though an overflow occurred as a
+** side-effect of this operation. The overflow may be detected by checking
+** the OverflowFlag in the Event Log info record.
+**
+** Specific implementations of HPI may have restrictions on how much data may
+** be passed to the saHpiEventLogEntryAdd() function. The Event Log info
+** record reports the maximum DataLength that is supported by the Event Log
+** for User Events. If saHpiEventLogEntryAdd() is called with a User Event
+** that has a larger DataLength than is supported, the event will not be added
+** to the Event Log, and an error will be returned.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogEntryAdd (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiEventT *EvtEntry
+);
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogClear()
+**
+** Description:
+** This function erases the contents of the specified Event Log.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Identifier for the Resource containing the Event Log.
+** Set to SAHPI_UNSPECIFIED_RESOURCE_ID to address the Domain Event Log.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not have an Event
+** Log capability (SAHPI_CAPABILITY_EVENT_LOG) set. Note this condition
+** only applies to Resource Event Logs. Domain Event Logs are mandatory,
+** and should not return this code
+**
+** Remarks:
+** The OverflowFlag field in the Event Log info record will be reset when this
+** function is called.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogClear (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId
+);
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogTimeGet()
+**
+** Description:
+** This function retrieves the current time from the Event Log's clock. This
+** clock is used to timestamp entries written into the Event Log.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Identifier for the Resource containing the Event Log.
+** Set to SAHPI_UNSPECIFIED_RESOURCE_ID to address the Domain Event Log.
+** Time - [out] Pointer to the returned current Event Log time.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not have an Event
+** Log capability (SAHPI_CAPABILITY_EVENT_LOG) set. Note this condition
+** only applies to Resource Event Logs. Domain Event Logs are mandatory,
+** and should not return this code.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the Time pointer is passed in as
+** NULL.
+**
+** Remarks:
+** If the implementation cannot supply an absolute time value, then it may
+** supply a time relative to some system-defined epoch, such as system boot.
+** If the time value is less than or equal to SAHPI_TIME_MAX_RELATIVE, then it
+** is relative; if it is greater than SAHPI_TIME_MAX_RELATIVE, then it is
+** absolute. The HPI implementation must provide valid timestamps for Event
+** Log entries, using a default time base if no time has been set. Thus, the
+** value SAHPI_TIME_UNSPECIFIED is never returned.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogTimeGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiTimeT *Time
+);
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogTimeSet()
+**
+** Description:
+** This function sets the Event Log's clock, which is used to timestamp events
+** written into the Event Log.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Identifier for the Resource containing the Event Log.
+** Set to SAHPI_UNSPECIFIED_RESOURCE_ID to address the Domain Event Log.
+** Time - [in] Time to which the Event Log clock should be set.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not have an Event
+** Log capability (SAHPI_CAPABILITY_EVENT_LOG) set. Note this condition
+** only applies to Resource Event Logs. Domain Event Logs are mandatory,
+** and should not return this code.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the Time parameter is set to
+** SAHPI_TIME_UNSPECIFIED.
+** For situations when the underlying implementation cannot represent a time
+** value that is specified in Time, SA_ERR_HPI_INVALID_DATA is returned.
+**
+** Remarks:
+** If the Time parameter value is less than or equal to
+** SAHPI_TIME_MAX_RELATIVE, but not SAHPI_TIME_UNSPECIFIED, then it is
+** relative; if it is greater than SAHPI_TIME_MAX_RELATIVE, then it is
+** absolute. Setting this parameter to the value SAHPI_TIME_UNSPECIFIED is
+** invalid and will result in an error return code of
+** SA_ERR_HPI_INVALID_PARAMS.
+**
+** Entries placed in the Event Log after this function is called will have
+** Event Log timestamps (i.e., the Timestamp field in the SaHpiEventLogEntryT
+** structure) based on the new time. Setting the clock does not affect
+** existing Event Log entries. If the time is set to a relative time,
+** subsequent entries placed in the Event Log will have an Event Log timestamp
+** expressed as a relative time; if the time is set to an absolute time,
+** subsequent entries will have an Event Log timestamp expressed as an
+** absolute time.
+**
+** This function only sets the Event Log time clock and does not have any
+** direct bearing on the timestamps placed on events (i.e., the Timestamp
+** field in the SaHpiEventT structure), or the timestamps placed in the domain
+** RPT info record. Setting the clocks used to generate timestamps other than
+** Event Log timestamps is implementation-dependent, and should be documented
+** by the HPI implementation provider.
+**
+** Some underlying implementations may not be able to handle the same relative
+** and absolute time ranges, as those defined in HPI. Such limitations will
+** be documented. When a time value is set in a region that is not supported
+** by the implementation, an error code of SA_ERR_HPI_INVALID_DATA will be
+** returned.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogTimeSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiTimeT Time
+);
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogStateGet()
+**
+** Description:
+** This function enables an HPI User to get the Event Log state.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Identifier for the Resource containing the Event Log.
+** Set to SAHPI_UNSPECIFIED_RESOURCE_ID to address the Domain Event Log.
+** EnableState - [out] Pointer to the current Event Log enable state. True
+** indicates that the Event Log is enabled; False indicates that it is
+** disabled.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not have an Event
+** Log capability (SAHPI_CAPABILITY_EVENT_LOG) set. Note this condition
+** only applies to Resource Event Logs. Domain Event Logs are mandatory,
+** and should not return this code.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the EnableState pointer is passed
+** in as NULL.
+**
+** Remarks:
+** If the Event Log is disabled, no events generated within the HPI
+** implementation will be added to the Event Log. Events may still be added to
+** the Event Log with the saHpiEventLogEntryAdd() function. When the Event Log
+** is enabled, events may be automatically added to the Event Log as they are
+** generated in a resource or a domain, however, it is implementation-specific
+** which events are automatically added to any Event Log.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiBoolT *EnableState
+);
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogStateSet()
+**
+** Description:
+** This function enables an HPI User to set the Event Log enabled state.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Identifier for the Resource containing the Event Log.
+** Set to SAHPI_UNSPECIFIED_RESOURCE_ID to address the Domain Event Log.
+** EnableState - [in] Event Log state to be set. True indicates that the Event
+** Log is to be enabled; False indicates that it is to be disabled.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not have an Event
+** Log capability (SAHPI_CAPABILITY_EVENT_LOG) set. Note this condition
+** only applies to Resource Event Logs. Domain Event Logs are mandatory,
+** and should not return this code.
+**
+** Remarks:
+** If the Event Log is disabled no events generated within the HPI
+** implementation will be added to the Event Log. Events may still be added to
+** the Event Log using the saHpiEventLogEntryAdd() function. When the Event
+** Log is enabled events may be automatically added to the Event Log as they
+** are generated in a resource or a domain. The actual set of events that are
+** automatically added to any Event Log is implementation-specific.
+**
+** Typically, the HPI implementation will provide an appropriate default value
+** for this parameter, which may vary by resource. This function is provided
+** so that an HPI User can override the default, if desired.
+**
+** If a resource hosting an Event Log is re-initialized (e.g., because of a
+** hot swap action), the HPI implementation may reset the value of this
+** parameter.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogStateSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiBoolT EnableState
+);
+
+/*******************************************************************************
+**
+** Name: saHpiEventLogOverflowReset()
+**
+** Description:
+** This function resets the OverflowFlag in the Event Log info record of the
+** specified Event Log.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Identifier for the Resource containing the Event Log.
+** Set to SAHPI_UNSPECIFIED_RESOURCE_ID to address the Domain Event Log.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_CMD is returned if the implementation does not support
+** independent clearing of the OverflowFlag on this Event Log.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not have an Event
+** Log capability (SAHPI_CAPABILITY_EVENT_LOG) set. Note this condition
+** only applies to Resource Event Logs. Domain Event Logs are mandatory,
+** and should not return this code.
+**
+** Remarks:
+** The only effect of this function is to clear the OverflowFlag field in the
+** Event Log info record for the specified Event Log. If the Event Log is
+** still full, the OverflowFlag will be set again as soon as another entry
+** needs to be added to the Event Log.
+**
+** Some Event Log implementations may not allow resetting of the OverflowFlag
+** except as a by-product of clearing the entire Event Log with the
+** saHpiEventLogClear() function. Such an implementation will return the
+** error code, SA_ERR_HPI_INVALID_CMD to this function. The OverflowResetable
+** flag in the Event Log info record indicates whether or not the
+** implementation supports resetting the OverflowFlag without clearing the
+** Event Log.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventLogOverflowReset (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId
+);
+
+/*******************************************************************************
+**
+** Name: saHpiSubscribe()
+**
+** Description:
+** This function allows an HPI User to subscribe for events. This single call
+** provides subscription to all session events, regardless of event type or
+** event severity.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_DUPLICATE is returned when a subscription is already in place
+** for this session.
+**
+** Remarks:
+** Only one subscription is allowed per session, and additional subscribers
+** will receive an appropriate error code. No event filtering will be done by
+** the HPI implementation.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSubscribe (
+ SAHPI_IN SaHpiSessionIdT SessionId
+);
+
+/*******************************************************************************
+**
+** Name: saHpiUnsubscribe()
+**
+** Description:
+** This function removes the event subscription for the session.
+**
+** Parameters:
+** SessionId - [in] Session for which event subscription will be closed.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_REQUEST is returned if the session is not currently
+** subscribed for events.
+**
+** Remarks:
+** After removal of a subscription, additional saHpiEventGet() calls will not
+** be allowed on the session unless an HPI User re-subscribes for events on
+** the session first. Any events that are still in the event queue when this
+** function is called will be cleared from it.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiUnsubscribe (
+ SAHPI_IN SaHpiSessionIdT SessionId
+);
+
+/*******************************************************************************
+**
+** Name: saHpiEventGet()
+**
+** Description:
+** This function allows an HPI User to get an event. This call is only valid
+** within a session that has subscribed for events.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** Timeout - [in] The number of nanoseconds to wait for an event to arrive.
+** Reserved time out values:
+** * SAHPI_TIMEOUT_IMMEDIATE Time out immediately if there are no events
+** available (non-blocking call).
+** * SAHPI_TIMEOUT_BLOCK Call should not return until an event is
+** retrieved.
+** Event - [out] Pointer to the next available event.
+** Rdr - [in/out] Pointer to structure to receive the resource data associated
+** with the event. If NULL, no RDR will be returned.
+** RptEntry - [in/out] Pointer to structure to receive the RPT entry
+** associated with the resource that generated the event. If NULL, no RPT
+** entry will be returned.
+** EventQueueStatus - [in/out] Pointer to location to store event queue
+** status. If NULL, event queue status will not be returned.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_REQUEST is returned if an HPI User is not currently
+** subscribed for events in this session.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the:
+** * Event pointer is passed in as NULL.
+** * Timeout parameter is not set to SAHPI_TIMEOUT_BLOCK,
+** SAHPI_TIMEOUT_IMMEDIATE or a positive value.
+** SA_ERR_HPI_TIMEOUT is returned if no event is available to return within
+** the timeout period. If SAHPI_TIMEOUT_IMMEDIATE is passed in the
+** Timeout parameter, this error return will be used if there is no event
+** queued when the function is called.
+**
+** Remarks:
+** SaHpiEventGet() will also return an EventQueueStatus flag to an HPI User.
+** This flag indicates whether or not a queue overflow has occurred. The
+** overflow flag is set if any events were unable to be queued because of
+** space limitations in the interface implementation. The overflow flag is
+** reset whenever saHpiEventGet() is called.
+**
+** If there are one or more events on the event queue when this function is
+** called, it will immediately return the next event on the queue. Otherwise,
+** if the Timeout parameter is SAHPI_TIMEOUT_IMMEDIATE, it will return
+** SA_ERR_HPI_TIMEOUT immediately. Otherwise, it will block for time
+** specified by the timeout parameter; if an event is added to the queue
+** within that time it will be returned immediately; if not, saHpiEventGet()
+** will return SA_ERR_HPI_TIMEOUT. If the Timeout parameter is
+** SAHPI_TIMEOUT_BLOCK, the saHpiEventGet() will block indefinitely, until
+** an event becomes available, and then return that event. This provides for
+** notification of events as they occur.
+**
+** If an HPI User provides a pointer for an RPT entry, but the event does not
+** include a valid ResourceId for a resource in the domain (e.g., OEM or USER
+** type event), then the RptEntry->ResourceCapabilities field will be set to
+** zero. No valid RPT entry will have a zero ResourceCapabilities.
+**
+** If an HPI User provides a pointer for an RDR, but there is no valid RDR
+** associated with the event being returned (e.g., returned event is not a
+** sensor event), then the Rdr->RdrType field will be set to SAHPI_NO_RECORD.
+**
+** The timestamp reported in the returned event structure is the best
+** approximation an implementation has to when the event actually occurred.
+** The implementation may need to make an approximation (such as the time the
+** event was placed on the event queue) because it may not have access to the
+** actual time the event occurred. The value SAHPI_TIME_UNSPECIFIED indicates
+** that the time of the event cannot be determined.
+**
+** If the implementation cannot supply an absolute timestamp, then it may
+** supply a timestamp relative to some system-defined epoch, such as system
+** boot. If the timestamp value is less than or equal to
+** SAHPI_TIME_MAX_RELATIVE, but not SAHPI_TIME_UNSPECIFIED, then it is
+** relative; if it is greater than SAHPI_TIME_MAX_RELATIVE, then it is
+** absolute.
+**
+** If an HPI User passes a NULL pointer for the returned EventQueueStatus
+** pointer, the event status will not be returned, but the overflow flag, if
+** set, will still be reset. Thus, if an HPI User needs to know about event
+** queue overflows, the EventQueueStatus parameter should never be NULL, and
+** the overflow flag should be checked after every call to saHpiEventGet().
+**
+** If saHpiEventGet() is called with a timeout value other than
+** SAHPI_TIMEOUT_IMMEDIATE, and the session is subsequently closed from
+** another thread, this function will return with SA_ERR_HPI_INVALID_SESSION.
+** If saHpiEventGet() is called with a timeout value other than
+** SAHPI_TIMEOUT_IMMEDIATE, and an HPI User subsequently calls
+** saHpiUnsubscribe() from another thread, this function will return with
+** SA_ERR_HPI_INVALID_REQUEST.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiTimeoutT Timeout,
+ SAHPI_OUT SaHpiEventT *Event,
+ SAHPI_INOUT SaHpiRdrT *Rdr,
+ SAHPI_INOUT SaHpiRptEntryT *RptEntry,
+ SAHPI_INOUT SaHpiEvtQueueStatusT *EventQueueStatus
+);
+
+/*******************************************************************************
+**
+** Name: saHpiEventAdd()
+**
+** Description:
+** This function enables an HPI User to add events to the HPI domain
+** identified by the SessionId. The domain controller processes an event
+** added with this function as if the event originated from within the
+** domain. The domain controller will attempt to publish events to all active
+** event subscribers and will attempt to log events in the Domain Event Log,
+** if room is available.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** EvtEntry - [in] Pointer to event to add to the domain. Event must be of
+** type SAHPI_ET_USER, and the Source field must be
+** SAHPI_UNSPECIFIED_RESOURCE_ID.
+**
+** Return Value:
+** SA_OK is returned if the event is successfully added to the domain;
+** otherwise, an error code is returned.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the:
+** * EvtEntry parameter is NULL.
+** * Event structure passed via the EvtEntry parameter is not an event of
+** type SAHPI_ET_USER with the Source field being
+** SAHPI_UNSPECIFIED_RESOURCE_ID.
+** * Event structure passed via the EvtEntry parameter has an invalid
+** Severity.
+** * SaHpiTextBufferT structure passed as part of the User Event structure
+** is not valid. This would occur when:
+** * The DataType is not one of the enumerated values for that type, or
+** * The data field contains characters that are not legal according to
+** the value of DataType, or
+** * The Language is not one of the enumerated values for that type when
+** the DataType is SAHPI_TL_TYPE_UNICODE or SAHPI_TL_TYPE_TEXT.
+** SA_ERR_HPI_INVALID_DATA is returned if the event data does not meet
+** implementation-specific restrictions on how much event data may be
+** provided in a SAHPI_ET_USER event.
+**
+** Remarks:
+** Specific implementations of HPI may have restrictions on how much data may
+** be included in a SAHPI_ET_USER event. If more event data is provided than
+** can be processed, an error will be returned. The event data size
+** restriction for the SAHPI_ET_USER event type is provided in the
+** UserEventMaxSize field in the domain Event Log info structure. An HPI User
+** should call the function saHpiEventLogInfoGet() to retrieve the Event
+** Log info structure.
+**
+** The domain controller will attempt to publish the event to all sessions
+** within the domain with active event subscriptions; however, a session's
+** event queue may overflow due to the addition of the new event.
+**
+** The domain controller will attempt to log the event in the Domain Event
+** Log; however, the Domain Event Log may overflow due to the addition of the
+** new event
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiEventAdd (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiEventT *EvtEntry
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAlarmGetNext()
+**
+** Description:
+** This function allows retrieval of an alarm from the current set of alarms
+** held in the Domain Alarm Table (DAT).
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** Severity - [in] Severity level of alarms to retrieve. Set to
+** SAHPI_ALL_SEVERITIES to retrieve alarms of any severity; otherwise, set
+** to requested severity level.
+** UnacknowledgedOnly - [in] Set to True to indicate only unacknowledged
+** alarms should be returned. Set to False to indicate either an
+** acknowledged or unacknowledged alarm may be returned.
+** Alarm - [in/out] Pointer to the structure to hold the returned alarm entry.
+** Also, on input, Alarm->AlarmId and Alarm->Timestamp are used to
+** identify the previous alarm.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_PARAMS is returned when:
+** * Severity is not one of the valid enumerated values for this type.
+** * The Alarm parameter is passed in as NULL.
+** SA_ERR_HPI_NOT_PRESENT is returned:
+** * If there are no additional alarms in the DAT that meet the criteria
+** specified by the Severity and UnacknowledgedOnly parameters.
+** * If the passed Alarm->AlarmId field was set to SAHPI_FIRST_ENTRY and
+** there are no alarms in the DAT that meet the criteria specified by
+** the Severity and UnacknowledgedOnly parameters.
+** SA_ERR_HPI_INVALID_DATA is returned if the passed Alarm->AlarmId matches an
+** alarm in the DAT, but the passed Alarm->Timestamp does not match the
+** timestamp of that alarm.
+**
+** Remarks:
+** All alarms contained in the DAT are maintained in the order in which they
+** were added. This function will return the next alarm meeting the
+** specifications given by an HPI User that was added to the DAT after the
+** alarm whose AlarmId and Timestamp is passed by an HPI User, even if the
+** alarm associated with the AlarmId and Timestamp has been deleted. If
+** SAHPI_FIRST_ENTRY is passed as the AlarmId, the first alarm in the DAT
+** meeting the specifications given by an HPI User is returned.
+**
+** Alarm selection can be restricted to only alarms of a specified severity,
+** and/or only unacknowledged alarms.
+**
+** To retrieve all alarms contained within the DAT meeting specific
+** requirements, call saHpiAlarmGetNext() with the Alarm->AlarmId field set to
+** SAHPI_FIRST_ENTRY and the Severity and UnacknowledgedOnly parameters set to
+** select what alarms should be returned. Then, repeatedly call
+** saHpiAlarmGetNext() passing the previously returned alarm as the Alarm
+** parameter, and the same values for Severity and UnacknowledgedOnly until
+** the function returns with the error code SA_ERR_HPI_NOT_PRESENT.
+**
+** SAHPI_FIRST_ENTRY and SAHPI_LAST_ENTRY are reserved AlarmId values, and
+** will never be assigned to an alarm in the DAT.
+**
+** The elements AlarmId and Timestamp are used in the Alarm parameter to
+** identify the previous alarm; the next alarm added to the table after this
+** alarm that meets the Severity and UnacknowledgedOnly requirements will be
+** returned. Alarm->AlarmId may be set to SAHPI_FIRST_ENTRY to select the
+** first alarm in the DAT meeting the Severity and UnacknowledgedOnly
+** requirements. If Alarm->AlarmId is SAHPI_FIRST_ENTRY, then
+** Alarm->Timestamp is ignored.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAlarmGetNext(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiSeverityT Severity,
+ SAHPI_IN SaHpiBoolT UnacknowledgedOnly,
+ SAHPI_INOUT SaHpiAlarmT *Alarm
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAlarmGet()
+**
+** Description:
+** This function allows retrieval of a specific alarm in the Domain Alarm
+** Table (DAT) by referencing its AlarmId.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** AlarmId - [in] AlarmId of the alarm to be retrieved from the DAT.
+** Alarm - [out] Pointer to the structure to hold the returned alarm entry.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_NOT_PRESENT is returned if the requested AlarmId does not
+** correspond to an alarm contained in the DAT.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the Alarm parameter is passed in
+** as NULL.
+**
+** Remarks:
+** SAHPI_FIRST_ENTRY and SAHPI_LAST_ENTRY are reserved AlarmId values, and
+** will never be assigned to an alarm in the DAT.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAlarmGet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiAlarmIdT AlarmId,
+ SAHPI_OUT SaHpiAlarmT *Alarm
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAlarmAcknowledge()
+**
+** Description:
+** This function allows an HPI User to acknowledge a single alarm entry or a
+** group of alarm entries by severity.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** AlarmId - [in] Identifier of the alarm to be acknowledged. Reserved
+** AlarmId values:
+** * SAHPI_ENTRY_UNSPECIFIED Ignore this parameter.
+** Severity - [in] Severity level of alarms to acknowledge. Ignored unless
+** AlarmId is SAHPI_ENTRY_UNSPECIFIED.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_NOT_PRESENT is returned if an alarm entry identified by the
+** AlarmId parameter does not exist in the DAT.
+** SA_ERR_HPI_INVALID_PARAMS is returned if AlarmId is SAHPI_ENTRY_UNSPECIFIED
+** and Severity is not one of the valid enumerated values for this type.
+**
+** Remarks:
+** An HPI User acknowledges an alarm to indicate that it is aware of the alarm
+** and to influence platform-specific alarm annunciation that may be provided
+** by the implementation. Typically, an implementation ignores acknowledged
+** alarms when announcing an alarm on annunciation devices such as audible
+** sirens and dry contact closures. However, alarm annunciation is
+** implementation-specific.
+**
+** An acknowledged alarm will have the Acknowledged field in the alarm entry
+** set to True.
+**
+** Alarms are acknowledged by one of two ways: a single alarm entry by AlarmId
+** regardless of severity or as a group of alarm entries by Severity
+** regardless of AlarmId.
+**
+** To acknowledge all alarms contained within the DAT, set the Severity
+** parameter to SAHPI_ALL_SEVERITIES, and set the AlarmId parameter to
+** SAHPI_ENTRY_UNSPECIFIED.
+**
+** To acknowledge all alarms of a specific severity contained within the DAT,
+** set the Severity parameter to the appropriate value, and set the AlarmId
+** parameter to SAHPI_ENTRY_UNSPECIFIED.
+**
+** To acknowledge a single alarm entry, set the AlarmId parameter to a value
+** other than SAHPI_ENTRY_UNSPECIFIED. The AlarmId must be a valid identifier
+** for an alarm entry present in the DAT at the time of the function call.
+**
+** If an alarm has been previously acknowledged, acknowledging it again has no
+** effect. However, this is not an error.
+**
+** If the AlarmId parameter has a value other than SAHPI_ENTRY_UNSPECIFIED,
+** the Severity parameter is ignored.
+**
+** If the AlarmId parameter is passed as SAHPI_ENTRY_UNSPECIFIED, and no
+** alarms are present that meet the requested Severity, this function will
+** have no effect. However, this is not an error.
+**
+** SAHPI_ENTRY_UNSPECIFIED is defined as the same value as SAHPI_FIRST_ENTRY,
+** so using either symbol will have the same effect. However,
+** SAHPI_ENTRY_UNSPECIFIED should be used with this function for clarity.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAlarmAcknowledge(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiAlarmIdT AlarmId,
+ SAHPI_IN SaHpiSeverityT Severity
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAlarmAdd()
+**
+** Description:
+** This function is used to add a User Alarm to the DAT.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** Alarm - [in/out] Pointer to the alarm entry structure that contains the new
+** User Alarm to add to the DAT.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the Alarm pointer is passed in
+** as NULL.
+** SA_ERR_HPI_INVALID_PARAMS is returned when Alarm->Severity is not one of
+** the following enumerated values: SAHPI_MINOR, SAHPI_MAJOR, or
+** SAHPI_CRITICAL.
+** SA_ERR_HPI_INVALID_PARAMS is returned when Alarm->AlarmCond.Type is not
+** SAHPI_STATUS_COND_TYPE_USER.
+** SA_ERR_HPI_OUT_OF_SPACE is returned if the DAT is not able to add an
+** additional User Alarm due to space limits or limits imposed on the
+** number of User Alarms permitted in the DAT.
+**
+** Remarks:
+** The AlarmId, and Timestamp fields within the Alarm parameter are not used
+** by this function. Instead, on successful completion, these fields are set
+** to new values associated with the added alarm.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAlarmAdd(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_INOUT SaHpiAlarmT *Alarm
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAlarmDelete()
+**
+** Description:
+** This function allows an HPI User to delete a single User Alarm or a group
+** of User Alarms from the DAT. Alarms may be deleted individually by
+** specifying a specific AlarmId, or they may be deleted as a group by
+** specifying a Severity.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** AlarmId - [in] Alarm identifier of the alarm entry to delete. Reserved
+** values:
+** * SAHPI_ENTRY_UNSPECIFIED Ignore this parameter.
+** Severity - [in] Severity level of alarms to delete. Ignored unless AlarmId
+** is SAHPI_ENTRY_UNSPECIFIED.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_PARAMS is returned if AlarmId is SAHPI_ENTRY_UNSPECIFIED
+** and Severity is not one of the valid enumerated values for this type.
+** SA_ERR_HPI_NOT_PRESENT is returned if an alarm entry identified by the
+** AlarmId parameter does not exist in the DAT.
+** SA_ERR_HPI_READ_ONLY is returned if the AlarmId parameter indicates a
+** non-User Alarm.
+**
+** Remarks:
+** Only User Alarms added to the DAT can be deleted. When deleting alarms by
+** severity, only User Alarms of the requested severity will be deleted.
+**
+** To delete a single, specific alarm, set the AlarmId parameter to a value
+** representing an actual User Alarm in the DAT. The Severity parameter is
+** ignored when the AlarmId parameter is set to a value other than
+** SAHPI_ENTRY_UNSPECIFIED.
+**
+** To delete a group of User Alarms, set the AlarmId parameter to
+** SAHPI_ENTRY_UNSPECIFIED, and set the Severity parameter to identify which
+** severity of alarms should be deleted. To clear all User Alarms contained
+** within the DAT, set the Severity parameter to SAHPI_ALL_SEVERITIES.
+**
+** If the AlarmId parameter is passed as SAHPI_ENTRY_UNSPECIFIED, and no User
+** Alarms are present that meet the specified Severity, this function will
+** have no effect. However, this is not an error.
+**
+** SAHPI_ENTRY_UNSPECIFIED is defined as the same value as SAHPI_FIRST_ENTRY,
+** so using either symbol will have the same effect. However,
+** SAHPI_ENTRY_UNSPECIFIED should be used with this function for clarity.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAlarmDelete(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiAlarmIdT AlarmId,
+ SAHPI_IN SaHpiSeverityT Severity
+);
+
+/*******************************************************************************
+**
+** Name: saHpiRdrGet()
+**
+** Description:
+** This function returns a resource data record from the addressed resource.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** EntryId - [in] Identifier of the RDR entry to retrieve. Reserved EntryId
+** values:
+** * SAHPI_FIRST_ENTRY Get first entry.
+** * SAHPI_LAST_ENTRY Reserved as delimiter for end of list. Not a
+** valid entry identifier.
+** NextEntryId - [out] Pointer to location to store EntryId of next entry in
+** RDR repository.
+** Rdr - [out] Pointer to the structure to receive the requested resource data
+** record.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource contains no RDR records
+** (and thus does not have the SAHPI_CAPABILITY_RDR flag set in its RPT
+** entry).
+** SA_ERR_HPI_NOT_PRESENT is returned if an EntryId (other than
+** SAHPI_FIRST_ENTRY) is passed that does not correspond to an actual
+** EntryId in the resource's RDR repository.
+** SA_ERR_HPI_INVALID_PARAMS is returned if:
+** * SAHPI_LAST_ENTRY is passed in to EntryId.
+** * NextEntryId pointer is passed in as NULL.
+** * Rdr pointer is passed in as NULL.
+**
+** Remarks:
+** Submitting an EntryId of SAHPI_FIRST_ENTRY results in the first RDR being
+** read. A returned NextEntryId of SAHPI_LAST_ENTRY indicates the last RDR has
+** been returned. A successful retrieval will include the next valid EntryId.
+** To retrieve the entire list of RDRs, call this function first with an
+** EntryId of SAHPI_FIRST_ENTRY and then use the returned NextEntryId in the
+** next call. Proceed until the NextEntryId returned is SAHPI_LAST_ENTRY.
+**
+** A resource's RDR repository is static over the lifetime of the resource;
+** therefore no precautions are required against changes to the content of the
+** RDR repository while it is being accessed.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiRdrGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiEntryIdT EntryId,
+ SAHPI_OUT SaHpiEntryIdT *NextEntryId,
+ SAHPI_OUT SaHpiRdrT *Rdr
+);
+
+/*******************************************************************************
+**
+** Name: saHpiRdrGetByInstrumentId()
+**
+** Description:
+** This function returns the Resource Data Record (RDR) for a specific
+** management instrument hosted by the addressed resource.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** RdrType - [in] Type of RDR being requested.
+** InstrumentId - [in] Instrument number identifying the specific RDR to be
+** returned. This is a sensor number, control number, watchdog timer
+** number, IDR number, or annunciator number, depending on the value of
+** the RdrType parameter.
+** Rdr - [out] Pointer to the structure to receive the requested RDR.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the:
+** * Resource contains no RDR records (and thus does not have the
+** SAHPI_CAPABILITY_RDR flag set in its RPT entry).
+** * Type of management instrument specified in the RdrType parameter is
+** not supported by the resource, as indicated by the Capability field
+** in its RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the specific management instrument
+** identified in the InstrumentId parameter is not present in the addressed
+** resource.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the:
+** * RdrType parameter is not a valid enumerated value for the type.
+** * RdrType is SAHPI_NO_RECORD.
+** * Rdr pointer is passed in as NULL.
+**
+** Remarks:
+** The RDR to be returned is identified by RdrType (sensor, control, watchdog
+** timer, inventory data repository, or annunciator) and InstrumentId (sensor
+** number, control number, watchdog number, IDR number, or annunciator number)
+** for the specific management instrument for the RDR being requested.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiRdrGetByInstrumentId (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiRdrTypeT RdrType,
+ SAHPI_IN SaHpiInstrumentIdT InstrumentId,
+ SAHPI_OUT SaHpiRdrT *Rdr
+);
+
+/*******************************************************************************
+**
+** Name: saHpiSensorReadingGet()
+**
+** Description:
+** This function is used to retrieve a sensor reading.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** SensorNum - [in] Sensor number for which the sensor reading is being
+** retrieved.
+** Reading - [in/out] Pointer to a structure to receive sensor reading values
+** If NULL, the sensor reading value will not be returned.
+** EventState - [in/out] Pointer to location to receive sensor event states.
+** If NULL, the sensor event states will not be returned.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support sensors,
+** as indicated by SAHPI_CAPABILITY_SENSOR in the resource's RPT entry.
+** SA_ERR_HPI_INVALID_REQUEST is returned if the sensor is currently disabled.
+** SA_ERR_HPI_NOT_PRESENT is returned if the sensor is not present.
+**
+** Remarks:
+** For sensors that return a type of SAHPI_SENSOR_READING_TYPE_BUFFER, the
+** format of the returned data buffer is implementation-specific.
+**
+** If the sensor does not provide a reading, the Reading structure returned by
+** the saHpiSensorReadingGet() function will indicate the reading is not
+** supported by setting the IsSupported flag to False.
+**
+** If the sensor does not support any event states, a value of 0x0000 will be
+** returned for the EventState value. This is indistinguishable from the
+** return for a sensor that does support event states, but currently has no
+** event states asserted. The Sensor RDR Events field can be examined to
+** determine if the sensor supports any event states.
+**
+** It is legal for both the Reading parameter and the EventState parameter to
+** be NULL. In this case, no data is returned other than the return code.
+** This can be used to determine if a sensor is present and enabled without
+** actually returning current sensor data. If the sensor is present and
+** enabled, SA_OK is returned; otherwise, an error code is returned.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorReadingGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_INOUT SaHpiSensorReadingT *Reading,
+ SAHPI_INOUT SaHpiEventStateT *EventState
+);
+
+/*******************************************************************************
+**
+** Name: saHpiSensorThresholdsGet()
+**
+** Description:
+** This function retrieves the thresholds for the given sensor.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** SensorNum - [in] Sensor number for which threshold values are being
+** retrieved.
+** SensorThresholds - [out] Pointer to returned sensor thresholds.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support sensors,
+** as indicated by SAHPI_CAPABILITY_SENSOR in the resource's RPT entry.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the SensorThresholds pointer is
+** passed in as NULL.
+** SA_ERR_HPI_INVALID_CMD is returned if:
+** * Getting a threshold on a sensor that is not a threshold type.
+** * The sensor does not have any readable threshold values.
+** SA_ERR_HPI_NOT_PRESENT is returned if the sensor is not present.
+**
+** Remarks:
+** This function only applies to sensors that support readable thresholds, as
+** indicated by the IsAccessible field in the SaHpiSensorThdDefnT structure
+** of the sensor's RDR being set to True and the ReadThold field in the same
+** structure having a non-zero value.
+**
+** For thresholds that do not apply to the identified sensor, the IsSupported
+** flag of the threshold value field will be set to False.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorThresholdsGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_OUT SaHpiSensorThresholdsT *SensorThresholds
+);
+
+
+/*******************************************************************************
+**
+** Name: saHpiSensorThresholdsSet()
+**
+** Description:
+** This function sets the specified thresholds for the given sensor.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** SensorNum - [in] Sensor number for which threshold values are being set.
+** SensorThresholds - [in] Pointer to the sensor thresholds values being set.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_DATA is returned if any of the threshold values are
+** provided in a format not supported by the sensor.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support sensors,
+** as indicated by SAHPI_CAPABILITY_SENSOR in the resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the sensor is not present.
+** SA_ERR_HPI_INVALID_CMD is returned when:
+** * Writing to a threshold that is not writable.
+** * Setting a threshold on a sensor that is not a threshold type as
+** indicated by the IsAccessible field of the SaHpiSensorThdDefnT
+** structure.
+** * Setting a threshold outside of the Min-Max range as defined by the
+** Range field of the SensorDataFormat of the RDR.
+** SA_ERR_HPI_INVALID_DATA is returned when:
+** * Thresholds are set out-of-order (see Remarks).
+** * A negative hysteresis value is provided.
+**
+** Remarks:
+** This function only applies to sensors that support writable thresholds,
+** as indicated by the IsAccessible field in the SaHpiSensorThdDefnT
+** structure of the sensor's RDR being set to True and the WriteThold field
+** in the same structure having a non-zero value.
+**
+** The type of value provided for each threshold setting must correspond to
+** the reading format supported by the sensor, as defined by the reading type
+** in the DataFormat field of the sensor's RDR (saHpiSensorRecT).
+**
+** Sensor thresholds cannot be set outside of the range defined by the Range
+** field of the SensorDataFormat of the Sensor RDR. If SAHPI_SRF_MAX
+** indicates that a maximum reading exists, no sensor threshold may be set
+** greater than the Max value. If SAHPI_SRF_MIN indicates that a minimum
+** reading exists, no sensor threshold may be set less than the Min value.
+**
+** Thresholds are required to be set progressively in-order, so that
+** Upper Critical >= Upper Major >= Upper Minor >= Lower Minor >= Lower Major
+** >= Lower Critical.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorThresholdsSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_IN SaHpiSensorThresholdsT *SensorThresholds
+);
+
+/*******************************************************************************
+**
+** Name: saHpiSensorTypeGet()
+**
+** Description:
+** This function retrieves the sensor type and event category for the
+** specified sensor.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** SensorNum - [in] Sensor number for which the type is being retrieved.
+** Type - [out] Pointer to returned enumerated sensor type for the specified
+** sensor.
+** Category - [out] Pointer to location to receive the returned sensor event
+** category.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support sensors,
+** as indicated by SAHPI_CAPABILITY_SENSOR in the resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the sensor is not present.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the:
+** * Type pointer is passed in as NULL.
+** * Category pointer is passed in as NULL.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorTypeGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_OUT SaHpiSensorTypeT *Type,
+ SAHPI_OUT SaHpiEventCategoryT *Category
+);
+
+/*******************************************************************************
+**
+** Name: saHpiSensorEnableGet()
+**
+** Description:
+** This function returns the current sensor enable status for an addressed
+** sensor.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** SensorNum - [in] Sensor number for which the sensor enable status is being
+** requested.
+** SensorEnabled - [out] Pointer to the location to store the sensor enable
+** status.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support sensors,
+** as indicated by SAHPI_CAPABILITY_SENSOR in the resource's RPT entry.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the SensorEnabled pointer is set
+** to NULL.
+** SA_ERR_HPI_NOT_PRESENT is returned if the sensor is not present.
+**
+** Remarks:
+** The SaHpiBoolT value pointed to by the SensorEnabled parameter will be set
+** to True if the sensor is enabled, or False if the sensor is disabled.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorEnableGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_OUT SaHpiBoolT *SensorEnabled
+);
+
+/*******************************************************************************
+**
+** Name: saHpiSensorEnableSet()
+**
+** Description:
+** This function sets the sensor enable status for an addressed sensor.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** SensorNum - [in] Sensor number for which the sensor enable status is being
+** set.
+** SensorEnabled - [in] Sensor enable status to be set for the sensor.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support sensors,
+** as indicated by SAHPI_CAPABILITY_SENSOR in the resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the sensor is not present.
+** SA_ERR_HPI_READ_ONLY is returned if the sensor does not support changing
+** the enable status (i.e., the EnableCtrl field in the Sensor RDR is set
+** to False).
+**
+** Remarks:
+** If a sensor is disabled, any calls to saHpiSensorReadingGet() for that
+** sensor will return an error, and no events will be generated for the
+** sensor.
+**
+** Calling saHpiSensorEnableSet() with a SensorEnabled parameter of True
+** will enable the sensor. A SensorEnabled parameter of False will disable
+** the sensor.
+**
+** If the sensor enable status changes as the result of this function call,
+** an event will be generated.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorEnableSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_IN SaHpiBoolT SensorEnabled
+);
+
+/*******************************************************************************
+**
+** Name: saHpiSensorEventEnableGet()
+**
+** Description:
+** This function returns the current sensor event enable status for an
+** addressed sensor.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** SensorNum - [in] Sensor number for which the sensor event enable status is
+** being requested.
+** SensorEventsEnabled - [out] Pointer to the location to store the sensor
+** event enable status.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support sensors,
+** as indicated by SAHPI_CAPABILITY_SENSOR in the resource's RPT entry.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the SensorEventsEnabled pointer
+** is set to NULL.
+** SA_ERR_HPI_NOT_PRESENT is returned if the sensor is not present.
+**
+** Remarks:
+** The SaHpiBoolT value pointed to by the SensorEventsEnabled parameter will
+** be set to True if event generation for the sensor is enabled, or False if
+** event generation for the sensor is disabled.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorEventEnableGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_OUT SaHpiBoolT *SensorEventsEnabled
+);
+
+/*******************************************************************************
+**
+** Name: saHpiSensorEventEnableSet()
+**
+** Description:
+** This function sets the sensor event enable status for an addressed sensor.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** SensorNum - [in] Sensor number for which the sensor enable status is being
+** set.
+** SensorEventsEnabled - [in] Sensor event enable status to be set for the
+** sensor.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support sensors,
+** as indicated by SAHPI_CAPABILITY_SENSOR in the resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the sensor is not present.
+** SA_ERR_HPI_READ_ONLY is returned if the sensor does not support changing
+** the event enable status (i.e., the EventCtrl field in the Sensor RDR is
+** set to SAHPI_SEC_READ_ONLY).
+**
+** Remarks:
+** If event generation for a sensor is disabled, no events will be generated
+** as a result of the assertion or deassertion of any event state, regardless
+** of the setting of the assert or deassert event masks for the sensor. If
+** event generation for a sensor is enabled, events will be generated when
+** event states are asserted or deasserted, according to the settings of the
+** assert and deassert event masks for the sensor. Event states may still be
+** read for a sensor even if event generation is disabled, by using the
+** saHpiSensorReadingGet() function.
+**
+** Calling saHpiSensorEventEnableSet() with a SensorEventsEnabled parameter
+** of True will enable event generation for the sensor. A SensorEventsEnabled
+** parameter of False will disable event generation for the sensor.
+**
+** If the sensor event enabled status changes as a result of this function
+** call, an event will be generated.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorEventEnableSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_IN SaHpiBoolT SensorEventsEnabled
+);
+
+/*******************************************************************************
+**
+** Name: saHpiSensorEventMasksGet()
+**
+** Description:
+** This function returns the assert and deassert event masks for a sensor.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** SensorNum - [in] Sensor number for which the event enable configuration is
+** being requested.
+** AssertEventMask - [in/out] Pointer to location to store sensor assert event
+** mask. If NULL, assert event mask is not returned.
+** DeassertEventMask - [in/out] Pointer to location to store sensor deassert
+** event mask. If NULL, deassert event mask is not returned.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support
+** sensors, as indicated by SAHPI_CAPABILITY_SENSOR in the resource's RPT
+** entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the sensor is not present.
+**
+** Remarks:
+** Two bit-mask values are returned by the saHpiSensorEventMasksGet()
+** function; one for the sensor assert event mask, and one for the sensor
+** deassert event mask. A bit set to '1' in the AssertEventMask value
+** indicates that an event will be generated by the sensor when the
+** corresponding event state for that sensor changes from deasserted to
+** asserted. A bit set to '1' in the DeassertEventMask value indicates that
+** an event will be generated by the sensor when the corresponding event
+** state for that sensor changes from asserted to deasserted.
+**
+** Events will only be generated by the sensor if the appropriate
+** AssertEventMask or DeassertEventMask bit is set, sensor events are
+** enabled, and the sensor is enabled.
+**
+** For sensors hosted by resources that have the
+** SAHPI_CAPABILITY_EVT_DEASSERTS flag set in its RPT entry, the
+** AssertEventMask and the DeassertEventMask values will always be the same.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorEventMasksGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_INOUT SaHpiEventStateT *AssertEventMask,
+ SAHPI_INOUT SaHpiEventStateT *DeassertEventMask
+);
+
+/*******************************************************************************
+**
+** Name: saHpiSensorEventMasksSet()
+**
+** Description:
+** This function provides the ability to change the settings of the sensor
+** assert and deassert event masks. Two parameters contain bit-mask values
+** indicating which bits in the sensor assert and deassert event masks should
+** be updated. In addition, there is an Action parameter.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** SensorNum - [in] Sensor number for which the event enable configuration
+** is being set.
+** Action - [in] Enumerated value describing what change should be made to
+** the sensor event masks:
+** * SAHPI_SENS_ADD_EVENTS_TO_MASKS - for each bit set in the
+** AssertEventMask and DeassertEventMask parameters, set the
+** corresponding bit in the sensor's assert and deassert event masks,
+** respectively.
+** * SAHPI_SENS_REMOVE_EVENTS_FROM_MASKS - for each bit set in the
+** AssertEventMask and DeassertEventMask parameters, clear the
+** corresponding bit in the sensor's assert and deassert event masks,
+** respectively.
+** AssertEventMask - [in] Bit mask or special value indicating which bits in
+** the sensor's assert event mask should be set or cleared. (But see
+** Remarks concerning resources with the SAHPI_EVT_DEASSERTS_CAPABILITY
+** flag set.)
+** DeassertEventMask - [in] Bit mask or special value indicating which bits
+** in the sensor's deassert event mask should be set or cleared. (But see
+** Remarks concerning resources with the SAHPI_EVT_DEASSERTS_CAPABILITY
+** flag set.)
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support
+** sensors, as indicated by SAHPI_CAPABILITY_SENSOR in the resource's RPT
+** entry.
+** SA_ERR_HPI_INVALID_DATA is returned if the Action parameter is
+** SAHPI_SENS_ADD_EVENTS_TO_MASKS, and either of the AssertEventMask or
+** DeassertEventMask parameters include a bit for an event state that is
+** not supported by the sensor.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the Action parameter is out of
+** range.
+** SA_ERR_HPI_NOT_PRESENT is returned if the sensor is not present.
+** SA_ERR_HPI_READ_ONLY is returned if the sensor does not support updating
+** the assert and deassert event masks (i.e., the EventCtrl field in the
+** Sensor RDR is set to SAHPI_SEC_READ_ONLY_MASKS or SAHPI_SEC_READ_ONLY).
+**
+** Remarks:
+** The bits in the sensor assert and deassert event masks that correspond to
+** '1' bits in the bit-mask parameters will be set or cleared, as indicated
+** by the Action parameter. The bits in the sensor assert and deassert event
+** masks corresponding to '0' bits in the bit-mask parameters will be
+** unchanged.
+**
+** Assuming that a sensor is enabled and event generation for the sensor is
+** enabled, then for each bit set in the sensor's assert event mask, an event
+** will be generated when the sensor's corresponding event state changes from
+** deasserted to asserted. Similarly, for each bit set in the sensor's
+** deassert event mask, an event will be generated when the sensor's
+** corresponding event state changes from asserted to deasserted.
+**
+** For sensors hosted by a resource that has the
+** SAHPI_CAPABILITY_EVT_DEASSERTS flag set in its RPT entry, the assert and
+** deassert event masks cannot be independently configured. When
+** saHpiSensorEventMasksSet() is called for sensors in a resource with this
+** capability, the DeassertEventMask parameter is ignored, and the
+** AssertEventMask parameter is used to determine which bits to set or clear
+** in both the assert event mask and deassert event mask for the sensor.
+**
+** The AssertEventMask or DeassertEventMask parameter may be set to the
+** special value, SAHPI_ALL_EVENT_STATES, indicating that all event states
+** supported by the sensor should be added to or removed from, the
+** corresponding sensor event mask.
+**
+** If the sensor assert and/or deassert event masks change as a result of
+** this function call, an event will be generated.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiSensorEventMasksSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiSensorNumT SensorNum,
+ SAHPI_IN SaHpiSensorEventMaskActionT Action,
+ SAHPI_IN SaHpiEventStateT AssertEventMask,
+ SAHPI_IN SaHpiEventStateT DeassertEventMask
+);
+
+/*******************************************************************************
+**
+** Name: saHpiControlTypeGet()
+**
+** Description:
+** This function retrieves the control type of a control object.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** CtrlNum - [in] Control number for which the type is being retrieved.
+** Type - [out] Pointer to SaHpiCtrlTypeT variable to receive the enumerated
+** control type for the specified control.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support
+** controls, as indicated by SAHPI_CAPABILITY_CONTROL in the resource's
+** RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the control is not present.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the Type pointer is passed in as
+** NULL.
+**
+** Remarks:
+** The Type parameter must point to a variable of type SaHpiCtrlTypeT. Upon
+** successful completion, the enumerated control type is returned in the
+** variable pointed to by Type.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiControlTypeGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiCtrlNumT CtrlNum,
+ SAHPI_OUT SaHpiCtrlTypeT *Type
+);
+
+/*******************************************************************************
+**
+** Name: saHpiControlGet()
+**
+** Description:
+** This function retrieves the current state and mode of a control object.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** CtrlNum - [in] Control number for which the state and mode are being
+** retrieved.
+** CtrlMode - [out] Pointer to the mode of the control. If NULL, the
+** control's mode will not be returned.
+** CtrlState - [in/out] Pointer to a control data structure into which the
+** current control state will be placed. For text controls, the line
+** number to read is passed in via CtrlState->StateUnion.Text.Line.
+** If NULL, the control's state will not be returned.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_CMD is returned if the control is a write-only control,
+** as indicated by the WriteOnly flag in the control's RDR (see remarks).
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support
+** controls, as indicated by the SAHPI_CAPABILITY_CONTROL in the
+** resource's RPT entry.
+** SA_ERR_HPI_INVALID_DATA is returned if the addressed control is a text
+** control, and the line number passed in CtrlState->StateUnion.Text.Line
+** does not exist in the control and is not SAHPI_TLN_ALL_LINES.
+** SA_ERR_HPI_NOT_PRESENT is returned if the control is not present.
+**
+** Remarks:
+** Note that the CtrlState parameter is both an input and an output parameter
+** for this function. This is necessary to support line number inputs for
+** text controls, as discussed below.
+**
+** In some cases, the state of a control may be set, but the corresponding
+** state cannot be read at a later time. Such controls are delineated with
+** the WriteOnly flag in the Control's RDR.
+**
+** Note that text controls are unique in that they have a state associated
+** with each line of the control - the state being the text on that line. The
+** line number to be read is passed in to saHpiControlGet() via
+** CtrlState->StateUnion.Text.Line; the contents of that line of the control
+** will be returned in CtrlState->StateUnion.Text.Text. The first line of
+** the text control is line number "1".
+**
+** If the line number passed in is SAHPI_TLN_ALL_LINES, then
+** saHpiControlGet() will return the entire text of the control, or as much
+** of it as will fit in a single SaHpiTextBufferT, in
+** CtrlState->StateUnion.Text.Text. This value will consist of the text of
+** all the lines concatenated, using the maximum number of characters for
+** each line (no trimming of trailing blanks).
+**
+** Note that depending on the data type and language, the text may be encoded
+** in 2-byte Unicode, which requires two bytes of data per character.
+**
+** Note that the number of lines and columns in a text control can be
+** obtained from the control's Resource Data Record.
+**
+** Write-only controls allow the control's state to be set, but the control
+** state cannot be subsequently read. Such controls are indicated in the RDR,
+** when the WriteOnly flag is set. SA_ERR_HPI_INVALID_CMD is returned when
+** calling this function for a write-only control.
+**
+** It is legal for both the CtrlMode parameter and the CtrlState parameter to
+** be NULL. In this case, no data is returned other than the return code.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiControlGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiCtrlNumT CtrlNum,
+ SAHPI_OUT SaHpiCtrlModeT *CtrlMode,
+ SAHPI_INOUT SaHpiCtrlStateT *CtrlState
+);
+
+/*******************************************************************************
+**
+** Name: saHpiControlSet()
+**
+** Description:
+** This function is used for setting the state and/or mode of the specified
+** control object.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** CtrlNum - [in] Control number for which the state and/or mode is being set.
+** CtrlMode - [in] The mode to set on the control.
+** CtrlState - [in] Pointer to a control state data structure holding the
+** state to be set.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support
+** controls, as indicated by the SAHPI_CAPABILITY_CONTROL in the
+** resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the control is not present.
+** SA_ERR_HPI_INVALID_DATA is returned when the:
+** * CtrlState->Type field is not the correct type for the control
+** identified by the CtrlNum parameter.
+** * CtrlState->StateUnion.Analog is out of range of the control record's
+** analog Min and Max values.
+** * CtrlState->StateUnion.Text.Text.DataLength, combined with the
+** CtrlState->StateUnion.Text.Line, overflows the remaining text
+** control space.
+** * CtrlState->StateUnion.Text.Text.DataType is not set to the DataType
+** specified in the RDR.
+** * DataType specified in the RDR is SAHPI_TL_TYPE_UNICODE or
+** SAHPI_TL_TYPE_TEXT and CtrlState->StateUnion.Text.Text.Language is
+** not set to the Language specified in the RDR.
+** * OEM control data is invalid (see remarks below).
+** SA_ERR_HPI_INVALID_PARAMS is returned if the:
+** * CtrlMode is not one of the valid enumerated values for this type.
+** * CtrlMode parameter is not SAHPI_CTRL_MODE_AUTO and the CtrlState
+** pointer is passed in as NULL.
+** * CtrlState->StateUnion.Digital is not one of the valid enumerated
+** values for this type.
+** * CtrlState->StateUnion.Stream.StreamLength is bigger than
+** SAHPI_CTRL_MAX_STREAM_LENGTH.
+** * SaHpiTextBufferT structure passed as CtrlState->StateUnion.Text.Text
+** contains text characters that are not allowed according to the value
+** of CtrlState->StateUnion.Text.Text.DataType.
+** SA_ERR_HPI_INVALID_REQUEST is returned when SAHPI_CTRL_STATE_PULSE_ON is
+** issued to a digital control, which is ON (in either manual or auto
+** mode). It is also returned when SAHPI_CTRL_STATE_PULSE_OFF is issued
+** to a digital control, which is OFF (in either manual or auto mode).
+** SA_ERR_HPI_READ_ONLY is returned when attempting to change the mode of a
+** control with a read-only mode.
+**
+** Remarks:
+** When the mode is set to SAHPI_CTRL_MODE_AUTO, the state input is ignored.
+** Ignored state inputs are not checked by the implementation.
+**
+** The CtrlState parameter must be of the correct type for the specified
+** control.
+**
+** If the CtrlMode parameter is set to SAHPI_CTRL_MODE_AUTO, then the
+** CtrlState parameter is not evaluated, and may be set to any value by an
+** HPI User, including a NULL pointer. Text controls include a line number
+** and a line of text in the CtrlState parameter, allowing update of just a
+** single line of a text control. The first line of the text control is line
+** number "1". If less than a full line of data is written, the control will
+** clear all spaces beyond those written on the line. Thus writing a
+** zero-length string will clear the addressed line. It is also possible to
+** include more characters in the text passed in the CtrlState structure than
+** will fit on one line; in this case, the control will wrap to the next line
+** (still clearing the trailing characters on the last line written). Thus,
+** there are two ways to write multiple lines to a text control: (a) call
+** saHpiControlSet() repeatedly for each line, or (b) call saHpiControlSet()
+** once and send more characters than will fit on one line. An HPI User
+** should not assume any "cursor positioning" characters are available to
+** use, but rather should always write full lines and allow "wrapping" to
+** occur. When calling saHpiControlSet() for a text control, an HPI User may
+** set the line number to SAHPI_TLN_ALL_LINES; in this case, the entire
+** control will be cleared, and the data will be written starting on line 1.
+** (This is different from simply writing at line 1, which only alters the
+** lines written to.)
+**
+** This feature may be used to clear the entire control, which can be
+** accomplished by setting:
+** CtrlState->StateUnion.Text.Line = SAHPI_TLN_ALL_LINES;
+** CtrlState->StateUnion.Text.Text.DataLength = 0;
+**
+** Note that the number of lines and columns in a text control can be
+** obtained from the control's RDR.
+**
+** The ManufacturerId (MId) field of an OEM control is ignored by the
+** implementation when calling saHpiControlSet().
+**
+** On an OEM control, it is up to the implementation to determine what is
+** invalid data, and to return the specified error code.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiControlSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiCtrlNumT CtrlNum,
+ SAHPI_IN SaHpiCtrlModeT CtrlMode,
+ SAHPI_IN SaHpiCtrlStateT *CtrlState
+);
+
+/*******************************************************************************
+**
+** Name: saHpiIdrInfoGet()
+**
+** Description:
+** This function returns the Inventory Data Repository information including
+** the number of areas contained within the IDR and the update counter. The
+** Inventory Data Repository is associated with a specific entity.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** IdrId - [in] Identifier for the Inventory Data Repository.
+** IdrInfo - [out] Pointer to the information describing the requested
+** Inventory Data Repository.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support an
+** inventory data repository, as indicated by
+** SAHPI_CAPABILITY_INVENTORY_DATA in the resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the IDR is not present.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the IdrInfo pointer is passed in
+** as NULL.
+**
+** Remarks:
+** The update counter provides a means for insuring that no additions or
+** changes are missed when retrieving the IDR data. In order to use this
+** feature, an HPI User should invoke the saHpiIdrInfoGet(), and retrieve the
+** update counter value before retrieving the first Area. After retrieving
+** all Areas and Fields of the IDR, an HPI User should again invoke the
+** saHpiIdrInfoGet() to get the update counter value. If the update counter
+** value has not been incremented, no modification or additions were made to
+** the IDR during data retrieval.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiIdrInfoGet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiIdrIdT IdrId,
+ SAHPI_OUT SaHpiIdrInfoT *IdrInfo
+);
+
+/*******************************************************************************
+**
+** Name: saHpiIdrAreaHeaderGet()
+**
+** Description:
+** This function returns the Inventory Data Area header information for a
+** specific area associated with a particular Inventory Data Repository.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** IdrId - [in] Identifier for the Inventory Data Repository.
+** AreaType - [in] Type of Inventory Data Area.
+** AreaId - [in] Identifier of Area entry to retrieve from the IDR. Reserved
+** AreaId values:
+** * SAHPI_FIRST_ENTRY Get first entry.
+** * SAHPI_LAST_ENTRY Reserved as a delimiter for end of list. Not a
+** valid AreaId.
+** NextAreaId - [out] Pointer to location to store the AreaId of next area of
+** the requested type within the IDR.
+** Header - [out] Pointer to Inventory Data Area Header into which the header
+** information will be placed.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support an
+** inventory data repository, as indicated by
+** SAHPI_CAPABILITY_INVENTORY_DATA in the resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the:
+** * IDR is not present.
+** * AreaType parameter is set to SAHPI_IDR_AREATYPE_UNSPECIFIED, and the
+** area specified by the AreaId parameter does not exist in the IDR.
+** * AreaType parameter is set to a specific area type, but an area
+** matching both the AreaId parameter and AreaType parameter does not
+** exist.
+** SA_ERR_HPI_INVALID_PARAMS is returned if:
+** * AreaType is not one of the valid enumerated values for this type.
+** * The AreaId is an invalid reserved value such as SAHPI_LAST_ENTRY.
+** * The NextAreaId pointer is passed in as NULL.
+** * The Header pointer is passed in as NULL.
+**
+** Remarks:
+** This function allows retrieval of an Inventory Data Area Header by one of
+** two ways: by AreaId regardless of type or by AreaType and AreaId.
+**
+** To retrieve all areas contained within an IDR, set the AreaType parameter
+** to SAHPI_IDR_AREATYPE_UNSPECIFIED, and set the AreaId parameter to
+** SAHPI_FIRST_ENTRY for the first call. For each subsequent call, set the
+** AreaId parameter to the value returned in the NextAreaId parameter.
+** Continue calling this function until the NextAreaId parameter contains the
+** value SAHPI_LAST_ENTRY.
+**
+** To retrieve areas of specific type within an IDR, set the AreaType
+** parameter to a valid AreaType enumeration. Use the AreaId parameter in
+** the same manner described above to retrieve all areas of the specified
+** type. Set the AreaId parameter to SAHPI_FIRST_ENTRY to retrieve the first
+** area of that type. Use the value returned in NextAreaId to retrieve the
+** remaining areas of that type until SAHPI_LAST_ENTRY is returned.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiIdrAreaHeaderGet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiIdrIdT IdrId,
+ SAHPI_IN SaHpiIdrAreaTypeT AreaType,
+ SAHPI_IN SaHpiEntryIdT AreaId,
+ SAHPI_OUT SaHpiEntryIdT *NextAreaId,
+ SAHPI_OUT SaHpiIdrAreaHeaderT *Header
+);
+
+/*******************************************************************************
+**
+** Name: saHpiIdrAreaAdd()
+**
+** Description:
+** This function is used to add an Area to the specified Inventory Data
+** Repository.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** IdrId - [in] Identifier for the Inventory Data Repository.
+** AreaType - [in] Type of Area to add.
+** AreaId- [out] Pointer to location to store the AreaId of the newly created
+** area.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support an
+** inventory data repository, as indicated by
+** SAHPI_CAPABILITY_INVENTORY_DATA in the resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the IDR is not present.
+** SA_ERR_HPI_INVALID_DATA is returned when attempting to add an area with an
+** AreaType of SAHPI_IDR_AREATYPE_UNSPECIFIED or when adding an area that
+** does not meet the implementation-specific restrictions.
+** SA_ERR_HPI_OUT_OF_SPACE is returned if the IDR does not have enough free
+** space to allow the addition of the area.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the:
+** * AreaId pointer is passed in as NULL.
+** * AreaType is not one of the valid enumerated values for this type.
+** SA_ERR_HPI_READ_ONLY is returned if the IDR is read-only and does not
+** allow the addition of the area.
+**
+** Remarks:
+** On successful completion, the AreaId parameter will contain the AreaId of
+** the newly created area.
+**
+** On successful completion, the ReadOnly element in the new Area's header
+** will always be False.
+**
+** SAHPI_IDR_AREATYPE_UNSPECIFIED is not a valid area type, and should not be
+** used with this function. If SAHPI_IDR_AREATYPE_UNSPECIFIED is specified
+** as the area type, an error code of SA_ERR_HPI_INVALID_DATA is returned.
+** This area type is only valid when used with the saHpiIdrAreaHeaderGet()
+** function to retrieve areas of an unspecified type.
+**
+** Some implementations may restrict the types of areas that may be added.
+** These restrictions should be documented. SA_ERR_HPI_INVALID_DATA is
+** returned when attempting to add an invalid area type.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiIdrAreaAdd(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiIdrIdT IdrId,
+ SAHPI_IN SaHpiIdrAreaTypeT AreaType,
+ SAHPI_OUT SaHpiEntryIdT *AreaId
+);
+
+/*******************************************************************************
+**
+** Name: saHpiIdrAreaDelete()
+**
+** Description:
+** This function is used to delete an Inventory Data Area, including the Area
+** header and all fields contained with the area, from a particular Inventory
+** Data Repository.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** IdrId - [in] Identifier for the Inventory Data Repository.
+** AreaId - [in] Identifier of Area entry to delete from the IDR.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support an
+** inventory data repository, as indicated by
+** SAHPI_CAPABILITY_INVENTORY_DATA in the resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the:
+** * IDR is not present.
+** * Area identified by the AreaId parameter does not exist within the IDR.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the AreaId is an invalid
+** reserved value such as SAHPI_LAST_ENTRY.
+** SA_ERR_HPI_READ_ONLY is returned if the:
+** * IDA is read-only and therefore cannot be deleted.
+** * IDA contains a read-only Field and therefore cannot be deleted.
+** * IDR is read-only as deletions are not permitted for an area from a
+** read-only IDR.
+**
+** Remarks:
+** Deleting an Inventory Data Area also deletes all fields contained within
+** the area.
+**
+** In some implementations, certain Areas are intrinsically read-only. The
+** ReadOnly flag, in the area header, indicates if the Area is read-only.
+**
+** If the Inventory Data Area is not read-only, but contains a Field that is
+** read-only, the Area cannot be deleted. An attempt to delete an Area that
+** contains a read-only Field will return an error.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiIdrAreaDelete(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiIdrIdT IdrId,
+ SAHPI_IN SaHpiEntryIdT AreaId
+);
+
+/*******************************************************************************
+**
+** Name: saHpiIdrFieldGet()
+**
+** Description:
+** This function returns the Inventory Data Field information from a
+** particular Inventory Data Area and Repository.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** IdrId - [in] Identifier for the Inventory Data Repository.
+** AreaId - [in] Area identifier for the IDA.
+** FieldType - [in] Type of Inventory Data Field.
+** FieldId - [in] Identifier of Field to retrieve from the IDA. Reserved
+** FieldId values:
+** * SAHPI_FIRST_ENTRY Get first entry.
+** * SAHPI_LAST_ENTRY Reserved as a delimiter for end of list. Not
+** a valid FieldId.
+** NextFieldId - [out] Pointer to location to store the FieldId of next field
+** of the requested type in the IDA.
+** Field - [out] Pointer to Inventory Data Field into which the field
+** information will be placed.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support an
+** inventory data repository, as indicated by
+** SAHPI_CAPABILITY_INVENTORY_DATA in the resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the:
+** * IDR is not present.
+** * Area identified by AreaId is not present.
+** * FieldType parameter is set to SAHPI_IDR_FIELDTYPE_UNSPECIFIED, and
+** the field specified by the FieldId parameter does not exist in the
+** IDA.
+** * FieldType parameter is set to a specific field type, but a field
+** matching both the FieldId parameter and FieldType parameter does not
+** exist.
+** SA_ERR_HPI_INVALID_PARAMS is returned if:
+** * FieldType is not one of the valid enumerated values for this type.
+** * The AreaId or FieldId is an invalid reserved value such as
+** SAHPI_LAST_ENTRY.
+** * The NextFieldId pointer is passed in as NULL.
+** * The Field pointer is passed in as NULL.
+**
+** Remarks:
+** This function allows retrieval of an Inventory Data Field by one of two
+** ways: by FieldId regardless of type or by FieldType and FieldId.
+**
+** To retrieve all fields contained within an IDA, set the FieldType parameter
+** to SAHPI_IDR_FIELDTYPE_UNSPECIFIED, and set the FieldId parameter to
+** SAHPI_FIRST_ENTRY for the first call. For each subsequent call, set the
+** FieldId parameter to the value returned in the NextFieldId parameter.
+** Continue calling this function until the NextFieldId parameter contains the
+** value SAHPI_LAST_ENTRY.
+**
+** To retrieve fields of a specific type within an IDA, set the FieldType
+** parameter to a valid Field type enumeration. Use the FieldId parameter in
+** the same manner described above to retrieve all fields of the specified
+** type. Set the FieldId parameter to SAHPI_FIRST_ENTRY to retrieve the first
+** field of that type. Use the value returned in NextFieldId to retrieve the
+** remaining fields of that type until SAHPI_LAST_ENTRY is returned.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiIdrFieldGet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiIdrIdT IdrId,
+ SAHPI_IN SaHpiEntryIdT AreaId,
+ SAHPI_IN SaHpiIdrFieldTypeT FieldType,
+ SAHPI_IN SaHpiEntryIdT FieldId,
+ SAHPI_OUT SaHpiEntryIdT *NextFieldId,
+ SAHPI_OUT SaHpiIdrFieldT *Field
+);
+
+/*******************************************************************************
+**
+** Name: saHpiIdrFieldAdd()
+**
+** Description:
+** This function is used to add a field to the specified Inventory Data Area
+** with a specific Inventory Data Repository.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** IdrId - [in] Identifier for the Inventory Data Repository.
+** Field - [in/out] Pointer to Inventory Data Field, which contains the new
+** field information to add to the IDA.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support an
+** inventory data repository, as indicated by
+** SAHPI_CAPABILITY_INVENTORY_DATA in the resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the:
+** * IDR is not present.
+** * Area identified by Field?AreaId does not exist within the IDR.
+** SA_ERR_HPI_INVALID_DATA is returned if the Field data is incorrectly
+** formatted or does not meet the restrictions for the implementation.
+** SA_ERR_HPI_OUT_OF_SPACE is returned if the IDR does not have enough free
+** space to allow the addition of the field.
+** SA_ERR_HPI_READ_ONLY is returned if the:
+** * Area identified by Field?AreaId is read-only and does not allow
+** modification to its fields.
+** * IDR is identified by IdrId, is read-only, and does not allow
+** modification to its fields.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the:
+** * The Field type is not one of the valid field type enumerated values.
+** * Field type, Field?Type, is set to SAHPI_IDR_FIELDTYPE_UNSPECIFIED.
+** * SaHpiTextBufferT structure passed as part of the Field parameter is
+** not valid. This occurs when:
+** * The DataType is not one of the enumerated values for that type, or
+** * The data field contains characters that are not legal according to
+** the value of DataType, or
+** * The Language is not one of the enumerated values for that type
+** when the DataType is SAHPI_TL_TYPE_UNICODE or SAHPI_TL_TYPE_TEXT.
+** * Field pointer is passed in as NULL.
+**
+** Remarks:
+** The FieldId element within the Field parameter is not used by this
+** function. Instead, on successful completion, the FieldId field is set to
+** the new value associated with the added Field.
+**
+** The ReadOnly element in the Field parameter is not used by this function.
+** On successful completion, the ReadOnly element in the new Field will
+** always be False.
+**
+** Addition of a read-only Inventory Data Field is not allowed; therefore the
+** ReadOnly element in the SaHpiIdrFieldT parameter is ignored.
+**
+** SAHPI_IDR_FIELDTYPE_UNSPECIFIED is not a valid field type, and should not
+** be used with this function. If SAHPI_IDR_FIELDTYPE_UNSPECIFIED is
+** specified as the field type, an error code of SA_ERR_HPI_INVALID_DATA is
+** returned. This field type is only valid when used with the
+** saHpiIdrFieldGet() function to retrieve fields of an unspecified type.
+**
+** Some implementations have restrictions on what fields are valid in specific
+** areas and/or the data format of some fields. These restrictions should be
+** documented. SA_ERR_HPI_INVALID_DATA is returned when the field type or
+** field data does not meet the implementation-specific restrictions.
+**
+** The AreaId element within the Field parameter identifies the specific IDA
+** into which the new field is added.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiIdrFieldAdd(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiIdrIdT IdrId,
+ SAHPI_INOUT SaHpiIdrFieldT *Field
+);
+
+/*******************************************************************************
+**
+** Name: saHpiIdrFieldSet()
+**
+** Description:
+** This function is used to update an Inventory Data Field for a particular
+** Inventory Data Area and Repository.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** IdrId - [in] Identifier for the Inventory Data Repository.
+** Field - [in] Pointer to Inventory Data Field, which contains the updated
+** field information.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support an
+** inventory data repository, as indicated by
+** SAHPI_CAPABILITY_INVENTORY_DATA in the resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the:
+** * IDR is not present.
+** * Area identified by Field?AreaId does not exist within the IDR or if
+** the Field does not exist within the Inventory Data Area.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the:
+** * Field pointer is passed in as NULL.
+** * Field type, Field?Type, is not set to one of the valid field type
+** enumerated values.
+** * Field type, Field?Type, is set to SAHPI_IDR_FIELDTYPE_UNSPECIFIED.
+** SA_ERR_HPI_INVALID_DATA is returned if the field data is incorrectly
+** formatted or does not meet the restrictions for the implementation.
+** SA_ERR_HPI_OUT_OF_SPACE is returned if the IDR does not have enough free
+** space to allow the modification of the field due to an increase in the
+** field size.
+** SA_ERR_HPI_READ_ONLY is returned if the:
+** * Field is read-only and does not allow modifications.
+** * Area is read-only and does not allow modifications to its fields.
+** * IDR is read-only and does not allow modifications to its fields.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the SaHpiTextBufferT structure
+** passed as part of the Field parameter is not valid. This occurs when:
+** * The DataType is not one of the enumerated values for that type, or
+** * The data field contains characters that are not legal according to
+** the value of DataType, or
+** * The Language is not one of the enumerated values for that type when
+** the DataType is SAHPI_TL_TYPE_UNICODE or SAHPI_TL_TYPE_TEXT.
+**
+** Remarks:
+** This function allows modification of both the FieldType and Field data of
+** a given Inventory Data Field. This function does not allow modification of
+** the read-only attribute of the Inventory Data Field; therefore after a
+** successful update, the ReadOnly element in the updated Field will always be
+** False. The input value for ReadOnly is ignored.
+**
+** SAHPI_IDR_FIELDTYPE_UNSPECIFIED is not a valid field type, and should not
+** be used with this function. If SAHPI_IDR_FIELDTYPE_UNSPECIFIED is
+** specified as the new field type, an error code of SA_ERR_HPI_INVALID_DATA
+** is returned. This field type is only valid when used with the
+** saHpiIdrFieldGet() function to retrieve fields of an unspecified type.
+**
+** Some implementations have restrictions on what fields are valid in specific
+** areas and/or the data format of some fields. These restrictions should be
+** documented. SA_ERR_HPI_INVALID_DATA is returned when the field type or
+** field data does not meet the implementation-specific restrictions.
+**
+** In some implementations, certain Fields are intrinsically read-only. The
+** ReadOnly flag, in the field structure, indicates if the Field is read-only.
+**
+** The Field to update is identified by the AreaId and FieldId elements within
+** the Field parameter.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiIdrFieldSet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiIdrIdT IdrId,
+ SAHPI_IN SaHpiIdrFieldT *Field
+);
+
+/*******************************************************************************
+**
+** Name: saHpiIdrFieldDelete()
+**
+** Description:
+** This function is used to delete an Inventory Data Field from a particular
+** Inventory Data Area and Repository.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** IdrId - [in] Identifier for the Inventory Data Repository.
+** AreaId - [in] Area identifier for the IDA.
+** FieldId - [in] Identifier of Field to delete from the IDA.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support an
+** inventory data repository, as indicated by
+** SAHPI_CAPABILITY_INVENTORY_DATA in the resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the:
+** * IDR is not present.
+** * Area identified by the AreaId parameter does not exist within the IDR,
+** or if the Field identified by the FieldId parameter does not exist
+** within the IDA.
+** SA_ERR_HPI_READ_ONLY is returned if the field, the IDA, or the IDR is
+** read-only and does not allow deletion.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the AreaId or FieldId is an
+** invalid reserved value such as SAHPI_LAST_ENTRY.
+**
+** Remarks:
+** In some implementations, certain fields are intrinsically read-only. The
+** ReadOnly flag, in the field structure, indicates if the field is read-only.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiIdrFieldDelete(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiIdrIdT IdrId,
+ SAHPI_IN SaHpiEntryIdT AreaId,
+ SAHPI_IN SaHpiEntryIdT FieldId
+);
+
+/*******************************************************************************
+**
+** Name: saHpiWatchdogTimerGet()
+**
+** Description:
+** This function retrieves the current watchdog timer settings and
+** configuration.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** WatchdogNum - [in] Watchdog number that specifies the watchdog timer on a
+** resource.
+** Watchdog - [out] Pointer to watchdog data structure.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support a
+** watchdog timer, as indicated by SAHPI_CAPABILITY_WATCHDOG in the
+** resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the WatchdogNum is not present.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the Watchdog pointer is passed
+** in as NULL.
+**
+** Remarks:
+** See the description of the SaHpiWatchdogT structure in Section 8.11 on
+** page 180 for details on what information is returned by this function.
+**
+** When the watchdog action is SAHPI_WA_RESET, the type of reset (warm or
+** cold) is implementation-dependent.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiWatchdogTimerGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiWatchdogNumT WatchdogNum,
+ SAHPI_OUT SaHpiWatchdogT *Watchdog
+);
+
+/*******************************************************************************
+**
+** Name: saHpiWatchdogTimerSet()
+**
+** Description:
+** This function provides a method for initializing the watchdog timer
+** configuration.
+**
+** Once the appropriate configuration has been set using
+** saHpiWatchdogTimerSet(), an HPI User must then call
+** saHpiWatchdogTimerReset() to initially start the watchdog timer, unless
+** the watchdog timer was already running prior to calling
+** saHpiWatchdogTimerSet() and the Running field in the passed Watchdog
+** structure is True.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** WatchdogNum - [in] The watchdog number specifying the specific watchdog
+** timer on a resource.
+** Watchdog - [in] Pointer to watchdog data structure.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support a
+** watchdog timer, as indicated by SAHPI_CAPABILITY_WATCHDOG in the
+** resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the WatchdogNum is not present.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the:
+** * Watchdog->TimerUse is not one of the valid enumerated values for this
+** type.
+** * Watchdog->TimerAction is not one of the valid enumerated values for
+** this type.
+** * Watchdog->PretimerInterrupt is not one of the valid enumerated values
+** for this type.
+** * Watchdog pointer is passed in as NULL.
+** SA_ERR_HPI_INVALID_DATA is returned when the:
+** * Watchdog->PreTimeoutInterval is outside the acceptable range for the
+** implementation.
+** * Watchdog->InitialCount is outside the acceptable range for the
+** implementation.
+** * Value of Watchdog->PreTimeoutInterval is greater than the value of
+** Watchdog->InitialCount.
+** * Watchdog->PretimerInterrupt is set to an unsupported value. See
+** remarks.
+** * Watchdog->TimerAction is set to an unsupported value. See remarks.
+** * Watchdog->TimerUse is set to an unsupported value. See remarks.
+**
+** Remarks:
+** Configuring the watchdog timer with the saHpiWatchdogTimerSet() function
+** does not start the timer running. If the timer was previously stopped
+** when this function is called, then it will remain stopped, and must be
+** started by calling saHpiWatchdogTimerReset(). If the timer was previously
+** running, then it will continue to run if the Watchdog->Running field passed
+** is True, or will be stopped if the Watchdog->Running field passed is False.
+** If it continues to run, it will restart its count-down from the newly
+** configured initial count value.
+**
+** If the initial counter value is set to 0, then any configured pre-timer
+** interrupt action or watchdog timer expiration action will be taken
+** immediately when the watchdog timer is started. This provides a mechanism
+** for software to force an immediate recovery action should that be dependent
+** on a Watchdog timeout occurring.
+**
+** See the description of the SaHpiWatchdogT structure for more details on the
+** effects of this command related to specific data passed in that structure.
+**
+** Some implementations impose a limit on the acceptable ranges for the
+** PreTimeoutInterval or InitialCount. These limitations must be documented.
+** SA_ERR_HPI_INVALID_DATA is returned if an attempt is made to set a value
+** outside of the supported range.
+**
+** Some implementations cannot accept all of the enumerated values for
+** TimerUse, TimerAction, or PretimerInterrupt. These restrictions should be
+** documented. SA_ERR_HPI_INVALID_DATA is returned if an attempt is made to
+** select an unsupported option.
+**
+** When the watchdog action is set to SAHPI_WA_RESET, the type of reset (warm
+** or cold) is implementation-dependent.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiWatchdogTimerSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiWatchdogNumT WatchdogNum,
+ SAHPI_IN SaHpiWatchdogT *Watchdog
+);
+
+/*******************************************************************************
+**
+** Name: saHpiWatchdogTimerReset()
+**
+** Description:
+** This function provides a method to start or restart the watchdog timer from
+** the initial countdown value.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** WatchdogNum - [in] The watchdog number specifying the specific watchdog
+** timer on a resource.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support a
+** watchdog timer, as indicated by SAHPI_CAPABILITY_WATCHDOG in the
+** resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the WatchdogNum is not present.
+** SA_ERR_HPI_INVALID_REQUEST is returned if the current watchdog state does
+** not allow a reset.
+**
+** Remarks:
+** If the Watchdog has been configured to issue a Pre-Timeout interrupt, and
+** that interrupt has already occurred, the saHpiWatchdogTimerReset() function
+** will not reset the watchdog counter. The only way to stop a Watchdog from
+** timing out once a Pre-Timeout interrupt has occurred is to use the
+** saHpiWatchdogTimerSet() function to reset and/or stop the timer.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiWatchdogTimerReset (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiWatchdogNumT WatchdogNum
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAnnunciatorGetNext()
+**
+** Description:
+** This function allows retrieval of an announcement from the current set of
+** announcements held in the Annunciator.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** AnnunciatorNum - [in] Annunciator number for the addressed Annunciator.
+** Severity - [in] Severity level of announcements to retrieve. Set to
+** SAHPI_ALL_SEVERITIES to retrieve announcement of any severity;
+** otherwise, set to requested severity level.
+** UnacknowledgedOnly - [in] Set to True to indicate only unacknowledged
+** announcements should be returned. Set to False to indicate either an
+** acknowledged or unacknowledged announcement may be returned.
+** Announcement - [in/out] Pointer to the structure to hold the returned
+** announcement. Also, on input, Announcement->EntryId and
+** Announcement->Timestamp are used to identify the "previous"
+** announcement.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support
+** Annunciators, as indicated by SAHPI_CAPABILITY_ANNUNCIATOR in the
+** resource's RPT entry.
+** SA_ERR_HPI_INVALID_PARAMS is returned when Severity is not one of the
+** valid enumerated values for this type.
+** SA_ERR_HPI_NOT_PRESENT is returned if:
+** * The AnnunciatorNum passed does not address a valid Annunciator
+** supported by the resource.
+** * There are no announcements (or no unacknowledged announcements if
+** UnacknowledgedOnly is True) that meet the specified Severity in the
+** current set after the announcement identified by
+** Announcement->EntryId and Announcement->Timestamp.
+** * There are no announcements (or no unacknowledged announcements if
+** UnacknowledgedOnly is True) that meet the specified Severity in the
+** current set if the passed Announcement->EntryId field was set to
+** SAHPI_FIRST_ENTRY.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the Announcement parameter is
+** passed in as NULL.
+** SA_ERR_HPI_INVALID_DATA is returned if the passed Announcement->EntryId
+** matches an announcement in the current set, but the passed
+** Announcement->Timestamp does not match the timestamp of that announcement.
+**
+** Remarks:
+** All announcements contained in the set are maintained in the order in which
+** they were added. This function will return the next announcement meeting
+** the specifications given by an HPI User that was added to the set after the
+** announcement whose EntryId and timestamp is passed by an HPI User. If
+** SAHPI_FIRST_ENTRY is passed as the EntryId, the first announcement in the
+** set meeting the specifications given by an HPI User is returned. This
+** function should operate even if the announcement associated with the
+** EntryId and Timestamp passed by an HPI User has been deleted.
+**
+** Selection can be restricted to only announcements of a specified severity,
+** and/or only unacknowledged announcements. To retrieve all announcements
+** contained meeting specific requirements, call saHpiAnnunciatorGetNext()
+** with the Status->EntryId field set to SAHPI_FIRST_ENTRY and the Severity
+** and UnacknowledgedOnly parameters set to select what announcements should
+** be returned. Then, repeatedly call saHpiAnnunciatorGetNext() passing the
+** previously returned announcement as the Announcement parameter, and the
+** same values for Severity and UnacknowledgedOnly until the function returns
+** with the error code SA_ERR_HPI_NOT_PRESENT.
+**
+** SAHPI_FIRST_ENTRY and SAHPI_LAST_ENTRY are reserved EntryId values, and
+** will never be assigned to an announcement.
+**
+** The elements EntryId and Timestamp are used in the Announcement parameter
+** to identify the "previous" announcement; the next announcement added to the
+** table after this announcement that meets the Severity and
+** UnacknowledgedOnly requirements will be returned. Announcement->EntryId
+** may be set to SAHPI_FIRST_ENTRY to select the first announcement in the
+** current set meeting the Severity and UnacknowledgedOnly requirements. If
+** Announcement->EntryId is SAHPI_FIRST_ENTRY, then Announcement->Timestamp
+** is ignored.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAnnunciatorGetNext(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiAnnunciatorNumT AnnunciatorNum,
+ SAHPI_IN SaHpiSeverityT Severity,
+ SAHPI_IN SaHpiBoolT UnacknowledgedOnly,
+ SAHPI_INOUT SaHpiAnnouncementT *Announcement
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAnnunciatorGet()
+**
+** Description:
+** This function allows retrieval of a specific announcement in the
+** Annunciator's current set by referencing its EntryId.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained
+** using saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** AnnunciatorNum - [in] Annunciator number for the addressed Annunciator.
+** EntryId - [in] Identifier of the announcement to retrieve from the
+** Annunciator.
+** Announcement - [out] Pointer to the structure to hold the returned
+** announcement.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support
+** Annunciators, as indicated by SAHPI_CAPABILITY_ANNUNCIATOR in the
+** resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if:
+** * The AnnunciatorNum passed does not address a valid Annunciator
+** supported by the resource.
+** * The requested EntryId does not correspond to an announcement
+** contained in the Annunciator.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the Announcement parameter is
+** passed in as NULL.
+**
+** Remarks:
+** SAHPI_FIRST_ENTRY and SAHPI_LAST_ENTRY are reserved EntryId values, and
+** will never be assigned to announcements.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAnnunciatorGet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiAnnunciatorNumT AnnunciatorNum,
+ SAHPI_IN SaHpiEntryIdT EntryId,
+ SAHPI_OUT SaHpiAnnouncementT *Announcement
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAnnunciatorAcknowledge()
+**
+** Description:
+** This function allows an HPI User to acknowledge a single announcement or a
+** group of announcements by severity.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** AnnunciatorNum - [in] Annunciator number for the addressed Annunciator.
+** EntryId - [in] Entry identifier of the announcement to acknowledge.
+** Reserved EntryId values:
+** * SAHPI_ENTRY_UNSPECIFIED Ignore this parameter.
+** Severity - [in] Severity level of announcements to acknowledge. Ignored
+** unless EntryId is SAHPI_ENTRY_UNSPECIFIED.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support
+** Annunciators, as indicated by SAHPI_CAPABILITY_ANNUNCIATOR in the
+** resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if:
+** * The AnnunciatorNum passed does not address a valid Annunciator
+** supported by the resource.
+** * An announcement identified by the EntryId parameter does not exist in
+** the current set.
+** SA_ERR_HPI_INVALID_PARAMS is returned if EntryId is SAHPI_ENTRY_UNSPECIFIED
+** and Severity is not one of the valid enumerated values for this type.
+**
+** Remarks:
+** Announcements are acknowledged by one of two ways: a single announcement
+** by EntryId regardless of severity or as a group of announcements by
+** severity regardless of EntryId.
+**
+** An HPI User acknowledges an announcement to influence the platform-specific
+** annunciation provided by the Annunciator management instrument.
+**
+** An acknowledged announcement will have the Acknowledged field set to True.
+**
+** To acknowledge all announcements contained within the current set, set the
+** Severity parameter to SAHPI_ALL_SEVERITIES, and set the EntryId parameter
+** to SAHPI_ENTRY_UNSPECIFIED.
+**
+** To acknowledge all announcements of a specific severity, set the Severity
+** parameter to the appropriate value, and set the EntryId parameter to
+** SAHPI_ENTRY_UNSPECIFIED.
+**
+** To acknowledge a single announcement, set the EntryId parameter to a value
+** other than SAHPI_ENTRY_UNSPECIFIED. The EntryId must be a valid identifier
+** for an announcement present in the current set.
+**
+** If an announcement has been previously acknowledged, acknowledging it again
+** has no effect. However, this is not an error.
+**
+** If the EntryId parameter has a value other than SAHPI_ENTRY_UNSPECIFIED,
+** the Severity parameter is ignored.
+**
+** If the EntryId parameter is passed as SAHPI_ENTRY_UNSPECIFIED, and no
+** announcements are present that meet the requested Severity, this function
+** will have no effect. However, this is not an error.
+**
+** SAHPI_ENTRY_UNSPECIFIED is defined as the same value as SAHPI_FIRST_ENTRY,
+** so using either symbol will have the same effect. However,
+** SAHPI_ENTRY_UNSPECIFIED should be used with this function for clarity.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAnnunciatorAcknowledge(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiAnnunciatorNumT AnnunciatorNum,
+ SAHPI_IN SaHpiEntryIdT EntryId,
+ SAHPI_IN SaHpiSeverityT Severity
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAnnunciatorAdd()
+**
+** Description:
+** This function is used to add an announcement to the set of items held by an
+** Annunciator management instrument.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** AnnunciatorNum - [in] Annunciator number for the addressed Annunciator.
+** Announcement - [in/out] Pointer to structure that contains the new
+** announcement to add to the set.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support
+** Annunciators, as indicated by SAHPI_CAPABILITY_ANNUNCIATOR in the
+** resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the AnnunciatorNum passed does not
+** address a valid Annunciator supported by the resource.
+** SA_ERR_HPI_INVALID_PARAMS is returned when:
+** * The Announcement pointer is passed in as NULL.
+** * The Announcement->Severity passed is not valid.
+** * The Announcement->StatusCond structure passed in is not valid.
+** SA_ERR_HPI_OUT_OF_SPACE is returned if the Annunciator is not able to add
+** an additional announcement due to resource limits.
+** SA_ERR_HPI_READ_ONLY is returned if the Annunciator is in auto mode.
+**
+** Remarks:
+** The EntryId, Timestamp, and AddedByUser fields within the Announcement
+** parameter are not used by this function. Instead, on successful
+** completion, these fields are set to new values associated with the added
+** announcement. AddedByUser will always be set to True.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAnnunciatorAdd(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiAnnunciatorNumT AnnunciatorNum,
+ SAHPI_INOUT SaHpiAnnouncementT *Announcement
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAnnunciatorDelete()
+**
+** Description:
+** This function allows an HPI User to delete a single announcement or a group
+** of announcements from the current set of an Annunciator. Announcements may
+** be deleted individually by specifying a specific EntryId, or they may be
+** deleted as a group by specifying a severity.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** AnnunciatorNum - [in] Annunciator number for the addressed Annunciator.
+** EntryId - [in] Entry identifier of the announcement to delete. Reserved
+** EntryId values:
+** * SAHPI_ENTRY_UNSPECIFIED Ignore this parameter.
+** Severity - [in] Severity level of announcements to delete. Ignored unless
+** EntryId is SAHPI_ENTRY_UNSPECIFIED.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support
+** Annunciators, as indicated by SAHPI_CAPABILITY_ANNUNCIATOR in the
+** resource's RPT entry.
+** SA_ERR_HPI_INVALID_PARAMS is returned if EntryId is SAHPI_ENTRY_UNSPECIFIED
+** and Severity is not one of the valid enumerated values for this type.
+** SA_ERR_HPI_NOT_PRESENT is returned if:
+** * The AnnunciatorNum passed does not address a valid Annunciator
+** supported by the resource
+** * An announcement identified by the EntryId parameter does not exist in
+** the current set of the Annunciator.
+** SA_ERR_HPI_READ_ONLY is returned if the Annunciator is in auto mode.
+**
+** Remarks:
+** To delete a single, specific announcement, set the EntryId parameter to a
+** value representing an actual announcement in the current set. The Severity
+** parameter is ignored when the EntryId parameter is set to a value other
+** than SAHPI_ENTRY_UNSPECIFIED.
+**
+** To delete a group of announcements, set the EntryId parameter to
+** SAHPI_ENTRY_UNSPECIFIED, and set the Severity parameter to identify which
+** severity of announcements should be deleted. To clear all announcements
+** contained within the Annunciator, set the Severity parameter to
+** SAHPI_ALL_SEVERITIES.
+**
+** If the EntryId parameter is passed as SAHPI_ENTRY_UNSPECIFIED, and no
+** announcements are present that meet the specified Severity, this function
+** will have no effect. However, this is not an error.
+**
+** SAHPI_ENTRY_UNSPECIFIED is defined as the same value as SAHPI_FIRST_ENTRY,
+** so using either symbol will have the same effect. However,
+** SAHPI_ENTRY_UNSPECIFIED should be used with this function for clarity.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAnnunciatorDelete(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiAnnunciatorNumT AnnunciatorNum,
+ SAHPI_IN SaHpiEntryIdT EntryId,
+ SAHPI_IN SaHpiSeverityT Severity
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAnnunciatorModeGet()
+**
+** Description:
+** This function allows an HPI User to retrieve the current operating mode of
+** an Annunciator. The mode indicates whether or not an HPI User is allowed to
+** add or delete items in the set, and whether or not the HPI implementation
+** will automatically add or delete items in the set.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** AnnunciatorNum - [in] Annunciator number for the addressed Annunciator.
+** Mode - [out] Pointer to location to store the current operating mode of the
+** Annunciator where the returned value will be one of the following:
+** * SAHPI_ANNUNCIATOR_MODE_AUTO - the HPI implementation may add or delete
+** announcements in the set; an HPI User may not add or delete
+** announcements in the set.
+** * SAHPI_ANNUNCIATOR_MODE_USER - the HPI implementation may not add or
+** delete announcements in the set; an HPI User may add or delete
+** announcements in the set.
+** * SAHPI_ANNUNCIATOR_MODE_SHARED - both the HPI implementation and an HPI
+** User may add or delete announcements in the set.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support
+** Annunciators, as indicated by SAHPI_CAPABILITY_ANNUNCIATOR in the
+** resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the AnnunciatorNum passed does not
+** address a valid Annunciator supported by the resource.
+** SA_ERR_HPI_INVALID_PARAMS is returned if Mode is passed in as NULL.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAnnunciatorModeGet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiAnnunciatorNumT AnnunciatorNum,
+ SAHPI_OUT SaHpiAnnunciatorModeT *Mode
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAnnunciatorModeSet()
+**
+** Description:
+** This function allows an HPI User to change the current operating mode of an
+** Annunciator. The mode indicates whether or not an HPI User is allowed to
+** add or delete announcements in the set, and whether or not the HPI
+** implementation will automatically add or delete announcements in the set.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** AnnunciatorNum - [in] Annunciator number for the addressed Annunciator.
+** Mode - [out] Mode to set for the Annunciator:
+** * SAHPI_ANNUNCIATOR_MODE_AUTO - the HPI implementation may add or delete
+** announcements in the set; an HPI User may not add or delete
+** announcements in the set.
+** * SAHPI_ANNUNCIATOR_MODE_USER - the HPI implementation may not add or
+** delete announcements in the set; an HPI User may add or delete
+** announcements in the set.
+** * SAHPI_ANNUNCIATOR_MODE_SHARED - both the HPI implementation and an HPI
+** User may add or delete announcements in the set.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support
+** Annunciators, as indicated by SAHPI_CAPABILITY_ANNUNCIATOR in the
+** resource's RPT entry.
+** SA_ERR_HPI_NOT_PRESENT is returned if the AnnunciatorNum passed does not
+** address a valid Annunciator supported by the resource.
+** SA_ERR_HPI_INVALID_PARAMS is returned if Mode is not a valid enumerated
+** value for this type.
+** SA_ERR_HPI_READ_ONLY is returned if mode changing is not permitted for
+** this Annunciator.
+**
+** Remarks:
+** None.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAnnunciatorModeSet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiAnnunciatorNumT AnnunciatorNum,
+ SAHPI_IN SaHpiAnnunciatorModeT Mode
+);
+
+/*******************************************************************************
+**
+** Name: saHpiHotSwapPolicyCancel()
+**
+** Description:
+** A resource supporting hot swap typically supports default policies for
+** insertion and extraction. On insertion, the default policy may be for the
+** resource to turn the associated FRU's local power on and to de-assert
+** reset. On extraction, the default policy may be for the resource to
+** immediately power off the FRU and turn on a hot swap indicator. This
+** function allows an HPI User, after receiving a hot swap event with
+** HotSwapState equal to SAHPI_HS_STATE_INSERTION_PENDING or
+** SAHPI_HS_STATE_EXTRACTION_PENDING, to prevent the default policy from
+** being executed.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support
+** managed hot swap, as indicated by SAHPI_CAPABILITY_MANAGED_HOTSWAP in
+** the resource's RPT entry.
+** SA_ERR_HPI_INVALID_REQUEST is returned if the resource is:
+** * Not in the INSERTION PENDING or EXTRACTION PENDING state.
+** * Processing an auto-insertion or auto-extraction policy.
+**
+** Remarks:
+** Each time the resource transitions to either the INSERTION PENDING or
+** EXTRACTION PENDING state, the default policies will execute after the
+** configured timeout period, unless cancelled using
+** saHpiHotSwapPolicyCancel() after the transition to INSERTION PENDING or
+** EXTRACTION PENDING state and before the timeout expires.The default policy
+** cannot be canceled once it has begun to execute.
+**
+** Because a resource that supports the simplified hot swap model will never
+** transition into INSERTION PENDING or EXTRACTION PENDING states, this
+** function is not applicable to those resources.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiHotSwapPolicyCancel (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId
+);
+
+/*******************************************************************************
+**
+** Name: saHpiResourceActiveSet()
+**
+** Description:
+** This function allows an HPI User to request a resource to transition to the
+** ACTIVE state from the INSERTION PENDING or EXTRACTION PENDING state.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support managed
+** hot swap, as indicated by SAHPI_CAPABILITY_MANAGED_HOTSWAP in the
+** resource's RPT entry.
+** SA_ERR_HPI_INVALID_REQUEST is returned if the resource is:
+** * Not in the INSERTION PENDING or EXTRACTION PENDING state.
+** * Processing an auto-insertion or auto-extraction policy.
+**
+** Remarks:
+** During insertion, a resource supporting hot swap will generate an event to
+** indicate that it is in the INSERTION PENDING state. If an HPI User calls
+** saHpiHotSwapPolicyCancel() before the resource begins an auto-insert
+** operation, then the resource will remain in INSERTION PENDING state while
+** an HPI User acts on the resource to integrate it into the system. During
+** this state, an HPI User can instruct the resource to power on the
+** associated FRU, to de-assert reset, or to turn off its hot swap indicator
+** using the saHpiResourcePowerStateSet(), saHpiResourceResetStateSet(), or
+** saHpiHotSwapIndicatorStateSet() functions, respectively, if the resource
+** has those associated capabilities. Once an HPI User has completed with the
+** integration of the FRU, this function must be called to signal that the
+** resource should now transition into the ACTIVE state.
+**
+** An HPI User may also use this function to request a resource to return to
+** the ACTIVE state from the EXTRACTION PENDING state in order to reject an
+** extraction request.
+**
+** Because a resource that supports the simplified hot swap model will never
+** transition into INSERTION PENDING or EXTRACTION PENDING states, this
+** function is not applicable to those resources.
+**
+** Only valid if resource is in INSERTION PENDING or EXTRACTION PENDING state
+** and an auto-insert or auto-extract policy action has not been initiated.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceActiveSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId
+);
+
+/*******************************************************************************
+**
+** Name: saHpiResourceInactiveSet()
+**
+** Description:
+** This function allows an HPI User to request a resource to transition to the
+** INACTIVE state from the INSERTION PENDING or EXTRACTION PENDING state.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support managed
+** hot swap, as indicated by SAHPI_CAPABILITY_MANAGED_HOTSWAP in the
+** resource's RPT entry.
+** SA_ERR_HPI_INVALID_REQUEST is returned if the resource is:
+** * Not in the INSERTION PENDING or EXTRACTION PENDING state.
+** * Processing an auto-insertion or auto-extraction policy.
+**
+** Remarks:
+** During extraction, a resource supporting hot swap will generate an event
+** to indicate that it is in the EXTRACTION PENDING state. If an HPI User
+** calls saHpiHotSwapPolicyCancel() before the resource begins an auto-extract
+** operation, then the resource will remain in EXTRACTION PENDING state while
+** an HPI User acts on the resource to isolate the associated FRU from the
+** system. During this state, an HPI User can instruct the resource to power
+** off the FRU, to assert reset, or to turn on its hot swap indicator using
+** the saHpiResourcePowerStateSet(), saHpiResourceResetStateSet(), or
+** saHpiHotSwapIndicatorStateSet() functions, respectively, if the resource
+** has these associated capabilities. Once an HPI User has completed the
+** shutdown of the FRU, this function must be called to signal that the
+** resource should now transition into the INACTIVE state.
+**
+** An HPI User may also use this function to request a resource to return to
+** the INACTIVE state from the INSERTION PENDING state to abort a hot-swap
+** insertion action.
+**
+** Because a resource that supports the simplified hot swap model will never
+** transition into INSERTION PENDING or EXTRACTION PENDING states, this
+** function is not applicable to those resources.
+**
+** Only valid if resource is in EXTRACTION PENDING or INSERTION PENDING state
+** and an auto-extract or auto-insert policy action has not been initiated.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceInactiveSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAutoInsertTimeoutGet()
+**
+** Description:
+** This function allows an HPI User to request the auto-insert timeout value
+** within a specific domain. This value indicates how long the resource will
+** wait before the default auto-insertion policy is invoked.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** Timeout - [out] Pointer to location to store the number of nanoseconds to
+** wait before autonomous handling of the hot swap event. Reserved time
+** outvalues:
+** * SAHPI_TIMEOUT_IMMEDIATE indicates autonomous handling is immediate.
+** * SAHPI_TIMEOUT_BLOCK indicates autonomous handling does not occur.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the Timeout pointer is passed in
+** as NULL.
+**
+** Remarks:
+** Each domain maintains a single auto-insert timeout value and it is applied
+** to all contained resources upon insertion, which support managed hot swap.
+** Further information on the auto-insert timeout can be found in the
+** function saHpiAutoInsertTimeoutSet().
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAutoInsertTimeoutGet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_OUT SaHpiTimeoutT *Timeout
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAutoInsertTimeoutSet()
+**
+** Description:
+** This function allows an HPI User to configure a timeout for how long to
+** wait before the default auto-insertion policy is invoked on a resource
+** within a specific domain.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** Timeout - [in] The number of nanoseconds to wait before autonomous handling
+** of the hot swap event. Reserved time out values:
+** * SAHPI_TIMEOUT_IMMEDIATE indicates proceed immediately to autonomous
+** handling.
+** * SAHPI_TIMEOUT_BLOCK indicates prevent autonomous handling.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_READ_ONLY is returned if the auto-insert timeout for the domain
+** is fixed as indicated by the SAHPI_DOMAIN_CAP_AUTOINSERT_READ_ONLY flag
+** in the DomainInfo structure.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the Timeout parameter is not set
+** to SAHPI_TIMEOUT_BLOCK, SAHPI_TIMEOUT_IMMEDIATE or a positive value.
+**
+** Remarks:
+** This function accepts a parameter instructing each resource to impose a
+** delay before performing its default hot swap policy for auto-insertion.
+** The parameter may be set to SAHPI_TIMEOUT_IMMEDIATE to direct resources to
+** proceed immediately to auto-insertion, or to SAHPI_TIMEOUT_BLOCK to prevent
+** auto-insertion from ever occurring. If the parameter is set to another
+** value, then it defines the number of nanoseconds between the time a hot
+** swap event with HotSwapState = SAHPI_HS_STATE_INSERTION_PENDING is
+** generated, and the time that the auto-insertion policy will be invoked for
+** that resource. If, during this time period, a saHpiHotSwapPolicyCancel()
+** function call is processed, the timer will be stopped, and the
+** auto-insertion policy will not be invoked. Each domain maintains a single
+** auto-insert timeout value and it is applied to all contained resources upon
+** insertion, which support managed hot swap.
+**
+** Once the auto-insertion policy begins, an HPI User will not be allowed to
+** cancel the insertion policy; hence, the timeout should be set appropriately
+** to allow for this condition. Note that the timeout period begins when the
+** hot swap event with HotSwapState = SAHPI_HS_STATE_INSERTION_PENDING is
+** initially generated; not when it is received by an HPI User with a
+** saHpiEventGet() function call, or even when it is placed in a session
+** event queue.
+**
+** A resource may exist in multiple domains, which themselves may have
+** different auto-insertion timeout values. Upon insertion, the resource will
+** begin its auto-insertion policy based on the smallest auto-insertion
+** timeout value. As an example, if a resource is inserted into two domains,
+** one with an auto-insertion timeout of 5 seconds, and one with an
+** auto-insertion timeout of 10 seconds, the resource will begin its
+** auto-insertion policy at 5 seconds.
+**
+** An implementation may enforce a fixed, preset timeout value. In such
+** cases, the SAHPI_DOMAIN_CAP_AUTOINSERT_READ_ONLY flag will be set to
+** indicate that an HPI User cannot change the auto-insert Timeout value.
+** SA_ERR_HPI_READ_ONLY is returned if an HPI User attempts to change a
+** read-only timeout.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAutoInsertTimeoutSet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiTimeoutT Timeout
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAutoExtractTimeoutGet()
+**
+** Description:
+** This function allows an HPI User to request the timeout for how long a
+** resource will wait before the default auto-extraction policy is invoked.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** Timeout - [out] Pointer to location to store the number of nanoseconds to
+** wait before autonomous handling of the hot swap event. Reserved time
+** out values:
+** * SAHPI_TIMEOUT_IMMEDIATE indicates autonomous handling is immediate.
+** * SAHPI_TIMEOUT_BLOCK indicates autonomous handling does not occur.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support managed
+** hot swap, as indicated by SAHPI_CAPABILITY_MANAGED_HOTSWAP in the
+** resource's RPT entry.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the Timeout pointer is passed in
+** as NULL.
+**
+** Remarks:
+** Further information on auto-extract timeouts is detailed in
+** saHpiAutoExtractTimeoutSet().
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAutoExtractTimeoutGet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiTimeoutT *Timeout
+);
+
+/*******************************************************************************
+**
+** Name: saHpiAutoExtractTimeoutSet()
+**
+** Description:
+** This function allows an HPI User to configure a timeout for how long to
+** wait before the default auto-extraction policy is invoked.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** Timeout - [in] The number of nanoseconds to wait before autonomous handling
+** of the hot swap event. Reserved timeout values:
+** * SAHPI_TIMEOUT_IMMEDIATE indicates proceed immediately to autonomous
+** handling.
+** * SAHPI_TIMEOUT_BLOCK indicates prevent autonomous handling.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support managed
+** hot swap, as indicated by SAHPI_CAPABILITY_MANAGED_HOTSWAP in the
+** resource's RPT entry.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the Timeout parameter is not set
+** to SAHPI_TIMEOUT_BLOCK, SAHPI_TIMEOUT_IMMEDIATE or a positive value.
+** SA_ERR_HPI_READ_ONLY is returned if the auto-extract timeout for the
+** resource is fixed, as indicated by the
+** SAHPI_HS_CAPABILITY_AUTOEXTRACT_READ_ONLY in the resource's RPT entry.
+**
+** Remarks:
+** This function accepts a parameter instructing the resource to impose a
+** delay before performing its default hot swap policy for auto-extraction.
+** The parameter may be set to SAHPI_TIMEOUT_IMMEDIATE to direct the resource
+** to proceed immediately to auto-extraction, or to SAHPI_TIMEOUT_BLOCK to
+** prevent auto-extraction from ever occurring on a resource. If the parameter
+** is set to another value, then it defines the number of nanoseconds between
+** the time a hot swap event with
+** HotSwapState = SAHPI_HS_STATE_EXTRACTION_PENDING is generated and the time
+** that the auto-extraction policy will be invoked for the resource. If,
+** during this time period, a saHpiHotSwapPolicyCancel() function call is
+** processed, the timer will be stopped, and the auto-extraction policy will
+** not be invoked.
+**
+** Once the auto-extraction policy begins, an HPI User will not be allowed to
+** cancel the extraction policy; hence, the timeout should be set
+** appropriately to allow for this condition. Note that the timeout period
+** begins when the hot swap event with
+** HotSwapState = SAHPI_HS_STATE_EXTRACTION_PENDING is initially generated;
+** not when it is received by a HPI User with a saHpiEventGet() function call,
+** or even when it is placed in a session event queue.
+**
+** The auto-extraction policy is set at the resource level and is only
+** supported by resources supporting the Managed Hot Swap capability. The
+** auto-extraction timeout value cannot be modified if the resource's "Hot
+** Swap AutoExtract Read-only" capability is set. After discovering that a
+** newly inserted resource supports Managed Hot Swap, and read-write
+** auto-extract timeouts, an HPI User may use this function to change the
+** timeout of the auto-extraction policy for that resource. If a resource
+** supports the simplified hot swap model, setting this timer has no effect
+** since the resource will transition directly to NOT PRESENT state on an
+** extraction.
+**
+** An implementation may enforce a fixed, preset timeout value. In such
+** cases, the SAHPI_HS_CAPABILITY_AUTOEXTRACT_READ_ONLY flag will be set to
+** indicate that an HPI User cannot change the auto-extract Timeout value.
+** SA_ERR_HPI_READ_ONLY is returned if an HPI User attempts to change a
+** read-only timeout.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiAutoExtractTimeoutSet(
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiTimeoutT Timeout
+);
+
+/*******************************************************************************
+**
+** Name: saHpiHotSwapStateGet()
+**
+** Description:
+** This function allows an HPI User to retrieve the current hot swap state of
+** a resource.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** State - [out] Pointer to location to store returned state information.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support managed
+** hot swap, as indicated by SAHPI_CAPABILITY_MANAGED_HOTSWAP in the
+** resource's RPT entry.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the State pointer is passed in as
+** NULL.
+**
+** Remarks:
+** The returned state will be one of the following four states:
+** * SAHPI_HS_STATE_INSERTION_PENDING
+** * SAHPI_HS_STATE_ACTIVE
+** * SAHPI_HS_STATE_EXTRACTION_PENDING
+** * SAHPI_HS_STATE_INACTIVE
+**
+** The state SAHPI_HS_STATE_NOT_PRESENT will never be returned, because a
+** resource that is not present cannot be addressed by this function in the
+** first place.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiHotSwapStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiHsStateT *State
+);
+
+/*******************************************************************************
+**
+** Name: saHpiHotSwapActionRequest()
+**
+** Description:
+** This function allows an HPI User to invoke an insertion or extraction
+** process via software.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** Action - [in] Requested action:
+** * SAHPI_HS_ACTION_INSERTION
+** * SAHPI_HS_ACTION_EXTRACTION
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support managed
+** hot swap, as indicated by SAHPI_CAPABILITY_MANAGED_HOTSWAP in the
+** resource's RPT entry.
+** SA_ERR_HPI_INVALID_REQUEST is returned if the resource is not in an
+** appropriate hot swap state, or if the requested action is inappropriate
+** for the current hot swap state. See the Remarks section below.
+** SA_ERR_HPI_INVALID_PARAMS is returned when Action is not one of the valid
+** enumerated values for this type.
+**
+** Remarks:
+** A resource supporting hot swap typically requires a physical action on the
+** associated FRU to invoke an insertion or extraction process. An insertion
+** process is invoked by physically inserting the FRU into a chassis.
+** Physically opening an ejector latch or pressing a button invokes the
+** extraction process. This function provides an alternative means to invoke
+** an insertion or extraction process via software.
+**
+** This function may only be called:
+** * To request an insertion action when the resource is in INACTIVE state.
+** * To request an extraction action when the resource is in the ACTIVE
+** state.
+** The function may not be called when the resource is in any other state.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiHotSwapActionRequest (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiHsActionT Action
+);
+
+/*******************************************************************************
+**
+** Name: saHpiHotSwapIndicatorStateGet()
+**
+** Description:
+** This function allows an HPI User to retrieve the state of the hot swap
+** indicator. A FRU associated with a hot-swappable resource may include a hot
+** swap indicator such as a blue LED. This indicator signifies that the FRU is
+** ready for removal.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** State - [out] Pointer to location to store state of hot swap indicator.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support:
+** * Managed hot swap, as indicated by SAHPI_CAPABILITY_MANAGED_HOTSWAP in
+** the resource's RPT entry.
+** * A hot swap indicator on the FRU as indicated by the
+** SAHPI_HS_CAPABILITY_INDICATOR_SUPPORTED in the resource's RPT entry.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the State pointer is passed in as
+** NULL.
+**
+** Remarks:
+** The returned state is either SAHPI_HS_INDICATOR_OFF or
+** SAHPI_HS_INDICATOR_ON. This function will return the state of the
+** indicator, regardless of what hot swap state the resource is in.
+**
+** Not all resources supporting managed hot swap will necessarily support
+** this function. Whether or not a resource supports the hot swap indicator
+** is specified in the Hot Swap Capabilities field of the RPT entry.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiHotSwapIndicatorStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiHsIndicatorStateT *State
+);
+
+/*******************************************************************************
+**
+** Name: saHpiHotSwapIndicatorStateSet()
+**
+** Description:
+** This function allows an HPI User to set the state of the hot swap
+** indicator. A FRU associated with a hot-swappable resource may include a hot
+** swap indicator such as a blue LED. This indicator signifies that the FRU is
+** ready for removal.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** State - [in] State of hot swap indicator to be set.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support:
+** * Managed hot swap, as indicated by SAHPI_CAPABILITY_MANAGED_HOTSWAP in
+** the resource's RPT entry.
+** * A hot swap indicator on the FRU as indicated by the
+** SAHPI_HS_CAPABILITY_INDICATOR_SUPPORTED in the resource's RPT entry.
+** SA_ERR_HPI_INVALID_PARAMS is returned when State is not one of the valid
+** enumerated values for this type.
+**
+** Remarks:
+** Valid states include SAHPI_HS_INDICATOR_OFF or SAHPI_HS_INDICATOR_ON. This
+** function will set the indicator regardless of what hot swap state the
+** resource is in, though it is recommended that this function be used only
+** in conjunction with moving the resource to the appropriate hot swap state.
+**
+** Not all resources supporting managed hot swap will necessarily support this
+** function. Whether or not a resource supports the hot swap indicator is
+** specified in the Hot Swap Capabilities field of the RPT entry.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiHotSwapIndicatorStateSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiHsIndicatorStateT State
+);
+
+/*******************************************************************************
+**
+** Name: saHpiParmControl()
+**
+** Description:
+** This function allows an HPI User to save and restore parameters associated
+** with a specific resource.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** Action - [in] Action to perform on resource parameters.
+** * SAHPI_DEFAULT_PARM Restores the factory default settings for a
+** specific resource. Factory defaults include sensor thresholds and
+** configurations, and resource- specific configuration parameters.
+** * SAHPI_SAVE_PARM Stores the resource configuration parameters in
+** non-volatile storage. Resource configuration parameters stored in
+** non-volatile storage will survive power cycles and resource resets.
+** * SAHPI_RESTORE_PARM Restores resource configuration parameters from
+** non-volatile storage. Resource configuration parameters include
+** sensor thresholds and sensor configurations, as well as
+** resource-specific parameters.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support
+** parameter control, as indicated by SAHPI_CAPABILITY_CONFIGURATION in the
+** resource's RPT entry.
+** SA_ERR_HPI_INVALID_PARAMS is returned when Action is not set to a proper
+** value.
+**
+** Remarks:
+** Resource-specific parameters should be documented in an implementation
+** guide for the HPI implementation.
+**
+** When this API is called with SAHPI_RESTORE_PARM as the action prior to
+** having made a call with this API where the action parameter was set to
+** SAHPI_SAVE_PARM, the default parameters will be restored.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiParmControl (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiParmActionT Action
+);
+
+/*******************************************************************************
+**
+** Name: saHpiResourceResetStateGet()
+**
+** Description:
+** This function gets the reset state of an entity, allowing an HPI User to
+** determine if the entity is being held with its reset asserted. If a
+** resource manages multiple entities, this function will address the entity
+** which is identified in the RPT entry for the resource.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** ResetAction - [out] The current reset state of the entity. Valid reset
+** states are:
+** * SAHPI_RESET_ASSERT: The entity's reset is asserted, e.g., for hot
+** swap insertion/extraction purposes.
+** * SAHPI_RESET_DEASSERT: The entity's reset is not asserted.
+**
+** Return Value:
+** SA_OK is returned if the resource has reset control, and the reset state
+** has successfully been determined; otherwise, an error code is returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support reset
+** control as indicated by SAHPI_CAPABILITY_RESET in the resource's RPT
+** entry.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the ResetAction pointer is passed
+** in as NULL.
+**
+** Remarks:
+** SAHPI_COLD_RESET and SAHPI_WARM_RESET are pulsed resets, and are not valid
+** values to be returned in ResetAction. If the entity is not being held in
+** reset (using SAHPI_RESET_ASSERT), the appropriate value is
+** SAHPI_RESET_DEASSERT.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceResetStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiResetActionT *ResetAction
+);
+
+/*******************************************************************************
+**
+** Name: saHpiResourceResetStateSet()
+**
+** Description:
+** This function directs the resource to perform the specified reset type on
+** the entity that it manages. If a resource manages multiple entities, this
+** function addresses the entity that is identified in the RPT entry for the
+** resource.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** ResetAction - [in] Type of reset to perform on the entity. Valid reset
+** actions are:
+** * SAHPI_COLD_RESET: Perform a 'Cold Reset' on the entity (pulse),
+** leaving reset de-asserted,
+** * SAHPI_WARM_RESET: Perform a 'Warm Reset' on the entity (pulse),
+** leaving reset de-asserted,
+** * SAHPI_RESET_ASSERT: Put the entity into reset state and hold reset
+** asserted, e.g., for hot swap insertion/extraction purposes,
+** * SAHPI_RESET_DEASSERT: Bring the entity out of the reset state.
+**
+** Return Value:
+** SA_OK is returned if the resource has reset control, and the requested
+** reset action has succeeded; otherwise, an error code is returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support resource
+** reset control, as indicated by SAHPI_CAPABILITY_RESET in the resource's
+** RPT entry.
+** SA_ERR_HPI_INVALID_PARAMS is returned when the ResetAction is not set to a
+** proper value.
+** SA_ERR_HPI_INVALID_CMD is returned if the requested ResetAction is
+** SAHPI_RESET_ASSERT and the resource does not support this action.
+** SA_ERR_HPI_INVALID_REQUEST is returned if the ResetAction is
+** SAHPI_COLD_RESET or SAHPI_WARM_RESET and reset is currently asserted.
+**
+** Remarks:
+** Some resources may not support holding the entity in reset. If this is the
+** case, the resource should return SA_ERR_HPI_INVALID_CMD if the
+** SAHPI_RESET_ASSERT action is requested. All resources that have the
+** SAHPI_CAPABILITY_RESET flag set in their RPTs should support
+** SAHPI_COLD_RESET and SAHPI_WARM_RESET. However, it is not required that
+** these actions be different. That is, some resources may only have one
+** sort of reset action (e.g., a "cold" reset) which is executed when either
+** SAHPI_COLD_RESET or SAHPI_WARM_RESET is requested.
+**
+** The SAHPI_RESET_ASSERT is used to hold an entity in reset, and
+** SAHPI_RESET_DEASSERT is used to bring the entity out of an asserted reset
+** state.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourceResetStateSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiResetActionT ResetAction
+);
+
+/*******************************************************************************
+**
+** Name: saHpiResourcePowerStateGet()
+**
+** Description:
+** This function gets the power state of an entity, allowing an HPI User to
+** determine if the entity is currently powered on or off. If a resource
+** manages multiple entities, this function will address the entity which is
+** identified in the RPT entry for the resource.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** State - [out] The current power state of the resource. Valid power states
+** are:
+** * SAHPI_POWER_OFF: The entity's primary power is OFF,
+** * SAHPI_POWER_ON: The entity's primary power is ON.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support power
+** management, as indicated by SAHPI_CAPABILITY_POWER in the resource's
+** RPT entry.
+** SA_ERR_HPI_INVALID_PARAMS is returned if the State pointer is passed in
+** as NULL.
+**
+** Remarks:
+** SAHPI_POWER_CYCLE is a pulsed power operation and is not a valid return
+** for the power state.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourcePowerStateGet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_OUT SaHpiPowerStateT *State
+);
+
+/*******************************************************************************
+**
+** Name: saHpiResourcePowerStateSet()
+**
+** Description:
+** This function directs the resource to perform the power control action on
+** the entity that it manages. If a resource manages multiple entities, this
+** function addresses the entity that is identified in the RPT entry for the
+** resource.
+**
+** Parameters:
+** SessionId - [in] Identifier for a session context previously obtained using
+** saHpiSessionOpen().
+** ResourceId - [in] Resource identified for this operation.
+** State - [in] the requested power control action. Valid values are:
+** * SAHPI_POWER_OFF: The entity's primary power is turned OFF,
+** * SAHPI_POWER_ON: The entity's primary power is turned ON,
+** * SAHPI_POWER_CYCLE: The entity's primary power is turned OFF, then
+** turned ON.
+**
+** Return Value:
+** SA_OK is returned on successful completion; otherwise, an error code is
+** returned.
+** SA_ERR_HPI_CAPABILITY is returned if the resource does not support power
+** management, as indicated by SAHPI_CAPABILITY_POWER in the resource's
+** RPT entry.
+** SA_ERR_HPI_INVALID_PARAMS is returned when State is not one of the valid
+** enumerated values for this type.
+**
+** Remarks:
+** This function controls the hardware power on a FRU entity regardless of
+** what hot-swap state the resource is in. For example, it is legal (and may
+** be desirable) to cycle power on the FRU even while it is in ACTIVE state in
+** order to attempt to clear a fault condition. Similarly, a resource could be
+** instructed to power on a FRU even while it is in INACTIVE state, for
+** example, in order to run off-line diagnostics.
+**
+** Not all resources supporting hot swap will necessarily support this
+** function. In particular, resources that use the simplified hot swap model
+** may not have the ability to control FRU power.
+**
+** This function may also be supported for non-FRU entities if power control
+** is available for those entities.
+**
+*******************************************************************************/
+SaErrorT SAHPI_API saHpiResourcePowerStateSet (
+ SAHPI_IN SaHpiSessionIdT SessionId,
+ SAHPI_IN SaHpiResourceIdT ResourceId,
+ SAHPI_IN SaHpiPowerStateT State
+);
+
+#endif
diff --git a/hpiutil/TODO b/hpiutil/TODO
new file mode 100644
index 0000000..5ab06da
--- /dev/null
+++ b/hpiutil/TODO
@@ -0,0 +1,65 @@
+HPIUTIL TODO
+
+x Porting the utilities in hpiutil from HPI_A to HPI_B
+ These can be built for either version of HPI via a compile flag.
+ They default to HPI_A, since HPI_B libraries are not fully released yet.
+ Ported to HPI B with OpenHPI:
+ hpialarmpanel.c done, with compile flags 10/13/04
+ hpireset.c, hpisensor.c, hpisel.c hpiwdt.c - done
+ hpifru.c (hpifrub.c) - done
+ hpievent.c (runs, but ThresholdSet error -1010 due to lib bug)
+ COMPLETE
+
+x SpiLibd supplies inventory capability for DIMMs, but gives error when
+ trying to get its inventory data.
+ COMPLETE in hpiutil-1.1.9
+
+Intel HPI library/daemon (SpiLibd) known issues:
+- If the SEL is totally empty (not even a 'cleared' message), the SpiLibd
+ will not start because the GetSelEntry returns 0xcb.
+ The lib probably needs to set eventid to zero and proceed in this case.
+
+OpenHPI library/daemon with ipmidirect plugin:
+ 11/10/06 completed adding LEDs, watchdog, and Intel RMS features
+ 12/07/06 openhpi-2.6.3 released, fully tested
+
+OpenHPI library with ipmi plugin testing & issues:
+ Continuing testing of hpiutil with OpenHPI using its ipmi plugin,
+ but currently there are blocking bugs open (see latest date below).
+ 02/11/04 OpenHPI 0.5 dies during discovery
+ 05/24/04 OpenHPI 1.0.0 testing, wrote more bugzillas
+ 10/14/04 openhpi-1.9.1 testing, then added alarm panel code
+ With patches to 1.9.1, alarm panel controls are operational now.
+ 12/02/04 Submitted fixes for watchdog 932510 & 1077934.
+ 01/10/05 Submitted fixes for several inventory bugs into openhpi-2.0.1 cvs.
+ Bug list: (f=fixed, x=rejected, o=open)
+ x 924280 IPMI plug-in takes too long to discover 2004-03-26 18:24
+ (ref #959765)
+ x 932486 wrong string terminator for Compact SDRs 2004-04-09 15:37
+ f 932492 Lots of FRU errors displayed during discovery 2004-04-09 15:47
+ f 932496 EventLog RecordId and Time are invalid 2004-04-09 15:55
+ f 932510 Watchdog values incorrect 2004-04-09 16:09
+ f 933737 hpievent test failed (EventGet & hyst_set) 2004-04-12 12:29
+ f 933741 Reset Controls not implemented 2004-04-12 12:33
+ f 934475 Add some alarm panel logic 2004-04-13 16:23
+ f 948551 RdrGet returns -1024 with hpifru 2004-05-05 11:25
+ f 948644 ResetStateSet returns error -1005 2004-05-05 14:01
+ o 959749 hpithres returns -1006 from ThresholdsGet 2004-05-24 18:02
+ f 959753 No Inventory RDRs are populated 2004-05-24 18:13
+ f 959765 IPMI plug-in takes too long to discover 2004-05-24 18:27
+ (some progress, 10 min down to 3 min - now 2.5 min)
+ f 1040276 Event in SEL not mapped to HPI 2004-10-04 19:22
+ f 1068098 EventLogEntryGet returns less than 16 data by 2004-11-17 11:04
+ o 1070785 OpenHPI discover method hangs if system is no 2004-11-21 23:54
+ f 1077934 some entity tags have zero length 2004-12-02 16:46
+ o 1086122 Can't set (write) Inventory fields 2004-12-15 18:02
+ f 1090496 FLOAT64 decoding should not be scientific not 2004-12-23 13:39
+ f 1095266 Inventory Product Fields report Board Area ty 2005-01-03 16:24
+ f 1095262 Inventory Custom field not retrieved 2005-01-03 16:14
+ o 1095256 Takes 5 Discovery passes to fill in FRU data 2005-01-03 16:09
+ f 1095225 Inventory content truncated 2005-01-03 15:04
+ f 1098067 hpisensor output usability 2005-01-07 13:37
+ f 1098073 ThresholdsGet sometimes returns TIMEOUT 2005-01-07 13:49
+ 09/26/06 Submitted bug against openhpi-2.6.2 ipmi plugin discovery failure
+ o 1565999 ohoi: domain not fully up, sel support = 0 2006-09-26 17;16
+
diff --git a/hpiutil/env.hpi b/hpiutil/env.hpi
new file mode 100755
index 0000000..2d14c96
--- /dev/null
+++ b/hpiutil/env.hpi
@@ -0,0 +1,11 @@
+export SAHPI_HOME=/etc/hpi
+export SPI_LIB_LOG_LOCATION=/var/log/spilib
+export SPI_LIB_CFG_LOCATION=$SAHPI_HOME/spi-lib.conf
+export SPI_DAEMON_LOG_LOCATION=/var/log/spidaemon
+export SPI_DAEMON_CFG_LOCATION=$SAHPI_HOME/spi-daemon.conf
+export SPI_DAEMON_LOG_LEVEL=-l5
+export SPI_LIB_LOG_LEVEL=-l5
+export LD_LIBRARY_PATH=/usr/lib:/lib
+# export LD_LIBRARY_PATH=$SAHPI_HOME/lib
+# export LD_ASSUME_KERNEL=2.4.1
+# make sure to "mkdir -p /etc/hpi"
diff --git a/hpiutil/env.openhpi b/hpiutil/env.openhpi
new file mode 100755
index 0000000..53bdee6
--- /dev/null
+++ b/hpiutil/env.openhpi
@@ -0,0 +1,2 @@
+export LD_LIBRARY_PATH=/usr/local/lib
+# make sure to "mkdir -p /etc/hpi"
diff --git a/hpiutil/hpialarmpanel.c b/hpiutil/hpialarmpanel.c
new file mode 100644
index 0000000..f918636
--- /dev/null
+++ b/hpiutil/hpialarmpanel.c
@@ -0,0 +1,373 @@
+/*
+ * hpialarmpanel.c
+ *
+ * Author: Andy Cress arcress at users.sourceforge.net
+ * Copyright (c) 2003 Intel Corporation.
+ *
+ * 04/15/03 Andy Cress - created
+ * 04/17/03 Andy Cress - mods for resourceid, first good run
+ * 04/23/03 Andy Cress - first run with good ControlStateGet
+ * 04/24/03 Andy Cress - v0.5 with good ControlStateSet
+ * 04/29/03 Andy Cress - v0.6 changed control.oem values
+ * 06/06/03 Andy Cress - v1.0 check for Analog States
+ * 02/23/04 Andy Cress - v1.1 add checking/setting disk LEDs
+ * 10/13/04 Andy Cress - v1.2 add ifdefs for HPI_A & HPI_B, added -d/raw
+ */
+/*M*
+Copyright (c) 2003, 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 <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include "SaHpi.h"
+
+#define uchar unsigned char
+#define SAHPI_OEM_ALARM_LED 0x10
+#define SAHPI_OEM_DISK_LED 0x20
+#ifdef HPI_A
+char *progver = "1.2 HPI-A";
+#else
+char *progver = "1.2 HPI-B";
+#endif
+char fdebug = 0;
+char *states[3] = {"off", "ON ", "unknown" };
+uchar fsetid = 0;
+uchar fid = 0;
+#define NLEDS 6
+struct {
+ uchar fset;
+ uchar val;
+} leds[NLEDS] = { /* rdr.RdrTypeUnion.CtrlRec.Oem is an index for this */
+{/*pwr*/ 0, 0},
+{/*crt*/ 0, 0},
+{/*maj*/ 0, 0},
+{/*min*/ 0, 0},
+{/*diska*/ 0, 0},
+{/*diskb*/ 0, 0} };
+
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ SaErrorT rv;
+ SaHpiSessionIdT sessionid;
+#ifdef HPI_A
+ SaHpiVersionT hpiVer;
+ SaHpiRptInfoT rptinfo;
+#endif
+ SaHpiRptEntryT rptentry;
+ SaHpiEntryIdT rptentryid;
+ SaHpiEntryIdT nextrptentryid;
+ SaHpiEntryIdT entryid;
+ SaHpiEntryIdT nextentryid;
+ SaHpiResourceIdT resourceid;
+ SaHpiRdrT rdr;
+ SaHpiCtrlTypeT ctltype;
+ SaHpiCtrlNumT ctlnum;
+ SaHpiCtrlStateT ctlstate;
+ int raw_val = 0;
+ int j;
+ uchar b = 0;
+
+ printf("%s ver %s\n", argv[0],progver);
+ while ( (c = getopt( argc, argv,"rxa:b:c:m:n:p:i:d:o?")) != EOF )
+ switch(c) {
+
+ case 'c': b = atoi(optarg); /* set crit alarm value */
+ leds[1].fset = 1;
+ leds[1].val = b;
+ break;
+ case 'm': b = atoi(optarg); /* set major alarm value */
+ leds[2].fset = 1;
+ leds[2].val = b;
+ break;
+ case 'n': b = atoi(optarg); /* set minor alarm value */
+ leds[3].fset = 1;
+ leds[3].val = b;
+ break;
+ case 'a': b = atoi(optarg); /* set disk a fault led */
+ leds[4].fset = 1;
+ leds[4].val = b;
+ break;
+ case 'b': b = atoi(optarg); /* set disk b fault led */
+ leds[5].fset = 1;
+ leds[5].val = b;
+ break;
+ case 'p': b = atoi(optarg); /* set power alarm value */
+ leds[0].fset = 1;
+ leds[0].val = b;
+ break;
+ case 'i': fid = atoi(optarg); /* set chassis id on/off */
+ fsetid = 1;
+ break;
+ case 'd': raw_val = atoi(optarg); /* set raw alarm byte */
+ break;
+ case 'o': fsetid=1; fid=0; /* set all alarms off */
+ for (j = 0; j < NLEDS; j++) {
+ leds[j].fset = 1;
+ leds[j].val = 0;
+ }
+ break;
+ case 'x': fdebug = 1; break; /* debug messages */
+ default:
+ printf("Usage: %s [-a -b -c -i -m -n -p -o -x]\n", argv[0]);
+ printf(" where -c1 sets Critical Alarm on\n");
+ printf(" -c0 sets Critical Alarm 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(" -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");
+#ifndef HPI_A
+ printf(" -d[byte] sets raw Alarm byte\n");
+#endif
+ printf(" -o sets all Alarms off\n");
+ printf(" -x show eXtra debug messages\n");
+ exit(1);
+ }
+
+#ifdef HPI_A
+ rv = saHpiInitialize(&hpiVer);
+ if (rv != SA_OK) {
+ printf("saHpiInitialize error %d\n",rv);
+ exit(-1);
+ }
+ if (fdebug) printf("Initialize complete, rv = %d\n",rv);
+ rv = saHpiSessionOpen(SAHPI_DEFAULT_DOMAIN_ID,&sessionid,NULL);
+ if (rv != SA_OK) {
+ if (rv == SA_ERR_HPI_ERROR)
+ printf("saHpiSessionOpen: error %d, HPI daemon not running\n",rv);
+ else
+ printf("saHpiSessionOpen error %d\n",rv);
+ exit(-1);
+ }
+ rv = saHpiResourcesDiscover(sessionid);
+ if (fdebug) printf("saHpiResourcesDiscover complete, rv = %d\n",rv);
+ rv = saHpiRptInfoGet(sessionid,&rptinfo);
+ if (fdebug) printf("saHpiRptInfoGet rv = %d\n",rv);
+ printf("RptInfo: UpdateCount = %x, UpdateTime = %lx\n",
+ rptinfo.UpdateCount, (unsigned long)rptinfo.UpdateTimestamp);
+#else /* HPI B.01.01 */
+ rv = saHpiSessionOpen(SAHPI_UNSPECIFIED_DOMAIN_ID,&sessionid,NULL);
+ if (rv != SA_OK) {
+ printf("saHpiSessionOpen error %d\n",rv);
+ exit(-1);
+ }
+ rv = saHpiDiscover(sessionid);
+ if (fdebug) printf("saHpiDiscover complete, rv = %d\n",rv);
+
+ if (fsetid) { /* HPI B.01.01 Identify logic */
+ printf("Setting ID led to %d sec\n", fid);
+ /* do saHpiIdentify function */
+ printf("Not yet supported\n");
+ }
+#endif
+
+ /* walk the RPT list */
+ rptentryid = SAHPI_FIRST_ENTRY;
+ while ((rv == SA_OK) && (rptentryid != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiRptEntryGet(sessionid,rptentryid,&nextrptentryid,&rptentry);
+ if (rv != SA_OK) printf("RptEntryGet: rv = %d\n",rv);
+ if (rv == SA_OK) {
+ /* Walk the RDR list for this RPT entry */
+ entryid = SAHPI_FIRST_ENTRY;
+ resourceid = rptentry.ResourceId;
+#ifdef HPI_A
+ rptentry.ResourceTag.Data[rptentry.ResourceTag.DataLength] = 0;
+#else
+ /*
+ * Don't stringify here, since OpenHPI returns a valid string, but
+ * a DataLength of zero here (for processor, bios).
+ */
+#endif
+ //if (fdebug)
+ printf("rptentry[%d] resourceid=%d tag: %s\n",
+ rptentryid, resourceid, rptentry.ResourceTag.Data);
+ while ((rv == SA_OK) && (entryid != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiRdrGet(sessionid,resourceid,
+ entryid,&nextentryid, &rdr);
+ if (fdebug) printf("saHpiRdrGet[%d] rv = %d\n",entryid,rv);
+ if (rv == SA_OK) {
+ if (rdr.RdrType == SAHPI_CTRL_RDR) {
+ /*type 1 includes alarm LEDs*/
+ ctlnum = rdr.RdrTypeUnion.CtrlRec.Num;
+ rdr.IdString.Data[rdr.IdString.DataLength] = 0;
+ if (fdebug) printf("Ctl[%d]: %d %d %s\n",
+ ctlnum, rdr.RdrTypeUnion.CtrlRec.Type,
+ rdr.RdrTypeUnion.CtrlRec.OutputType,
+ rdr.IdString.Data);
+ rv = saHpiControlTypeGet(sessionid,resourceid,
+ ctlnum,&ctltype);
+ if (fdebug) printf("saHpiControlTypeGet[%d] rv = %d, type = %d\n",ctlnum,rv,ctltype);
+#ifdef HPI_A
+ rv = saHpiControlStateGet(sessionid,resourceid,
+ ctlnum,&ctlstate);
+#else
+ rv = saHpiControlGet(sessionid, resourceid, ctlnum,
+ NULL, &ctlstate);
+#endif
+ if (fdebug)
+ printf("saHpiControlStateGet[%d] rv = %d v = %x\n",
+ ctlnum,rv,ctlstate.StateUnion.Digital);
+ printf("RDR[%d]: ctltype=%d:%d oem=%02x %s \t",
+ rdr.RecordId,
+ rdr.RdrTypeUnion.CtrlRec.Type,
+ rdr.RdrTypeUnion.CtrlRec.OutputType,
+ rdr.RdrTypeUnion.CtrlRec.Oem,
+ rdr.IdString.Data);
+ if (rv == SA_OK) {
+ if (ctlstate.Type == SAHPI_CTRL_TYPE_ANALOG)
+ b = 2; /*Identify*/
+ else {
+ b = ctlstate.StateUnion.Digital;
+ if (b > 2) b = 2;
+ }
+ printf("state = %s\n",states[b]);
+ } else { printf("\n"); }
+
+ if (rdr.RdrTypeUnion.CtrlRec.Type == SAHPI_CTRL_TYPE_ANALOG &&
+ rdr.RdrTypeUnion.CtrlRec.OutputType == SAHPI_CTRL_LED) {
+ /* This is a Chassis Identify */
+ if (fsetid) {
+ printf("Setting ID led to %d sec\n", fid);
+ ctlstate.Type = SAHPI_CTRL_TYPE_ANALOG;
+ ctlstate.StateUnion.Analog = fid;
+#ifdef HPI_A
+ rv = saHpiControlStateSet(sessionid,
+ resourceid, ctlnum,&ctlstate);
+#else
+ rv = saHpiControlSet(sessionid, resourceid,
+ ctlnum, SAHPI_CTRL_MODE_MANUAL,
+ &ctlstate);
+#endif
+ printf("saHpiControlStateSet[%d] rv = %d\n",ctlnum,rv);
+ }
+ } else
+ if (rdr.RdrTypeUnion.CtrlRec.Type == SAHPI_CTRL_TYPE_DIGITAL &&
+ (rdr.RdrTypeUnion.CtrlRec.Oem & 0xf0) == SAHPI_OEM_ALARM_LED &&
+ rdr.RdrTypeUnion.CtrlRec.OutputType == SAHPI_CTRL_LED) {
+ /* this is an alarm LED */
+ b = (uchar)rdr.RdrTypeUnion.CtrlRec.Oem & 0x0f;
+ if ((b < NLEDS) && leds[b].fset) {
+ printf("Setting alarm led %d to %d\n",b,leds[b].val);
+ if (leds[b].val == 0)
+ ctlstate.StateUnion.Digital = SAHPI_CTRL_STATE_OFF;
+ else
+ ctlstate.StateUnion.Digital = SAHPI_CTRL_STATE_ON;
+#ifdef HPI_A
+ rv = saHpiControlStateSet(sessionid,
+ resourceid, ctlnum,&ctlstate);
+#else
+ rv = saHpiControlSet(sessionid, resourceid,
+ ctlnum, SAHPI_CTRL_MODE_MANUAL,
+ &ctlstate);
+#endif
+ /* if (fdebug) */
+ printf("saHpiControlStateSet[%d] rv = %d\n",ctlnum,rv);
+ }
+ }
+ else if (rdr.RdrTypeUnion.CtrlRec.Type == SAHPI_CTRL_TYPE_DIGITAL &&
+ (rdr.RdrTypeUnion.CtrlRec.Oem & 0xf0) == SAHPI_OEM_DISK_LED &&
+ rdr.RdrTypeUnion.CtrlRec.OutputType == SAHPI_CTRL_LED) {
+ /* this is a disk LED */
+ b = (uchar)rdr.RdrTypeUnion.CtrlRec.Oem & 0x0f;
+ if ((b < NLEDS) && leds[b].fset) {
+ printf("Setting disk led %d to %d\n",b,leds[b].val);
+ if (leds[b].val == 0)
+ ctlstate.StateUnion.Digital = SAHPI_CTRL_STATE_OFF;
+ else
+ ctlstate.StateUnion.Digital = SAHPI_CTRL_STATE_ON;
+#ifdef HPI_A
+ rv = saHpiControlStateSet(sessionid,
+ resourceid, ctlnum,&ctlstate);
+#else
+ rv = saHpiControlSet(sessionid, resourceid,
+ ctlnum, SAHPI_CTRL_MODE_MANUAL,
+ &ctlstate);
+#endif
+ printf("saHpiControlStateSet[%d] rv = %d\n",ctlnum,rv);
+ }
+ }
+#ifndef HPI_A
+ else if (rdr.RdrTypeUnion.CtrlRec.Type == SAHPI_CTRL_TYPE_OEM &&
+ rdr.RdrTypeUnion.CtrlRec.OutputType == SAHPI_CTRL_FRONT_PANEL_LOCKOUT) {
+ /* This is a raw control for alarm panel,
+ * but HPI never populates an RDR for this. */
+ printf("Found raw alarm control\n");
+ if (raw_val != 0) {
+ ctlstate.Type = SAHPI_CTRL_TYPE_OEM;
+ ctlstate.StateUnion.Oem.BodyLength = 1;
+ ctlstate.StateUnion.Oem.Body[0] = raw_val;
+ printf("Set raw alarm control to %x\n",raw_val);
+ rv = saHpiControlSet(sessionid, resourceid, ctlnum,
+ SAHPI_CTRL_MODE_MANUAL, &ctlstate);
+ printf("saHpiControlSet[%d] raw, rv = %d\n",ctlnum,rv);
+ }
+ }
+#endif
+ rv = SA_OK; /* ignore errors & continue */
+ }
+ j++;
+ entryid = nextentryid;
+ }
+ } /* RdrGet loop */
+ rptentryid = nextrptentryid;
+ }
+ } /* RptEntryGet loop */
+
+ rv = saHpiSessionClose(sessionid);
+#ifdef HPI_A
+ rv = saHpiFinalize();
+#endif
+
+ exit(0);
+ return(0);
+}
+
+/*-----------Sample output-----------------------------------
+hpialarmpanel ver 0.6
+RptInfo: UpdateCount = 5, UpdateTime = 8a2dc6c0
+rptentry[0] resourceid=1 tag: Mullins
+RDR[45]: ctltype=2:1 oem=0 Chassis Identify Control
+RDR[48]: ctltype=0:1 oem=10 Front Panel Power Alarm LED state = off
+RDR[51]: ctltype=0:1 oem=13 Front Panel Minor Alarm LED state = ON
+RDR[46]: ctltype=0:0 oem=0 Cold Reset Control
+RDR[49]: ctltype=0:1 oem=11 Front Panel Critical Alarm LED state = off
+RDR[50]: ctltype=0:1 oem=12 Front Panel Major Alarm LED state = off
+ *-----------------------------------------------------------*/
+/* end hpialarmpanel.c */
diff --git a/hpiutil/hpievent.c b/hpiutil/hpievent.c
new file mode 100644
index 0000000..56a5930
--- /dev/null
+++ b/hpiutil/hpievent.c
@@ -0,0 +1,621 @@
+/*
+ * hpievent.c
+ *
+ * Author: Bill Barkley
+ * Copyright (c) 2003 Intel Corporation.
+ *
+ * 05/14/03
+ * 06/06/03 - complete working version
+ * 06/20/03 ARCress - added option for Mullins w default=Langley-type sensor
+ * added progver
+ * 02/26/04 ARCress - added general search for any Fan sensor.
+ * 03/17/04 ARCress - changed to Temp sensor (always has Lower Major)
+ * 03/30/04 ARCress - fixed rv with saHpiSensorThresholdsSet
+ * 01/03/05 ARCress - some edits for HPI_A/B
+ * 01/07/05 ARCress - clean compile for HPI B, but ThresholdGet returns -1006
+ * 04/01/05 ARCress - set UpMajor if not fFan
+ */
+/*M*
+Copyright (c) 2003, 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include "SaHpi.h"
+
+char progname[] = "hpievent";
+char progver[] = "1.2";
+char s_name[] = "80mm Sys Fan (R)"; /*TSRLT2, default*/
+char sm_name[] = "Baseboard Fan 2"; /*TSRMT2, Mullins*/
+int fFan = 1;
+char s_pattn[] = "Temp"; /* else use the first temperature SDR found */
+char *sensor_name;
+int sensor_name_len = 0;
+int fdebug = 0;
+int fxdebug = 0;
+int fsensor = 0;
+int slist = 0;
+int i,j,k = 0;
+char inbuff[1024];
+char outbuff[256];
+SaHpiUint32T buffersize;
+SaHpiUint32T actualsize;
+SaHpiTextBufferT *strptr;
+#ifdef HPI_A
+SaHpiInventoryDataT *inv;
+SaHpiInventGeneralDataT *dataptr;
+SaHpiSensorEvtEnablesT enables1;
+SaHpiSensorEvtEnablesT enables2;
+#endif
+
+char *rdrtypes[5] = {
+ "None ",
+ "Control ",
+ "Sensor ",
+ "Invent ",
+ "Watchdog"};
+
+#define HPI_NSEC_PER_SEC 1000000000LL
+#define NSU 32
+char *units[NSU] = {
+ "units", "deg C", "deg F", "deg K", "volts", "amps",
+ "watts", "joules", "coulombs", "va", "nits", "lumen",
+ "lux", "candela", "kpa", "psi", "newton", "cfm",
+ "rpm", "Hz", "us", "ms", "sec", "min",
+ "hours", "days", "weeks", "mil", "in", "ft",
+ "mm", "cm"
+};
+
+#ifdef NOT
+void
+fixstr(SaHpiTextBufferT *strptr)
+{
+ size_t datalen;
+ outbuff[0] = 0;
+ if (strptr == NULL) return;
+ datalen = strptr->DataLength;
+ if (datalen != 0) {
+ strncpy ((char *)outbuff, (char *)strptr->Data, datalen);
+ outbuff[datalen] = 0;
+ }
+}
+#endif
+
+static void ShowThresh(
+ SaHpiSensorThresholdsT *sensbuff, SaHpiSensorThdMaskT ReadThold)
+{
+ printf( " Supported Thresholds:\n");
+#ifdef HPI_A
+ if (sensbuff->LowCritical.ValuesPresent & SAHPI_SRF_INTERPRETED)
+ printf( " Lower Critical Threshold: %5.2f\n",
+ sensbuff->LowCritical.Interpreted.Value.SensorFloat32);
+ if (sensbuff->LowMajor.ValuesPresent & SAHPI_SRF_INTERPRETED)
+ printf( " Lower Major Threshold: %5.2f\n",
+ sensbuff->LowMajor.Interpreted.Value.SensorFloat32);
+ if (sensbuff->LowMinor.ValuesPresent & SAHPI_SRF_INTERPRETED)
+ printf( " Lower Minor Threshold: %5.2f\n",
+ sensbuff->LowMinor.Interpreted.Value.SensorFloat32);
+
+ if (sensbuff->UpCritical.ValuesPresent & SAHPI_SRF_INTERPRETED)
+ printf( " Upper Critical Threshold: %5.2f\n",
+ sensbuff->UpCritical.Interpreted.Value.SensorFloat32);
+ if (sensbuff->UpMajor.ValuesPresent & SAHPI_SRF_INTERPRETED)
+ printf( " Upper Major Threshold: %5.2f\n",
+ sensbuff->UpMajor.Interpreted.Value.SensorFloat32);
+ if (sensbuff->UpMinor.ValuesPresent & SAHPI_SRF_INTERPRETED)
+ printf( " Upper Minor Threshold: %5.2f\n",
+ sensbuff->UpMinor.Interpreted.Value.SensorFloat32);
+
+ if (sensbuff->PosThdHysteresis.ValuesPresent & SAHPI_SRF_RAW)
+ printf( " Positive Threshold Hysteresis in RAW\n");
+ if (sensbuff->PosThdHysteresis.ValuesPresent & SAHPI_SRF_INTERPRETED)
+ printf( " Positive Threshold Hysteresis: %5.2f\n",
+ sensbuff->PosThdHysteresis.Interpreted.Value.SensorFloat32);
+ if (sensbuff->NegThdHysteresis.ValuesPresent & SAHPI_SRF_RAW)
+ printf( " Negative Threshold Hysteresis in RAW\n");
+ if (sensbuff->NegThdHysteresis.ValuesPresent & SAHPI_SRF_INTERPRETED)
+ printf( " Negative Threshold Hysteresis: %5.2f\n",
+ sensbuff->NegThdHysteresis.Interpreted.Value.SensorFloat32);
+#else
+ if ( ReadThold & SAHPI_STM_LOW_CRIT ) {
+ printf( " Lower Critical Threshold: %5.2f\n",
+ sensbuff->LowCritical.Value.SensorFloat64);
+ }
+ if ( ReadThold & SAHPI_STM_LOW_MAJOR ) {
+ printf( " Lower Major Threshold: %5.2f\n",
+ sensbuff->LowMajor.Value.SensorFloat64);
+ }
+ if ( ReadThold & SAHPI_STM_LOW_MINOR ) {
+ printf( " Lower Minor Threshold: %5.2f\n",
+ sensbuff->LowMinor.Value.SensorFloat64);
+ }
+
+ if ( ReadThold & SAHPI_STM_UP_CRIT ) {
+ printf( " Upper Critical Threshold: %5.2f\n",
+ sensbuff->UpCritical.Value.SensorFloat64);
+ }
+ if ( ReadThold & SAHPI_STM_UP_MAJOR ) {
+ printf( " Upper Major Threshold: %5.2f\n",
+ sensbuff->UpMajor.Value.SensorFloat64);
+ }
+ if ( ReadThold & SAHPI_STM_UP_MINOR ) {
+ printf( " Upper Minor Threshold: %5.2f\n",
+ sensbuff->UpMinor.Value.SensorFloat64);
+ }
+
+ if ( ReadThold & SAHPI_STM_UP_HYSTERESIS ) {
+ printf( " Positive Threshold Hysteresis: %5.2f\n",
+ sensbuff->PosThdHysteresis.Value.SensorFloat64);
+ }
+ if ( ReadThold & SAHPI_STM_LOW_HYSTERESIS ) {
+ printf( " Negative Threshold Hysteresis: %5.2f\n",
+ sensbuff->NegThdHysteresis.Value.SensorFloat64);
+ }
+#endif
+ printf( "\n");
+}
+
+static
+SaErrorT DoEvent(
+ SaHpiSessionIdT sessionid,
+ SaHpiResourceIdT resourceid,
+ SaHpiSensorRecT *sensorrec )
+{
+ SaHpiSensorNumT sensornum;
+ SaHpiSensorReadingT reading;
+ SaHpiSensorThresholdsT senstbuff1;
+ SaHpiSensorThresholdsT senstbuff2;
+ SaErrorT rv, rv2;
+#ifdef HPI_A
+ SaHpiSensorReadingT conv_reading;
+#else
+ SaHpiEventStateT evtstate;
+#endif
+
+ SaHpiTimeoutT timeout = (SaHpiInt64T)(12 * HPI_NSEC_PER_SEC); /* 12 seconds*/
+ SaHpiEventT event;
+ SaHpiRptEntryT rptentry;
+ SaHpiRdrT rdr;
+ char *unit;
+ int eventflag = 0;
+ int i;
+
+ sensornum = sensorrec->Num;
+
+/* Get current sensor reading */
+#ifdef HPI_A
+ rv = saHpiSensorReadingGet( sessionid, resourceid, sensornum, &reading);
+#else
+ rv = saHpiSensorReadingGet(sessionid,resourceid, sensornum, &reading,&evtstate);
+#endif
+ if (rv != SA_OK) {
+ printf( "saHpiSensorReadingGet error %d\n",rv);
+/* printf("ReadingGet ret=%d\n", rv); */
+ return(rv);
+ }
+
+#ifdef HPI_A
+ /* HPI A has both interpreted and raw. HPI B has only interpreted. */
+ if ((reading.ValuesPresent & SAHPI_SRF_INTERPRETED) == 0 &&
+ (reading.ValuesPresent & SAHPI_SRF_RAW)) {
+ /* only try convert if intrepreted not available. */
+ rv = saHpiSensorReadingConvert(sessionid, resourceid, sensornum,
+ &reading, &conv_reading);
+ if (rv != SA_OK) {
+ printf("raw=%x conv_ret=%d\n", reading.Raw, rv);
+ /* printf("conv_rv=%s\n", decode_error(rv)); */
+ return(rv);
+ } else {
+ reading.Interpreted.Type = conv_reading.Interpreted.Type;
+ reading.Interpreted.Value.SensorUint32 =
+ conv_reading.Interpreted.Value.SensorUint32;
+ }
+ }
+#endif
+
+ /* Determine units of interpreted reading */
+ i = sensorrec->DataFormat.BaseUnits;
+ if (i > NSU) i = 0;
+ unit = units[i];
+ /* We know that reading.Type is float for the chosen sensor. */
+#ifdef HPI_A
+ printf(" = %05.2f %s \n",
+ reading.Interpreted.Value.SensorFloat32, unit);
+#else
+ printf(" = %05.2f %s \n", reading.Value.SensorFloat64, unit);
+#endif
+
+/* Retrieve current threshold setings, twice */
+/* once for backup and once for modification */
+
+ /* Get backup copy */
+ rv = saHpiSensorThresholdsGet(
+ sessionid, resourceid, sensornum, &senstbuff1);
+ if (rv != SA_OK) {
+ printf( "saHpiSensorThresholdsGet error %d\n",rv); return(rv); }
+ /* OpenHPI 2.0.0 ipmi plugin returns -1006 timeout here, why ???? */
+
+ /* Get modification copy */
+ rv = saHpiSensorThresholdsGet(
+ sessionid, resourceid, sensornum, &senstbuff2);
+ if (rv != SA_OK) {
+ printf( "saHpiSensorThresholdsGet error %d\n",rv); return(rv); }
+
+ /* Display current thresholds */
+ if (rv == SA_OK) {
+ printf( " Current\n");
+ ShowThresh( &senstbuff2, sensorrec->ThresholdDefn.ReadThold);
+ }
+
+/* Set new threshold to current reading + 10% */
+#ifdef HPI_A
+ if (fFan) {
+ senstbuff2.LowMajor.Interpreted.Value.SensorFloat32 =
+ reading.Interpreted.Value.SensorFloat32 * (SaHpiFloat32T)1.10;
+ } else {
+ senstbuff2.UpMinor.Interpreted.Value.SensorFloat32 =
+ reading.Interpreted.Value.SensorFloat32 * (SaHpiFloat32T)0.90;
+ senstbuff2.UpMajor.Interpreted.Value.SensorFloat32 =
+ reading.Interpreted.Value.SensorFloat32 * (SaHpiFloat32T)0.05;
+ }
+ if (fdebug) {
+ printf( "ValuesPresent = %x\n", senstbuff2.LowMajor.ValuesPresent);
+ printf( "Values Mask = %x\n", (SAHPI_SRF_RAW));
+ }
+ senstbuff2.LowMajor.ValuesPresent =
+ senstbuff2.LowMajor.ValuesPresent ^ (SAHPI_SRF_RAW);
+ if (fdebug)
+ printf( "ValuesPresent = %x\n", senstbuff2.LowMajor.ValuesPresent);
+#else
+ /* If fan type, set LowMajor, if temp type, set HighMinor. */
+ if (fFan) {
+ senstbuff2.LowMajor.Value.SensorFloat64 =
+ reading.Value.SensorFloat64 * (SaHpiFloat64T)1.10;
+ } else { /* usually Temperature sensor */
+ senstbuff2.UpMinor.Value.SensorFloat64 =
+ reading.Value.SensorFloat64 * (SaHpiFloat64T)0.90;
+ senstbuff2.UpMajor.Value.SensorFloat64 =
+ reading.Value.SensorFloat64 * (SaHpiFloat64T)0.95;
+ }
+#endif
+
+ /* Display new current thresholds */
+ if (rv == SA_OK) {
+ printf( " New\n");
+ ShowThresh( &senstbuff2, sensorrec->ThresholdDefn.ReadThold);
+ }
+
+#ifdef HPI_A
+ /* See what Events are Enabled */
+ rv = saHpiSensorEventEnablesGet(
+ sessionid, resourceid, sensornum, &enables1);
+ if (rv != SA_OK) {
+ printf( "saHpiSensorEventEnablesGet error %d\n",rv); return(rv); }
+
+ printf( "Sensor Event Enables: \n");
+ printf( " Sensor Status = %x\n", enables1.SensorStatus);
+ printf( " Assert Events = %x\n", enables1.AssertEvents);
+ printf( " Deassert Events = %x\n", enables1.DeassertEvents);
+#endif
+
+/*
+ enables1.AssertEvents = 0x0400;
+ enables1.DeassertEvents = 0x0400;
+ rv = saHpiSensorEventEnablesSet(
+ sessionid, resourceid, sensornum, &enables1);
+ if (rv != SA_OK) return(rv);
+*/
+
+
+/************************
+ Temporary exit */
+/*
+ return(rv);
+*/
+
+/* Subscribe to New Events, only */
+printf( "Subscribe to events\n");
+#ifdef HPI_A
+ rv = saHpiSubscribe( sessionid, (SaHpiBoolT)0 );
+#else
+ rv = saHpiSubscribe( sessionid );
+#endif
+ if (rv != SA_OK) {
+ printf( "saHpiSubscribe error %d\n",rv); return(rv); }
+
+/* Set new thresholds */
+printf( "Set new thresholds\n");
+
+ rv = saHpiSensorThresholdsSet(
+ sessionid, resourceid, sensornum, &senstbuff2);
+ if (rv != SA_OK) {
+ printf( "saHpiSensorThresholdsSet error %d\n",rv);
+ /* rv2 = saHpiUnsubscribe( sessionid );
+ if (fxdebug) printf("saHpiUnsubscribe, rv = %d\n",rv2);
+ return(rv); */
+ }
+
+/* Go wait on event to occur */
+printf( "Go and get the event\n");
+ eventflag = 0;
+ while ( eventflag == 0) {
+#ifdef HPI_A
+ rv = saHpiEventGet( sessionid, timeout, &event, &rdr, &rptentry );
+#else
+ timeout = SAHPI_TIMEOUT_BLOCK;
+ timeout = SAHPI_TIMEOUT_IMMEDIATE; /* use this if not threaded */
+ rv = saHpiEventGet( sessionid, timeout, &event, &rdr, &rptentry, NULL);
+#endif
+ if (rv != SA_OK) {
+ if (rv == SA_ERR_HPI_TIMEOUT) {
+ printf( "Time expired during EventGet - Test FAILED\n");
+ /* Reset to the original thresholds */
+ printf( "Reset thresholds\n");
+ rv = saHpiSensorThresholdsSet(
+ sessionid, resourceid, sensornum, &senstbuff1);
+ if (rv != SA_OK) return(rv);
+
+ /* Re-read threshold values */
+ rv = saHpiSensorThresholdsGet(
+ sessionid, resourceid, sensornum, &senstbuff2);
+ if (rv != SA_OK) return(rv);
+ return(rv);
+ } else {
+ printf( "Error %d during EventGet - Test FAILED\n",rv);
+ return(rv);
+ }
+ }
+
+/* Decode the event information */
+printf( "Decode event info\n");
+ if (event.EventType == SAHPI_ET_SENSOR) {
+ printf( "Sensor # = %2d Severity = %2x\n",
+ event.EventDataUnion.SensorEvent.SensorNum, event.Severity );
+ if (event.EventDataUnion.SensorEvent.SensorNum == sensornum) {
+ eventflag = 1;
+ printf( "Got it - Test PASSED\n");
+ }
+ }
+ }
+/* Reset to the original thresholds */
+printf( "Reset thresholds\n");
+ rv = saHpiSensorThresholdsSet(
+ sessionid, resourceid, sensornum, &senstbuff1);
+ if (rv != SA_OK) {
+ printf( "saHpiSensorThresholdsSet error %d\n",rv);
+ rv2 = saHpiUnsubscribe( sessionid );
+ if (fxdebug) printf("saHpiUnsubscribe, rv = %d\n",rv2);
+ return(rv);
+ } else {
+ /* Re-read threshold values */
+ rv = saHpiSensorThresholdsGet( sessionid, resourceid, sensornum,
+ &senstbuff2);
+ if (rv != SA_OK) {
+ printf( "saHpiSensorThresholdsGet error %d\n",rv);
+ } else { /* rv == SA_OK */
+ /* Display reset thresholds */
+ printf( " Reset\n");
+ ShowThresh( &senstbuff2, sensorrec->ThresholdDefn.ReadThold);
+ }
+ } /*end-else SA_OK*/
+
+/* Unsubscribe to future events */
+printf( "Unsubscribe\n");
+ rv2 = saHpiUnsubscribe( sessionid );
+ if (fxdebug) printf("saHpiUnsubscribe, rv = %d\n",rv2);
+
+ return(rv);
+} /*end DoEvent*/
+
+/*
+ * findmatch
+ * returns offset of the match if found, or -1 if not found.
+ */
+static int
+findmatch(char *buffer, int sbuf, char *pattern, int spattern, char figncase)
+{
+ int c, 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++;
+ if (imatch == spattern) return (++j - imatch);
+ } else if (pattern[imatch] == '?') { /*wildcard char*/
+ imatch++;
+ if (imatch == spattern) return (++j - imatch);
+ } else if (figncase == 1) {
+ if ((c & 0x5f) == (pattern[imatch] & 0x5f)) {
+ imatch++;
+ if (imatch == spattern) return (++j - imatch);
+ } else
+ imatch = 0;
+ } else
+ imatch = 0;
+ }
+ return (-1);
+} /*end findmatch */
+
+int
+main(int argc, char **argv)
+{
+ int c;
+#ifdef HPI_A
+ SaHpiVersionT hpiVer;
+ SaHpiRptInfoT rptinfo;
+#endif
+ SaHpiSessionIdT sessionid;
+ SaHpiRptEntryT rptentry;
+ SaHpiEntryIdT rptentryid;
+ SaHpiEntryIdT nextrptentryid;
+ SaHpiEntryIdT entryid;
+ SaHpiEntryIdT nextentryid;
+ SaHpiResourceIdT resourceid;
+ SaHpiRdrT rdr;
+ int firstpass = 1;
+ SaErrorT rv;
+
+ printf("%s ver %s\n", progname,progver);
+ sensor_name = (char *)strdup(s_name);
+ while ( (c = getopt( argc, argv,"ms:xz?")) != EOF )
+ switch(c)
+ {
+ case 'z': fxdebug = 1; /* fall thru to include next setting */
+ case 'x': fdebug = 1; break;
+ case 'm':
+ sensor_name = (char *)strdup(sm_name);
+ fFan = 0; /*assume not a Fan */
+ break;
+ case 's':
+ fsensor = 1;
+ if (optarg) {
+ sensor_name = (char *)strdup(optarg);
+ }
+ break;
+ default:
+ printf("Usage: %s [-xm] [-s sensor_descriptor]\n", progname);
+ printf(" -s Sensor descriptor\n");
+ printf(" -m use Mullins sensor descriptor\n");
+ printf(" -x Display debug messages\n");
+ printf(" -z Display extra debug messages\n");
+ exit(1);
+ }
+#ifdef HPI_A
+ inv = (SaHpiInventoryDataT *)&inbuff[0];
+
+ rv = saHpiInitialize(&hpiVer);
+
+ if (rv != SA_OK) {
+ printf("saHpiInitialize error %d\n",rv);
+ exit(-1);
+ }
+ rv = saHpiSessionOpen(SAHPI_DEFAULT_DOMAIN_ID,&sessionid,NULL);
+ if (rv != SA_OK) {
+ printf("saHpiSessionOpen error %d\n",rv);
+ exit(-1);
+ }
+
+ if (fdebug) printf("Starting Discovery ...\n");
+ rv = saHpiResourcesDiscover(sessionid);
+ if (fdebug) printf("saHpiResourcesDiscover rv = %d\n",rv);
+
+ rv = saHpiRptInfoGet(sessionid,&rptinfo);
+ if (fxdebug) printf("saHpiRptInfoGet rv = %d\n",rv);
+ if (fdebug) printf("RptInfo: UpdateCount = %x, UpdateTime = %lx\n",
+ rptinfo.UpdateCount, (unsigned long)rptinfo.UpdateTimestamp);
+
+#else
+ rv = saHpiSessionOpen(SAHPI_UNSPECIFIED_DOMAIN_ID,&sessionid,NULL);
+ if (rv != SA_OK) {
+ printf("saHpiSessionOpen error %d\n",rv);
+ exit(-1);
+ }
+ if (fdebug) printf("Starting Discovery ...\n");
+ rv = saHpiDiscover(sessionid);
+ if (fdebug) printf("saHpiResourcesDiscover rv = %d\n",rv);
+
+ // rv = saHpiDomainInfoGet(sessionid,&rptinfo);
+ {
+ /*
+ * If OpenHPI, we need to wait extra time before doing
+ * ThresholdsGet because its discovery isn't really done.
+ */
+ sleep(5);
+ }
+#endif
+
+ /* walk the RPT list */
+ rptentryid = SAHPI_FIRST_ENTRY;
+ while ((rv == SA_OK) && (rptentryid != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiRptEntryGet(sessionid,rptentryid,&nextrptentryid,&rptentry);
+ if (rv == SA_OK)
+ {
+ /* walk the RDR list for this RPT entry */
+ entryid = SAHPI_FIRST_ENTRY;
+#ifdef HPI_A
+ rptentry.ResourceTag.Data[rptentry.ResourceTag.DataLength] = 0;
+#endif
+ resourceid = rptentry.ResourceId;
+
+ if (fdebug) printf("rptentry[%d] resourceid=%d\n", entryid,resourceid);
+
+ printf("Resource Tag: %s\n", rptentry.ResourceTag.Data);
+ while ((rv == SA_OK) && (entryid != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiRdrGet(sessionid,resourceid, entryid,&nextentryid, &rdr);
+
+ if (fxdebug) printf("saHpiRdrGet[%d] rv = %d\n",entryid,rv);
+
+ if (rv == SA_OK)
+ {
+ if (rdr.RdrType == SAHPI_SENSOR_RDR)
+ {
+ /*type 2 includes sensor and control records*/
+ rdr.IdString.Data[rdr.IdString.DataLength] = 0;
+#ifdef OLD
+ if (strncmp(rdr.IdString.Data, sensor_name,
+ rdr.IdString.DataLength) == 0)
+#else
+ if (findmatch(rdr.IdString.Data,rdr.IdString.DataLength,
+ sensor_name, strlen(sensor_name),0) >= 0)
+#endif
+ {
+ printf( "%02d %s\t", rdr.RecordId, rdr.IdString.Data);
+ rv = DoEvent( sessionid, resourceid, &rdr.RdrTypeUnion.SensorRec);
+ if (rv != SA_OK)
+ printf( "Returned Error from DoEvent: rv=%d\n", rv);
+ break; /* done with rdr loop */
+ }
+ }
+ if (rv != SA_OK)
+ printf( "Returned HPI Error: rv=%d\n", rv);
+ entryid = nextentryid;
+ }
+ if (firstpass && entryid == SAHPI_LAST_ENTRY) {
+ /* Not found yet, so try again, looking for any Temp */
+ sensor_name = s_pattn;
+ entryid = SAHPI_FIRST_ENTRY;
+ firstpass = 0;
+ fFan = 0; /*Temp not Fan*/
+ }
+ } /*while rdr loop */
+ rptentryid = nextrptentryid;
+ }
+ } /*while rpt loop*/
+ rv = saHpiSessionClose(sessionid);
+#ifdef HPI_A
+ rv = saHpiFinalize();
+#endif
+ exit(0);
+}
+ /* end hpievent.c */
diff --git a/hpiutil/hpifru.c b/hpiutil/hpifru.c
new file mode 100644
index 0000000..c18a5e2
--- /dev/null
+++ b/hpiutil/hpifru.c
@@ -0,0 +1,19 @@
+/*
+ * hpifru.c
+ *
+ * Author: Bill Barkley & Andy Cress
+ * Copyright (c) 2003-2004 Intel Corporation.
+ *
+ * 04/18/03
+ * 06/09/03 - new CustomField parsing, including SystemGUID
+ * 02/19/04 ARCress - generalized BMC tag parsing, created IsTagBmc()
+ * 05/05/04 ARCress - added OpenHPI Mgt Ctlr tag to IsTagBmc()
+ * 09/22/04 ARCress - invbuf size bigger, check null ptr in fixstr
+ * 10/14/04 ARCress - added HPI_B logic, incomplete
+ */
+#ifdef HPI_A
+#include "hpifrua.c"
+#else
+#include "hpifrub.c"
+#endif
+/* end hpifru.c */
diff --git a/hpiutil/hpifrua.c b/hpiutil/hpifrua.c
new file mode 100644
index 0000000..ae41a7d
--- /dev/null
+++ b/hpiutil/hpifrua.c
@@ -0,0 +1,550 @@
+/*
+ * hpifrua.c (hpifru.c for HPI_A)
+ *
+ * Author: Bill Barkley & Andy Cress
+ * Copyright (c) 2003-2005 Intel Corporation.
+ *
+ * 04/18/03
+ * 06/09/03 - new CustomField parsing, including SystemGUID
+ * 02/19/04 ARCress - generalized BMC tag parsing, created IsTagBmc()
+ * 05/05/04 ARCress - added OpenHPI Mgt Ctlr tag to IsTagBmc()
+ * 09/22/04 ARCress - inbuff size bigger, check null ptr in fixstr
+ * 01/11/05 ARCress - skip INVENTORY RDRs that return errors
+ * 03/16/05 ARCress - make sure asset tag is BMC for writes
+ */
+/*M*
+Copyright (c) 2003-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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include "SaHpi.h"
+
+#define NCT 25
+
+char progver[] = "1.4 HPI-A";
+char progname[] = "hpifru";
+char *chasstypes[NCT] = {
+ "Not Defined", "Other", "Unknown", "Desktop", "Low Profile Desktop",
+ "Pizza Box", "Mini Tower", "Tower", "Portable", "Laptop",
+ "Notebook", "Handheld", "Docking Station", "All in One", "Subnotebook",
+ "Space Saving", "Lunch Box", "Main Server", "Expansion", "SubChassis",
+ "Buss Expansion Chassis", "Peripheral Chassis", "RAID Chassis",
+ "Rack-Mount Chassis", "New"
+};
+int fasset = 0;
+int fdebug = 0;
+int fxdebug = 0;
+int i,j,k = 0;
+SaHpiUint32T buffersize;
+SaHpiUint32T actualsize;
+char *asset_tag;
+char inbuff[2048];
+char outbuff[1024];
+SaHpiInventoryDataT *inv;
+SaHpiInventChassisTypeT chasstype;
+SaHpiInventGeneralDataT *dataptr;
+SaHpiTextBufferT *strptr;
+
+#ifdef ANYINVENT
+static int
+IsTagBmc(char *dstr, int dlen)
+{
+ /* if OpenHPI, always return TRUE for any Inventory RDR */
+ return(1);
+}
+#else
+char bmctag[] = "Basbrd Mgmt Ctlr"; /* see IsTagBmc() */
+char bmctag2[] = "Management Controller"; /* see IsTagBmc() */
+/*
+ * findmatch
+ * returns offset of the match if found, or -1 if not found.
+ */
+static int
+findmatch(char *buffer, int sbuf, char *pattern, int spattern, char figncase)
+{
+ int c, 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++;
+ if (imatch == spattern) return (++j - imatch);
+ } else if (pattern[imatch] == '?') { /*wildcard char*/
+ imatch++;
+ if (imatch == spattern) return (++j - imatch);
+ } else if (figncase == 1) {
+ if ((c & 0x5f) == (pattern[imatch] & 0x5f)) {
+ imatch++;
+ if (imatch == spattern) return (++j - imatch);
+ } else
+ imatch = 0;
+ } else
+ imatch = 0;
+ }
+ return (-1);
+} /*end findmatch */
+
+static int
+IsTagBmc(char *dstr, int dlen)
+{
+ int ret = 0;
+ if (strncmp(dstr, bmctag, sizeof(bmctag)) == 0) /* Sahalee */
+ ret = 1;
+ else if (findmatch(dstr,dlen,"BMC",3,1) >= 0) /* mBMC or other */
+ ret = 1;
+ else if (findmatch(dstr,dlen,bmctag2,sizeof(bmctag2),1) >= 0)
+ ret = 1; /* BMC tag for OpenHPI with ipmi plugin */
+ return(ret);
+}
+#endif
+
+static void
+fixstr(SaHpiTextBufferT *strptr)
+{
+ size_t datalen;
+
+ outbuff[0] = 0;
+ if (strptr == NULL) return;
+ datalen = strptr->DataLength;
+ if (datalen > sizeof(outbuff)) datalen = sizeof(outbuff) - 1;
+ if (datalen != 0) {
+ strncpy ((char *)outbuff, (char *)strptr->Data, datalen);
+ outbuff[datalen] = 0;
+ if (fdebug) {
+ printf("TextBuffer: %s, len=%d, dtype=%x lang=%d\n",
+ outbuff, strptr->DataLength,
+ strptr->DataType, strptr->Language);
+ }
+ }
+}
+
+static void
+prtchassinfo(void)
+{
+ chasstype = (SaHpiInventChassisTypeT)inv->DataRecords[i]->RecordData.ChassisInfo.Type;
+ for (k=0; k<NCT; k++) {
+ if (k == chasstype)
+ printf( "Chassis Type : %s\n", chasstypes[k]);
+ }
+
+ dataptr = (SaHpiInventGeneralDataT *)&inv->DataRecords[i]->RecordData.ChassisInfo.GeneralData;
+ strptr=dataptr->Manufacturer;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Chassis Manufacturer: %s\n", outbuff);
+
+ strptr=dataptr->ProductName;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Chassis Name : %s\n", outbuff);
+
+ strptr=dataptr->ProductVersion;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Chassis Version : %s\n", outbuff);
+
+ strptr=dataptr->ModelNumber;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Chassis Model Number: %s\n", outbuff);
+
+ strptr=dataptr->SerialNumber;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Chassis Serial # : %s\n", outbuff);
+
+ strptr=dataptr->PartNumber;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Chassis Part Number : %s\n", outbuff);
+
+ strptr=dataptr->FileId;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Chassis FRU File ID : %s\n", outbuff);
+
+ strptr=dataptr->AssetTag;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Chassis Asset Tag : %s\n", outbuff);
+ if (dataptr->CustomField[0] != 0)
+ {
+ if (dataptr->CustomField[0]->DataLength != 0)
+ strncpy ((char *)outbuff, (char *)dataptr->CustomField[0]->Data,
+ dataptr->CustomField[0]->DataLength);
+ outbuff[dataptr->CustomField[0]->DataLength] = 0;
+ printf( "Chassis OEM Field : %s\n", outbuff);
+ }
+}
+
+static void
+prtprodtinfo(void)
+{
+ int j;
+ dataptr = (SaHpiInventGeneralDataT *)&inv->DataRecords[i]->RecordData.ProductInfo;
+ strptr=dataptr->Manufacturer;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Product Manufacturer: %s\n", outbuff);
+
+ strptr=dataptr->ProductName;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Product Name : %s\n", outbuff);
+
+ strptr=dataptr->ProductVersion;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Product Version : %s\n", outbuff);
+
+ strptr=dataptr->ModelNumber;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Product Model Number: %s\n", outbuff);
+
+ strptr=dataptr->SerialNumber;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Product Serial # : %s\n", outbuff);
+
+ strptr=dataptr->PartNumber;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Product Part Number : %s\n", outbuff);
+
+ strptr=dataptr->FileId;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Product FRU File ID : %s\n", outbuff);
+
+ strptr=dataptr->AssetTag;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Product Asset Tag : %s\n", outbuff);
+
+ for (j = 0; j < 10; j++) {
+ int ii;
+ if (dataptr->CustomField[j] != NULL) {
+ if ((dataptr->CustomField[j]->DataType == 0) &&
+ (dataptr->CustomField[j]->DataLength == 16)) { /*binary GUID*/
+ printf( "IPMI SystemGUID : ");
+ for (ii=0; ii< dataptr->CustomField[j]->DataLength; ii++)
+ printf("%02x", dataptr->CustomField[j]->Data[ii]);
+ printf("\n");
+ } else { /* other text field */
+ dataptr->CustomField[j]->Data[
+ dataptr->CustomField[j]->DataLength] = 0;
+ if (fdebug) {
+ printf("TextBuffer: %s, len=%d, dtype=%x lang=%d\n",
+ dataptr->CustomField[j]->Data,
+ dataptr->CustomField[j]->DataLength,
+ dataptr->CustomField[j]->DataType,
+ dataptr->CustomField[j]->Language);
+ }
+ printf( "Product OEM Field : %s\n",
+ dataptr->CustomField[j]->Data);
+ }
+ } else /* NULL pointer */
+ break;
+ } /*end for*/
+}
+
+static void
+prtboardinfo(void)
+{
+ dataptr = (SaHpiInventGeneralDataT *)&inv->DataRecords[i]->RecordData.BoardInfo;
+ strptr=dataptr->Manufacturer;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Board Manufacturer : %s\n", outbuff);
+
+ strptr=dataptr->ProductName;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Board Product Name : %s\n", outbuff);
+
+ strptr=dataptr->ModelNumber;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Board Model Number : %s\n", outbuff);
+
+ strptr=dataptr->PartNumber;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Board Part Number : %s\n", outbuff);
+
+ strptr=dataptr->ProductVersion;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Board Version : %s\n", outbuff);
+
+ strptr=dataptr->SerialNumber;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Board Serial # : %s\n", outbuff);
+
+ strptr=dataptr->FileId;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Board FRU File ID : %s\n", outbuff);
+
+ strptr=dataptr->AssetTag;
+ fixstr((SaHpiTextBufferT *)strptr);
+ printf( "Board Asset Tag : %s\n", outbuff);
+
+ if (dataptr->CustomField[0] != 0)
+ {
+ if (dataptr->CustomField[0]->DataLength != 0)
+ strncpy ((char *)outbuff, (char *)dataptr->CustomField[0]->Data,
+ dataptr->CustomField[0]->DataLength);
+ outbuff[dataptr->CustomField[0]->DataLength] = 0;
+ printf( "Board OEM Field : %s\n", outbuff);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int prodrecindx=0;
+ int asset_len=0;
+ int c;
+ SaErrorT rv;
+ SaHpiVersionT hpiVer;
+ SaHpiSessionIdT sessionid;
+ SaHpiRptInfoT rptinfo;
+ SaHpiRptEntryT rptentry;
+ SaHpiEntryIdT rptentryid;
+ SaHpiEntryIdT nextrptentryid;
+ SaHpiEntryIdT entryid;
+ SaHpiEntryIdT nextentryid;
+ SaHpiResourceIdT resourceid;
+ SaHpiRdrT rdr;
+ SaHpiEirIdT eirid;
+
+ printf("%s ver %s\n",progname,progver);
+
+ while ( (c = getopt( argc, argv,"a:xz?")) != EOF )
+ switch(c) {
+ case 'z': fxdebug = 1; /* fall thru to include next setting */
+ case 'x': fdebug = 1; break;
+ case 'a':
+ fasset = 1;
+ if (optarg)
+ {
+ asset_tag = (char *)strdup(optarg);
+ asset_len = strlen(optarg);
+ }
+ /*
+ printf( "String Length = %d\n", asset_len);
+ printf( "String Length = %d\n", strlen(optarg));
+ */
+ break;
+ default:
+ printf("Usage: %s [-x] [-a asset_tag]\n", progname);
+ printf(" -a Sets the asset tag\n");
+ printf(" -x Display debug messages\n");
+ printf(" -z Display extra debug messages\n");
+ exit(1);
+ }
+ inv = (SaHpiInventoryDataT *)&inbuff[0];
+ rv = saHpiInitialize(&hpiVer);
+ if (rv != SA_OK) {
+ printf("saHpiInitialize error %d\n",rv);
+ exit(-1);
+ }
+ rv = saHpiSessionOpen(SAHPI_DEFAULT_DOMAIN_ID,&sessionid,NULL);
+ if (rv != SA_OK) {
+ printf("saHpiSessionOpen error %d\n",rv);
+ exit(-1);
+ }
+
+ rv = saHpiResourcesDiscover(sessionid);
+ if (fxdebug) printf("saHpiResourcesDiscover rv = %d\n",rv);
+ rv = saHpiRptInfoGet(sessionid,&rptinfo);
+ if (fxdebug) printf("saHpiRptInfoGet rv = %d\n",rv);
+ if (fdebug) printf("RptInfo: UpdateCount = %x, UpdateTime = %lx\n",
+ rptinfo.UpdateCount, (unsigned long)rptinfo.UpdateTimestamp);
+
+ /* walk the RPT list */
+ rptentryid = SAHPI_FIRST_ENTRY;
+ while ((rv == SA_OK) && (rptentryid != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiRptEntryGet(sessionid,rptentryid,&nextrptentryid,&rptentry);
+ if (rv != SA_OK) printf("RptEntryGet: rv = %d\n",rv);
+ if (rv == SA_OK)
+ {
+ /* walk the RDR list for this RPT entry */
+ entryid = SAHPI_FIRST_ENTRY;
+ /* OpenHPI sometimes has bad RPT DataLength here. */
+ rptentry.ResourceTag.Data[rptentry.ResourceTag.DataLength] = 0;
+ resourceid = rptentry.ResourceId;
+ printf("Resource Tag: %s\n", rptentry.ResourceTag.Data);
+ if (fdebug) printf("rptentry[%d] resourceid=%d\n", rptentryid,resourceid);
+ while ((rv == SA_OK) && (entryid != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiRdrGet(sessionid,resourceid, entryid,&nextentryid, &rdr);
+ if (fxdebug) printf("saHpiRdrGet[%d] rv = %d\n",entryid,rv);
+ if (rv == SA_OK)
+ {
+ if (rdr.RdrType == SAHPI_INVENTORY_RDR)
+ {
+ /*type 3 includes inventory records*/
+ eirid = rdr.RdrTypeUnion.InventoryRec.EirId;
+ rdr.IdString.Data[rdr.IdString.DataLength] = 0;
+ if (fdebug) printf( "RDR[%d]: Inventory, type=%d num=%d %s\n",
+ rdr.RecordId, rdr.RdrType, eirid, rdr.IdString.Data);
+ else printf("RDR[%d]: %s \n",rdr.RecordId,rdr.IdString.Data);
+
+ buffersize = sizeof(inbuff);
+ if (fdebug) printf("BufferSize=%d InvenDataRecSize=%d\n",
+ buffersize, sizeof(inbuff));
+ /* Always get inventory data, not just for BMC */
+ /* if ( IsTagBmc(rdr.IdString.Data, rdr.IdString.DataLength) ) */
+ {
+ memset(inv,0,buffersize);
+ if (fdebug) printf("InventoryDataRead (%d, %d, %d, %d, %p, %d)\n",
+ sessionid, resourceid, eirid, buffersize, inv,
+ actualsize);
+
+ rv = saHpiEntityInventoryDataRead( sessionid, resourceid,
+ eirid, buffersize, inv, &actualsize);
+ if (fdebug) {
+ printf("saHpiEntityInventoryDataRead[%d] rv = %d\n",eirid,rv);
+ printf("buffersize = %d, ActualSize=%d\n",
+ buffersize,actualsize);
+ }
+ if (rv == SA_OK || rv == -2000) // (0 - buffersize))
+ {
+ /* Walk thru the list of inventory data */
+ for (i=0; inv->DataRecords[i] != NULL; i++)
+ {
+ if (fdebug) printf( "Record index=%d type=%x len=%d\n",
+ i, inv->DataRecords[i]->RecordType,
+ inv->DataRecords[i]->DataLength);
+ if (inv->Validity == SAHPI_INVENT_DATA_VALID)
+ {
+ switch (inv->DataRecords[i]->RecordType)
+ {
+ case SAHPI_INVENT_RECTYPE_INTERNAL_USE:
+ if (fdebug) printf( "Internal Use\n");
+ break;
+ case SAHPI_INVENT_RECTYPE_PRODUCT_INFO:
+ if (fdebug) printf( "Product Info\n");
+ prodrecindx = i;
+ prtprodtinfo();
+ break;
+ case SAHPI_INVENT_RECTYPE_CHASSIS_INFO:
+ if (fdebug) printf( "Chassis Info\n");
+ prtchassinfo();
+ break;
+ case SAHPI_INVENT_RECTYPE_BOARD_INFO:
+ if (fdebug) printf( "Board Info\n");
+ prtboardinfo();
+ break;
+ case SAHPI_INVENT_RECTYPE_OEM:
+ if (fdebug) printf( "OEM Record\n");
+ break;
+ default:
+ printf(" Invalid Invent Rec Type =%x\n",
+ inv->DataRecords[i]->RecordType);
+ break;
+ }
+ }
+ }
+ /* Cannot guarantee writable unless it is the BMC. */
+ if (IsTagBmc(rdr.IdString.Data,rdr.IdString.DataLength)
+ && (fasset == 1))
+ { /* handle asset tag */
+ SaHpiTextBufferT aTag;
+ if (fdebug) printf( "Inventory = %s\n", rdr.IdString.Data);
+ /* prodrecindx contains index for Prod Rec Type */
+ dataptr = (SaHpiInventGeneralDataT *)
+ &inv->DataRecords[prodrecindx]->RecordData.ProductInfo;
+ dataptr->AssetTag = &aTag;
+ strptr=dataptr->AssetTag;
+ strptr->DataType = SAHPI_TL_TYPE_LANGUAGE;
+ strptr->Language = SAHPI_LANG_ENGLISH;
+ strptr->DataLength = (SaHpiUint8T)asset_len;
+ strncpy( (char *)strptr->Data, (char *)asset_tag,asset_len);
+ strptr->Data[asset_len] = 0;
+
+ printf( "Writing new asset tag: %s\n",(char *)strptr->Data);
+ rv = saHpiEntityInventoryDataWrite( sessionid,
+ resourceid, eirid, inv);
+ printf("Return Write Status = %d\n", rv);
+
+ if (rv == SA_OK)
+ {
+ printf ("Good write - re-reading!\n");
+ rv = saHpiEntityInventoryDataRead( sessionid, resourceid,
+ eirid, buffersize, inv, &actualsize);
+ if (fxdebug) printf(
+ "saHpiEntityInventoryDataRead[%d] rv = %d\n", eirid, rv);
+ if (fdebug) printf("ActualSize=%d\n", actualsize);
+ if (rv == SA_OK)
+ {
+ /* Walk thru the list of inventory data */
+ for (i=0; inv->DataRecords[i] != NULL; i++)
+ {
+ if (inv->Validity == SAHPI_INVENT_DATA_VALID)
+ {
+ if (fdebug) printf( "Index = %d type=%x len=%d\n",
+ i, inv->DataRecords[i]->RecordType,
+ inv->DataRecords[i]->DataLength);
+ switch (inv->DataRecords[i]->RecordType)
+ {
+ case SAHPI_INVENT_RECTYPE_INTERNAL_USE:
+ if (fdebug) printf( "Internal Use\n");
+ break;
+ case SAHPI_INVENT_RECTYPE_PRODUCT_INFO:
+ if (fdebug) printf( "Product Info\n");
+ prtprodtinfo();
+ break;
+ case SAHPI_INVENT_RECTYPE_CHASSIS_INFO:
+ if (fdebug) printf( "Chassis Info\n");
+ prtchassinfo();
+ break;
+ case SAHPI_INVENT_RECTYPE_BOARD_INFO:
+ if (fdebug) printf( "Board Info\n");
+ prtboardinfo();
+ break;
+ case SAHPI_INVENT_RECTYPE_OEM:
+ if (fdebug) printf( "OEM Record\n");
+ break;
+ default:
+ printf(" Invalid Invent Rec Type =%x\n",
+ inv->DataRecords[i]->RecordType);
+ break;
+ }
+ }
+ }
+ } /*re-walk the inventory record list */
+ } /* Good write - re-read */
+ } /* check asset tag flag */
+ } else {
+ /* It is an Inventory RDR, but gets error reading FRU. */
+ if (fdebug) printf("\tinventory read error, rv=%d\n", rv);
+ rv = 0; /* keep trying another RDR */
+ entryid = nextentryid;
+ continue;
+ }
+ }
+ } /* Inventory Data Records - Type 3 */
+ entryid = nextentryid;
+ }
+ }
+ rptentryid = nextrptentryid;
+ }
+ }
+ rv = saHpiSessionClose(sessionid);
+ rv = saHpiFinalize();
+ exit(0);
+}
+ /* end hpifru.c */
diff --git a/hpiutil/hpifrub.c b/hpiutil/hpifrub.c
new file mode 100644
index 0000000..822127c
--- /dev/null
+++ b/hpiutil/hpifrub.c
@@ -0,0 +1,619 @@
+/* -*- linux-c -*-
+ *
+ * hpiinv.c
+ *
+ * Copyright (c) 2003-2005 by Intel Corp.
+ * (C) Copyright IBM Corp. 2004
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. This
+ * file and program are licensed under a BSD style license. See
+ * the Copying file included with the OpenHPI distribution for
+ * full licensing terms.
+ *
+ * Authors:
+ * Andy Cress <arcress at users.sourceforge.net>
+ * Peter D. Phan <pdphan@users.sourceforge.net>
+ * Renier Morales <renierm@users.sf.net>
+ * Tariq Shureih <tariq.shureih@intel.com>
+ * Racing Guo <racing.guo@intel.com>
+ *
+ * Log:
+ * 6/29/04 Copied from hpifru.c and modified for general use
+ * 11/30/04 ver 0.2 for openhpi-2.0.0
+ * 2/09/05 ARCress re-merged with hpifru.c, adding IdrFieldSet,
+ * generalized for other HPI libraris also.
+ */
+// #define OPENHPI_USED 1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <SaHpi.h>
+#ifdef OPENHPI_USED
+#include <oh_utils.h>
+#endif
+
+#define NCT 25
+#define MAX_STRSIZE 64
+
+char progver[] = "1.5 HPI-B";
+char progname[] = "hpiinv";
+char *chasstypes[NCT] = {
+ "Not Defined", "Other", "Unknown", "Desktop", "Low Profile Desktop",
+ "Pizza Box", "Mini Tower", "Tower", "Portable", "Laptop",
+ "Notebook", "Handheld", "Docking Station", "All in One", "Subnotebook",
+ "Space Saving", "Lunch Box", "Main Server", "Expansion", "SubChassis",
+ "Buss Expansion Chassis", "Peripheral Chassis", "RAID Chassis",
+ "Rack-Mount Chassis", "New"
+};
+int fasset = 0;
+int fverbose = 0;
+int foundasset = 0;
+int fdebug = 0;
+int fzdebug = 0;
+int i,j,k = 0;
+SaHpiUint32T buffersize;
+SaHpiUint32T actualsize;
+char inbuff[2048];
+char outbuff[1024];
+SaHpiIdrAreaHeaderT *inv;
+SaHpiIdrFieldTypeT chasstype;
+SaHpiTextBufferT *strptr;
+struct {
+ SaHpiResourceIdT rid;
+ SaHpiEntryIdT idrid;
+ SaHpiEntryIdT areaid;
+ SaHpiEntryIdT fieldid;
+ char *tag;
+ int tlen;
+ } atag;
+#define NRW_ENTS 12
+SaHpiEntityTypeT rw_entities[NRW_ENTS] = { /*read-writable entities*/
+ SAHPI_ENT_SYS_MGMNT_MODULE,
+ SAHPI_ENT_SYSTEM_BOARD,
+ SAHPI_ENT_FRONT_PANEL_BOARD,
+ SAHPI_ENT_SYSTEM_CHASSIS,
+ SAHPI_ENT_SYS_MGMNT_SOFTWARE,
+ SAHPI_ENT_COMPACTPCI_CHASSIS,
+ SAHPI_ENT_ADVANCEDTCA_CHASSIS,
+ SAHPI_ENT_RACK_MOUNTED_SERVER,
+ SAHPI_ENT_SYSTEM_BLADE,
+ SAHPI_ENT_SWITCH_BLADE,
+ SAHPI_ENT_SPEC_PROC_BLADE,
+ SAHPI_ENT_ALARM_MANAGER };
+
+#ifdef BMCONLY
+char bmctag[] = "Basbrd Mgmt Ctlr"; /* see IsTagBmc() */
+char bmctag2[] = "Management Controller"; /* see IsTagBmc() */
+
+/*
+ * findmatch
+ * returns offset of the match if found, or -1 if not found.
+ */
+static int
+findmatch(char *buffer, int sbuf, char *pattern, int spattern, char figncase)
+{
+ int c, 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++;
+ if (imatch == spattern) return (++j - imatch);
+ } else if (pattern[imatch] == '?') { /*wildcard char*/
+ imatch++;
+ if (imatch == spattern) return (++j - imatch);
+ } else if (figncase == 1) {
+ if ((c & 0x5f) == (pattern[imatch] & 0x5f)) {
+ imatch++;
+ if (imatch == spattern) return (++j - imatch);
+ } else
+ imatch = 0;
+ } else
+ imatch = 0;
+ }
+ return (-1);
+} /*end findmatch */
+
+static int
+IsTagBmc(char *dstr, int dlen)
+{
+ int ret = 0;
+
+ if (strncmp(dstr, bmctag, sizeof(bmctag)) == 0) /* Sahalee */
+ ret = 1;
+ else if (findmatch(dstr,dlen,"BMC",3,1) >= 0) /* mBMC or other */
+ ret = 1;
+ else if (findmatch(dstr,dlen,bmctag2,sizeof(bmctag2),1) >= 0)
+ ret = 1; /* BMC tag for OpenHPI with ipmi plugin */
+ return(ret);
+}
+#else
+static int
+IsTagBmc(char *dstr, int dlen)
+{
+ /* if OpenHPI, always return TRUE for any Inventory RDR */
+ return(1);
+}
+#endif
+
+static int
+ent_writable(SaHpiEntityPathT *ep, SaHpiIdrInfoT *idrinfo)
+{
+ int i, rv;
+ /* The IdrInfo ReadOnly field might be ok, but we don't
+ even want to attempt to write to DIMMs or Power Supplies,
+ even if the plugin reports it otherwise, so only check
+ for known writable entity types. */
+ for (i = 0; i < NRW_ENTS; i++)
+ if (rw_entities[i] == ep->Entry[0].EntityType) break;
+ if (i >= NRW_ENTS) rv = 0;
+ else rv = 1;
+ return(rv);
+}
+
+static void
+fixstr(SaHpiTextBufferT *strptr, char *outstr)
+{
+ size_t datalen;
+
+ if (outstr == NULL) return;
+ outstr[0] = 0;
+ if (strptr == NULL) return;
+ datalen = strptr->DataLength;
+ if (datalen > MAX_STRSIZE) datalen = MAX_STRSIZE-1;
+ if (datalen != 0) {
+ strncpy ((char *)outstr, (char *)strptr->Data, datalen);
+ outstr[datalen] = 0;
+ if (fdebug) {
+ printf("TextBuffer len=%d, dtype=%x lang=%d: %s\n",
+ strptr->DataLength,strptr->DataType,strptr->Language,
+ strptr->Data );
+ }
+ }
+#ifdef LENGTH_BAD
+ else /* may be bogus length, try anyway */
+ strcpy ((char *)outstr, (char *)strptr->Data);
+#endif
+}
+
+#define NAREATYP 6
+static struct { SaHpiUint8T type; char *str;
+} map_areatype[NAREATYP] = {
+ { SAHPI_IDR_AREATYPE_INTERNAL_USE, "Internal Area" },
+ { SAHPI_IDR_AREATYPE_CHASSIS_INFO, "Chassis Area" },
+ { SAHPI_IDR_AREATYPE_BOARD_INFO, "Board Area" },
+ { SAHPI_IDR_AREATYPE_PRODUCT_INFO, "Product Area" },
+ { SAHPI_IDR_AREATYPE_OEM, "OEM Area" },
+ { SAHPI_IDR_AREATYPE_UNSPECIFIED, "Unspecified Area" }
+};
+
+#define NFIELDTYP 11
+static struct { SaHpiUint8T type; char *str;
+} map_fieldtype[NFIELDTYP] = {
+ { SAHPI_IDR_FIELDTYPE_CHASSIS_TYPE, "Chassis Type "},
+ { SAHPI_IDR_FIELDTYPE_MFG_DATETIME, "Mfg DateTime "},
+ { SAHPI_IDR_FIELDTYPE_MANUFACTURER, "Manufacturer "},
+ { SAHPI_IDR_FIELDTYPE_PRODUCT_NAME, "Product Name "},
+ { SAHPI_IDR_FIELDTYPE_PRODUCT_VERSION, "Product Versn"},
+ { SAHPI_IDR_FIELDTYPE_SERIAL_NUMBER, "Serial Number"},
+ { SAHPI_IDR_FIELDTYPE_PART_NUMBER, "Part Number "},
+ { SAHPI_IDR_FIELDTYPE_FILE_ID, "File ID "},
+ { SAHPI_IDR_FIELDTYPE_ASSET_TAG, "Asset Tag "},
+ { SAHPI_IDR_FIELDTYPE_CUSTOM, "Custom Field "},
+ { SAHPI_IDR_FIELDTYPE_UNSPECIFIED, "Unspecified "}
+};
+
+#define NEPTYPES 67
+struct { SaHpiEntityTypeT type; char *str; } map_epstr[NEPTYPES] = {
+ { SAHPI_ENT_ADD_IN_CARD, "ADD_IN_CARD" },
+ { SAHPI_ENT_ADVANCEDTCA_CHASSIS, "ADVANCEDTCA_CHASSIS" },
+ { SAHPI_ENT_ALARM_MANAGER, "ALARM_MANAGER" },
+ { SAHPI_ENT_BACK_PANEL_BOARD, "BACK_PANEL_BOARD" },
+ { SAHPI_ENT_BATTERY, "BATTERY" },
+ { SAHPI_ENT_BIOS, "BIOS" },
+ { SAHPI_ENT_BOARD_SET_SPECIFIC, "BOARD_SET_SPECIFIC" },
+ { SAHPI_ENT_CHASSIS_BACK_PANEL_BOARD, "CHASSIS_BACK_PANEL_BOARD" },
+ { SAHPI_ENT_CHASSIS_SPECIFIC, "CHASSIS_SPECIFIC" },
+ { SAHPI_ENT_COMPACTPCI_CHASSIS, "COMPACTPCI_CHASSIS" },
+ { SAHPI_ENT_COOLING_DEVICE, "COOLING_DEVICE" },
+ { SAHPI_ENT_COOLING_UNIT, "COOLING_UNIT" },
+ { SAHPI_ENT_DEVICE_BAY, "DEVICE_BAY" },
+ { SAHPI_ENT_DISK_BAY, "DISK_BAY" },
+ { SAHPI_ENT_DISK_BLADE, "DISK_BLADE" },
+ { SAHPI_ENT_DISK_DRIVE, "DISK_DRIVE" },
+ { SAHPI_ENT_DISK_DRIVE_BAY, "DISK_DRIVE_BAY" },
+ { SAHPI_ENT_DISPLAY_PANEL, "DISPLAY_PANEL" },
+ { SAHPI_ENT_DRIVE_BACKPLANE, "DRIVE_BACKPLANE" },
+ { SAHPI_ENT_EXTERNAL_ENVIRONMENT, "EXTERNAL_ENVIRONMENT" },
+ { SAHPI_ENT_FAN, "FAN" },
+ { SAHPI_ENT_FRONT_PANEL_BOARD, "FRONT_PANEL_BOARD" },
+ { SAHPI_ENT_GROUP, "GROUP" },
+ { SAHPI_ENT_INTERCONNECT, "INTERCONNECT" },
+ { SAHPI_ENT_IO_BLADE, "IO_BLADE" },
+ { SAHPI_ENT_IO_SUBBOARD, "IO_SUBBOARD" },
+ { SAHPI_ENT_MEMORY_DEVICE, "MEMORY_DEVICE" },
+ { SAHPI_ENT_MEMORY_MODULE, "MEMORY_MODULE" },
+ { SAHPI_ENT_OEM_SYSINT_SPECIFIC, "OEM_SYSINT_SPECIFIC" },
+ { SAHPI_ENT_OPERATING_SYSTEM, "OPERATING_SYSTEM" },
+ { SAHPI_ENT_OTHER, "OTHER" },
+ { SAHPI_ENT_OTHER_CHASSIS_BOARD, "OTHER_CHASSIS_BOARD" },
+ { SAHPI_ENT_OTHER_SYSTEM_BOARD, "OTHER_SYSTEM_BOARD" },
+ { SAHPI_ENT_PERIPHERAL_BAY, "PERIPHERAL_BAY" },
+ { SAHPI_ENT_PERIPHERAL_BAY_2, "PERIPHERAL_BAY_2" },
+ { SAHPI_ENT_PHYSICAL_SLOT, "PHYSICAL_SLOT" },
+ { SAHPI_ENT_POWER_DISTRIBUTION_UNIT, "POWER_DISTRIBUTION_UNIT" },
+ { SAHPI_ENT_POWER_MGMNT, "POWER_MGMNT" },
+ { SAHPI_ENT_POWER_MODULE, "POWER_MODULE" },
+ { SAHPI_ENT_POWER_SUPPLY, "POWER_SUPPLY" },
+ { SAHPI_ENT_POWER_SYSTEM_BOARD, "POWER_SYSTEM_BOARD" },
+ { SAHPI_ENT_POWER_UNIT, "POWER_UNIT" },
+ { SAHPI_ENT_PROCESSOR, "PROCESSOR" },
+ { SAHPI_ENT_PROCESSOR_BOARD, "PROCESSOR_BOARD" },
+ { SAHPI_ENT_PROCESSOR_MODULE, "PROCESSOR_MODULE" },
+ { SAHPI_ENT_RACK, "RACK" },
+ { SAHPI_ENT_RACK_MOUNTED_SERVER, "RACK_MOUNTED_SERVER" },
+ { SAHPI_ENT_REMOTE, "REMOTE" },
+ { SAHPI_ENT_ROOT, "ROOT" },
+ { SAHPI_ENT_SBC_BLADE, "SBC_BLADE" },
+ { SAHPI_ENT_SBC_SUBBOARD, "SBC_SUBBOARD" },
+ { SAHPI_ENT_SHELF_MANAGER, "SHELF_MANAGER" },
+ { SAHPI_ENT_SPEC_PROC_BLADE, "SPEC_PROC_BLADE" },
+ { SAHPI_ENT_SUBBOARD_CARRIER_BLADE, "SUBBOARD_CARRIER_BLADE" },
+ { SAHPI_ENT_SUB_CHASSIS, "SUB_CHASSIS" },
+ { SAHPI_ENT_SUBRACK, "SUBRACK" },
+ { SAHPI_ENT_SWITCH, "SWITCH" },
+ { SAHPI_ENT_SWITCH_BLADE, "SWITCH_BLADE" },
+ { SAHPI_ENT_SYS_EXPANSION_BOARD, "SYS_EXPANSION_BOARD" },
+ { SAHPI_ENT_SYS_MGMNT_MODULE, "SYS_MGMNT_MODULE" },
+ { SAHPI_ENT_SYS_MGMNT_SOFTWARE, "SYS_MGMNT_SOFTWARE" },
+ { SAHPI_ENT_SYSTEM_BLADE, "SYSTEM_BLADE" },
+ { SAHPI_ENT_SYSTEM_BOARD, "SYSTEM_BOARD" },
+ { SAHPI_ENT_SYSTEM_BUS, "SYSTEM_BUS" },
+ { SAHPI_ENT_SYSTEM_CHASSIS, "SYSTEM_CHASSIS" },
+ { SAHPI_ENT_UNKNOWN, "UNKNOWN" },
+ { SAHPI_ENT_UNSPECIFIED, "UNSPECIFIED" },
+};
+
+static void print_epath(SaHpiEntityPathT *epath, int len);
+static void print_epath(SaHpiEntityPathT *epath, int len)
+{
+ int i,j;
+ SaHpiEntityTypeT t;
+ char *pstr;
+
+#ifdef OPENHPI_USED
+ if (fverbose) {
+ oh_print_ep(epath, len);
+ } else
+#endif
+ {
+ for (i = 0; i < SAHPI_MAX_ENTITY_PATH; i++) {
+ t = epath->Entry[i].EntityType;
+ pstr = "";
+ for (j = 0; j < NEPTYPES; j++) {
+ if (t == map_epstr[j].type) {
+ pstr = map_epstr[j].str;
+ break;
+ }
+ }
+ if (j == NEPTYPES) j--;
+ printf("{%s:%d} ",pstr, epath->Entry[i].EntityLocation);
+ if (t == SAHPI_ENT_ROOT) break;
+ }
+ printf("\n");
+ }
+ return;
+}
+
+static void print_idrinfo(SaHpiIdrInfoT *idrInfo,int len);
+static void print_idrinfo(SaHpiIdrInfoT *idrInfo,int len)
+{
+#ifdef OPENHPI_USED
+ if (fverbose) {
+ oh_print_idrinfo(idrInfo, len);
+ } else
+#endif
+ { /* don't need to show this if not fverbose */
+ }
+}
+
+static void print_idrareaheader(SaHpiIdrAreaHeaderT *areaHeader, int len);
+static void print_idrareaheader(SaHpiIdrAreaHeaderT *areaHeader, int len)
+{
+ int i;
+#ifdef OPENHPI_USED
+ if (fverbose) {
+ oh_print_idrareaheader(areaHeader, len);
+ } else
+#endif
+ {
+ for (i = 0; i < NAREATYP; i++) {
+ if (map_areatype[i].type == areaHeader->Type) break;
+ }
+ if (i == NAREATYP) i--;
+ printf("AreaId[%d] %s\n",areaHeader->AreaId,map_areatype[i].str);
+ }
+}
+
+static void print_idrfield(SaHpiIdrFieldT *field, int len);
+static void print_idrfield(SaHpiIdrFieldT *field, int len)
+{
+ SaHpiTextBufferT *strptr;
+ char fieldstr[MAX_STRSIZE];
+ int i;
+
+#ifdef OPENHPI_USED
+ if (fverbose) {
+ oh_print_idrfield(field, len);
+ } else
+#endif
+ {
+ for (i = 0; i < NFIELDTYP; i++) {
+ if (map_fieldtype[i].type == field->Type) break;
+ }
+ if (i == NFIELDTYP) i--;
+ strptr = &(field->Field);
+ fixstr(strptr,fieldstr); /*stringify if needed*/
+ printf(" FieldId[%d] %s : %s\n",
+ field->FieldId,map_fieldtype[i].str ,fieldstr);
+ }
+}
+
+int walkInventory(SaHpiSessionIdT sessionid, SaHpiResourceIdT resourceid,
+ SaHpiIdrInfoT *idrInfo);
+int walkInventory(SaHpiSessionIdT sessionid, SaHpiResourceIdT resourceid,
+ SaHpiIdrInfoT *idrInfo)
+{
+
+ SaErrorT rv = SA_OK,
+ rvField = SA_OK;
+
+ SaHpiUint32T numAreas;
+ SaHpiUint32T countAreas = 0;
+ SaHpiUint32T countFields = 0;
+
+ SaHpiEntryIdT areaId;
+ SaHpiEntryIdT nextareaId;
+ SaHpiIdrAreaTypeT areaType;
+ SaHpiIdrAreaHeaderT areaHeader;
+
+ SaHpiEntryIdT fieldId;
+ SaHpiEntryIdT nextFieldId;
+ SaHpiIdrFieldTypeT fieldType;
+ SaHpiIdrFieldT thisField;
+
+ numAreas = idrInfo->NumAreas;
+ areaType = SAHPI_IDR_AREATYPE_UNSPECIFIED;
+ areaId = SAHPI_FIRST_ENTRY;
+ foundasset = 0;
+ while ((rv == SA_OK) && (areaId != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiIdrAreaHeaderGet(sessionid, resourceid,
+ idrInfo->IdrId, areaType,
+ areaId, &nextareaId,
+ &areaHeader);
+ if (rv == SA_OK) {
+ countAreas++;
+ print_idrareaheader(&areaHeader, 8);
+
+ fieldType = SAHPI_IDR_FIELDTYPE_UNSPECIFIED;
+ fieldId = SAHPI_FIRST_ENTRY;
+ countFields = 0;
+
+ while ((rvField == SA_OK) && (fieldId != SAHPI_LAST_ENTRY))
+ {
+ rvField = saHpiIdrFieldGet( sessionid, resourceid,
+ idrInfo->IdrId,
+ areaHeader.AreaId, fieldType,
+ fieldId, &nextFieldId,
+ &thisField);
+ if (fdebug)
+ printf("saHpiIdrFieldGet[%x] rv = %d type=%d\n",
+ idrInfo->IdrId,rvField,
+ thisField.Type);
+ if (rvField == SA_OK) {
+ countFields++;
+ print_idrfield(&thisField, 12);
+ if (thisField.Type == SAHPI_IDR_FIELDTYPE_ASSET_TAG) {
+ atag.rid = resourceid;
+ atag.idrid = idrInfo->IdrId;
+ atag.areaid = areaHeader.AreaId;
+ atag.fieldid = fieldId;
+ foundasset = 1;
+ }
+ }
+ fieldId = nextFieldId;
+ } /*while fields*/
+
+ if ( countFields != areaHeader.NumFields)
+ printf("Area Header error: areaHeader.NumFields %d, countFields %d\n",
+ areaHeader.NumFields, countFields);
+ } else {
+ printf("saHpiIdrAreaHeaderGet error %d\n",rv);
+ }
+ areaId = nextareaId;
+
+ } /*while areas*/
+
+ if ((rv == SA_OK) && (countAreas != numAreas))
+ printf("idrInfo error! idrInfo.NumAreas = %d; countAreas = %d\n",
+ numAreas, countAreas);
+
+ if (countFields > 0) rv = 0;
+ return(rv);
+} /*end walkInventory*/
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ SaErrorT rv;
+ SaHpiSessionIdT sessionid;
+ SaHpiDomainInfoT rptinfo;
+ SaHpiRptEntryT rptentry;
+ SaHpiEntryIdT rptentryid;
+ SaHpiEntryIdT nextrptentryid;
+ SaHpiEntryIdT entryid;
+ SaHpiEntryIdT nextentryid;
+ SaHpiResourceIdT resourceid;
+ SaHpiRdrT rdr;
+ SaHpiIdrInfoT idrInfo;
+ SaHpiIdrIdT idrid;
+ int invfound = 0;
+ int nloops = 0;
+
+ printf("%s ver %s\n",progname,progver);
+ atag.tlen = 0;
+
+ while ( (c = getopt( argc, argv,"a:vxz?")) != EOF )
+ switch(c) {
+ case 'z': fzdebug = 1; /* fall thru to include next setting */
+ case 'x': fdebug = 1; break;
+ case 'v': fverbose = 1; break;
+ case 'a':
+ fasset = 1;
+ if (optarg) {
+ atag.tag = (char *)strdup(optarg);
+ atag.tlen = strlen(optarg);
+ }
+ break;
+ default:
+ printf("Usage: %s [-x] [-a asset_tag]\n", progname);
+ printf(" -a Sets the asset tag\n");
+ printf(" -x Display debug messages\n");
+ printf(" -z Display extra debug messages\n");
+ exit(1);
+ }
+
+ inv = (SaHpiIdrAreaHeaderT *)&inbuff[0];
+ rv = saHpiSessionOpen(SAHPI_UNSPECIFIED_DOMAIN_ID,&sessionid,NULL);
+ if (fdebug) printf("saHpiSessionOpen rv = %d sessionid = %x\n",rv,sessionid);
+ if (rv != SA_OK) {
+ printf("saHpiSessionOpen error %d\n",rv);
+ exit(-1);
+ }
+
+ rv = saHpiDomainInfoGet(sessionid,&rptinfo);
+ if (fdebug) printf("saHpiDomainInfoGet rv = %d\n",rv);
+ // if (fdebug) printf("RptInfo: UpdateCount = %x, UpdateTime = %lx\n",
+ // rptinfo.UpdateCount, (unsigned long)rptinfo.UpdateTimestamp);
+
+ while (!invfound && (nloops < 7))
+ {
+ /*
+ * The OpenHPI ipmi plugin has a bug whereby the FRU RDR is added
+ * much later, and always requires a rediscovery. (bug #1095256)
+ * This should not apply to other well-behaved plugins.
+ */
+ nloops++;
+ if (fdebug) printf("Starting Discovery, pass %d ...\n",nloops);
+ rv = saHpiDiscover(sessionid);
+ if (fdebug) printf("saHpiDiscover rv = %d\n",rv);
+ if (rv != SA_OK) {
+ printf("saHpiDiscover error %d\n",rv);
+ break;
+ }
+
+ /* walk the RPT list */
+ rptentryid = SAHPI_FIRST_ENTRY;
+ while ((rv == SA_OK) && (rptentryid != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiRptEntryGet(sessionid,rptentryid,&nextrptentryid,&rptentry);
+ if (rv != SA_OK) printf("RptEntryGet: rid=%d rv = %d\n",rptentryid,rv);
+ if (rv == SA_OK)
+ {
+ /* walk the RDR list for this RPT entry */
+ entryid = SAHPI_FIRST_ENTRY;
+ /* OpenHPI plugin sometimes has bad RPT Tag DataLength here. */
+ // rptentry.ResourceTag.Data[rptentry.ResourceTag.DataLength] = 0;
+ resourceid = rptentry.ResourceId;
+ if (fdebug) printf("rptentry[%d] resourceid=%d\n", rptentryid,resourceid);
+ if (rptentry.ResourceCapabilities & SAHPI_CAPABILITY_INVENTORY_DATA)
+ {
+ printf("Resource[%d] Tag: %s \thas inventory capability\n", rptentryid,rptentry.ResourceTag.Data);
+ while ((rv == SA_OK) && (entryid != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiRdrGet(sessionid,resourceid, entryid,&nextentryid, &rdr);
+ if (fdebug) printf("saHpiRdrGet[%x] rv = %d\n",entryid,rv);
+ if (rv == SA_OK)
+ {
+ if (fdebug) printf("Rdr[%x] type = %d tag = %s\n",entryid,
+ rdr.RdrType,rdr.IdString.Data);
+ if (rdr.RdrType == SAHPI_INVENTORY_RDR)
+ {
+ invfound = 1;
+ /*type 3 includes inventory records*/
+ rdr.IdString.Data[rdr.IdString.DataLength] = 0;
+ idrid = rdr.RdrTypeUnion.InventoryRec.IdrId;
+ buffersize = sizeof(inbuff);
+ if (fdebug) {
+ printf("Rdr[%x] is inventory, IdrId=%x\n",rdr.RecordId,idrid);
+ printf("Inv BufferSize=%d\n", buffersize);
+ }
+ if ( IsTagBmc(rdr.IdString.Data, rdr.IdString.DataLength) )
+ {
+ /* Get all of the inventory data areas and fields */
+ memset(inv,0,buffersize);
+ rv = saHpiIdrInfoGet(sessionid, resourceid, idrid, &idrInfo);
+ if (rv != SA_OK) {
+ printf("IDR Info error: rv = %d\n",rv);
+ } else { /* idrInfo is ok */
+ if (fdebug) printf("IDR Info: ok \n");
+ print_epath(&rptentry.ResourceEntity, 1);
+ printf("RDR[%x]: Inventory, IdrId=%x %s\n",rdr.RecordId,
+ idrid,rdr.IdString.Data);
+ print_idrinfo(&idrInfo,4);
+ rv = walkInventory(sessionid, resourceid, &idrInfo);
+ if (fdebug) printf("walkInventory rv = %d\n",rv);
+ }
+
+ if (!ent_writable(&rptentry.ResourceEntity,&idrInfo))
+ foundasset = 0;
+ if ((fasset == 1) && (foundasset == 1)) {
+ SaHpiIdrFieldT atagField;
+ atagField.Type = SAHPI_IDR_FIELDTYPE_ASSET_TAG;
+ atagField.ReadOnly = SAHPI_FALSE;
+ atagField.AreaId = atag.areaid;
+ atagField.FieldId = atag.fieldid;
+ strptr=&(atagField.Field);
+ strptr->DataType = SAHPI_TL_TYPE_TEXT;
+ strptr->Language = SAHPI_LANG_ENGLISH;
+ strptr->DataLength = (SaHpiUint8T)atag.tlen;
+ strncpy((char *)strptr->Data, atag.tag, atag.tlen);
+ strptr->Data[atag.tlen] = 0;
+ printf( "Writing new asset tag: %s\n",strptr->Data);
+ rv = saHpiIdrFieldSet(sessionid, resourceid,
+ atag.idrid, &atagField);
+ printf("Return Write Status = %d\n", rv);
+ if (rv == SA_OK) {
+ printf ("Good write - re-reading!\n");
+ rv = walkInventory(sessionid, resourceid, &idrInfo);
+ if (fdebug) printf("walkInventory rv = %d\n",rv);
+ } /* Good write - re-read */
+ } /*endif fasset*/
+ } /*endif RDR tag ok*/
+ } /* Inventory Data Records - Type 3 */
+ else if (fdebug) printf("rdr type = %d\n", rdr.RdrType);
+ } /*endif RdrGet ok*/
+ entryid = nextentryid;
+ } /*end while rdr*/
+ } /*endif rpt invent capab*/
+ else
+ if (fdebug) printf("Resource[%d] Tag: %s\n", rptentryid,
+ rptentry.ResourceTag.Data);
+ } /*endif rpt ok*/
+ rptentryid = nextrptentryid;
+ } /*end rpt loop */
+ if (fdebug) printf("loop %d inventory found = %d\n",nloops,invfound);
+ } /*end while no inv */
+ rv = saHpiSessionClose(sessionid);
+ exit(0);
+}
+ /* end hpifru.c */
diff --git a/hpiutil/hpiinit.sh b/hpiutil/hpiinit.sh
new file mode 100755
index 0000000..eace400
--- /dev/null
+++ b/hpiutil/hpiinit.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+#
+# hpi init script to start/stop the Intel hpi library daemon
+# process name: SpiLibd
+#
+# For RedHat and MontaVista
+# chkconfig: 345 50 35
+#
+### BEGIN SuSE INIT INFO
+# Provides: tam
+# Required-Start: $network
+# Default-Start: 3 5
+# Default-Stop: 0 1 2 6
+# Description: tam is used to start/stop Telco Alarm Manager
+### END INIT INFO
+name=hpiutil
+lockfile=/var/lock/subsys/$name
+
+if [ ! -d /var/lock/subsys ]; then
+ lockfile=/var/run/$name.pid
+fi
+
+case "$1" in
+"start")
+ # Is it already started?
+ ps -ef | grep -v grep | grep SpiLibd
+ if [ $? -eq 0 ]
+ then
+ echo "SpiLibd is already started"
+ exit 1
+ fi
+ SAHPI_HOME=/etc/hpi
+ LD_LIBRARY_PATH=/usr/lib
+ #LD_LIBRARY_PATH=$SAHPI_HOME/lib
+ # Use default config locations (/etc/hpi/*.conf)
+ #SPI_LIB_CFG_LOCATION=$SAHPI_HOME/spi-lib.conf
+ #SPI_DAEMON_CFG_LOCATION=$SAHPI_HOME/spi-daemon.conf
+ SPI_LIB_LOG_LOCATION=/var/log/spilib
+ SPI_DAEMON_LOG_LOCATION=/var/log/spidaemon
+ SPI_DAEMON_LOG_LEVEL=-l5
+ SPI_LIB_LOG_LEVEL=-l5
+# LD_ASSUME_KERNEL=2.4.1
+ # flush the logs before starting daemon
+ export SAHPI_HOME LD_LIBRARY_PATH SPI_LIB_LOG_LOCATION
+ export SPI_DAEMON_LOG_LOCATION SPI_DAEMON_LOG_LEVEL SPI_LIB_LOG_LEVEL
+# export SPI_LIB_CFG_LOCATION SPI_DAEMON_CFG_LOCATION
+ rm -f ${SPI_DAEMON_LOG_LOCATION}.1 $SPI_LIB_LOG_LOCATION 2>/dev/null
+ mv $SPI_DAEMON_LOG_LOCATION ${SPI_DAEMON_LOG_LOCATION}.1 2>/dev/null
+ # see /usr/bin/SpiLibd
+ SpiLibd
+ touch $lockfile
+ ;;
+"stop")
+ spid=`ps -ef |greo SpiLibd | grep -v grep |awk '{ print $2 }'`
+ if [ "$spid" != "" ]
+ then
+ kill $spid
+ sleep 5
+ kill -9 $spid 2>/dev/null
+ fi
+ rm -f $lockfile
+ ;;
+*)
+ echo "Usage: $0 start|stop"
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/hpiutil/hpireset.c b/hpiutil/hpireset.c
new file mode 100644
index 0000000..aeddd03
--- /dev/null
+++ b/hpiutil/hpireset.c
@@ -0,0 +1,225 @@
+/*
+ * hpireset.c
+ *
+ * Author: Andy Cress arcress at users.sourceforge.net
+ * Copyright (c) 2003 Intel Corporation.
+ *
+ * 05/02/03 Andy Cress - created
+ * 06/06/03 Andy Cress - beta2
+ * 06/26/03 Andy Cress - exclude stuff that isn't in HPI 1.0 (MAYBELATER)
+ * 12/07/04 Andy Cress - added HPI_A/B compile flags
+ */
+/*M*
+Copyright (c) 2003, 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 <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include "SaHpi.h"
+
+#define uchar unsigned char
+char *progver = "1.1";
+char fdebug = 0;
+
+static void Usage(char *pname)
+{
+ printf("Usage: %s [-r -d -x]\n", pname);
+ printf(" where -r hard Resets the system\n");
+ printf(" -d powers Down the system\n");
+#ifdef MAYBELATER
+/*++++ not implemented in HPI 1.0 ++++
+ printf(" -c power Cycles the system\n");
+ printf(" -n sends NMI to the system\n");
+ printf(" -o soft-shutdown OS\n");
+ printf(" -s reboots to Service Partition\n");
+ ++++*/
+#endif
+ printf(" -x show eXtra debug messages\n");
+}
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ SaErrorT rv;
+#ifdef HPI_A
+ SaHpiVersionT hpiVer;
+ SaHpiRptInfoT rptinfo;
+#endif
+ SaHpiSessionIdT sessionid;
+ SaHpiRptEntryT rptentry;
+ SaHpiEntryIdT rptentryid;
+ SaHpiEntryIdT nextrptentryid;
+ SaHpiEntryIdT entryid;
+ SaHpiEntryIdT nextentryid;
+ SaHpiResourceIdT resourceid;
+ SaHpiRdrT rdr;
+ SaHpiCtrlNumT ctlnum;
+ int j;
+ uchar breset;
+ uchar bopt;
+ uchar fshutdown = 0;
+ SaHpiCtrlStateT ctlstate;
+
+ printf("%s ver %s\n", argv[0],progver);
+ breset = 3; /* hard reset as default */
+ bopt = 0; /* Boot Options default */
+ while ( (c = getopt( argc, argv,"rdx?")) != EOF )
+ switch(c) {
+ case 'd': breset = 0; break; /* power down */
+ case 'r': breset = 3; break; /* hard reset */
+ case 'x': fdebug = 1; break; /* debug messages */
+#ifdef MAYBELATER
+ case 'c': breset = 2; break; /* power cycle */
+ case 'o': fshutdown = 1; break; /* shutdown OS */
+ case 'n': breset = 4; break; /* interrupt (NMI) */
+ case 's': bopt = 1; break; /* hard reset to svc part */
+#endif
+ default:
+ Usage(argv[0]);
+ exit(1);
+ }
+ if (fshutdown) breset = 5; /* soft shutdown option */
+
+#ifdef HPI_A
+ rv = saHpiInitialize(&hpiVer);
+ if (rv != SA_OK) {
+ printf("saHpiInitialize error %d\n",rv);
+ exit(-1);
+ }
+ rv = saHpiSessionOpen(SAHPI_DEFAULT_DOMAIN_ID,&sessionid,NULL);
+ if (rv != SA_OK) {
+ if (rv == SA_ERR_HPI_ERROR)
+ printf("saHpiSessionOpen: error %d, HPI Library not running\n",rv);
+ else
+ printf("saHpiSessionOpen error %d\n",rv);
+ exit(-1);
+ }
+ rv = saHpiResourcesDiscover(sessionid);
+ if (fdebug) printf("saHpiResourcesDiscover rv = %d\n",rv);
+ rv = saHpiRptInfoGet(sessionid,&rptinfo);
+ if (fdebug) printf("saHpiRptInfoGet rv = %d\n",rv);
+ printf("RptInfo: UpdateCount = %x, UpdateTime = %lx\n",
+ rptinfo.UpdateCount, (unsigned long)rptinfo.UpdateTimestamp);
+#else
+ rv = saHpiSessionOpen(SAHPI_UNSPECIFIED_DOMAIN_ID,&sessionid,NULL);
+ if (rv != SA_OK) {
+ printf("saHpiSessionOpen: error %d\n",rv);
+ exit(-1);
+ }
+ rv = saHpiDiscover(sessionid);
+ if (fdebug) printf("saHpiDiscover error %d\n",rv);
+#endif
+
+ /* walk the RPT list */
+ rptentryid = SAHPI_FIRST_ENTRY;
+ while ((rv == SA_OK) && (rptentryid != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiRptEntryGet(sessionid,rptentryid,&nextrptentryid,&rptentry);
+ if (rv != SA_OK) printf("RptEntryGet: rv = %d\n",rv);
+ if (rv == SA_OK) {
+ /* walk the RDR list for this RPT entry */
+ entryid = SAHPI_FIRST_ENTRY;
+ resourceid = rptentry.ResourceId;
+#ifdef HPI_A
+ rptentry.ResourceTag.Data[rptentry.ResourceTag.DataLength] = 0;
+#endif
+ printf("rptentry[%d] resourceid=%d tag: %s\n",
+ entryid,resourceid, rptentry.ResourceTag.Data);
+ while ((rv == SA_OK) && (entryid != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiRdrGet(sessionid,resourceid,
+ entryid,&nextentryid, &rdr);
+ if (fdebug) printf("saHpiRdrGet[%d] rv = %d\n",entryid,rv);
+ if (rv == SA_OK) {
+ if (rdr.RdrType == SAHPI_CTRL_RDR) {
+ /*type 1 includes Cold Reset Control */
+ ctlnum = rdr.RdrTypeUnion.CtrlRec.Num;
+ rdr.IdString.Data[rdr.IdString.DataLength] = 0;
+ if (fdebug) printf("Ctl[%d]: %d %d %s\n",
+ ctlnum, rdr.RdrTypeUnion.CtrlRec.Type,
+ rdr.RdrTypeUnion.CtrlRec.OutputType,
+ rdr.IdString.Data);
+ if ((rdr.RdrTypeUnion.CtrlRec.Type == SAHPI_CTRL_TYPE_DIGITAL) &&
+ (rdr.RdrTypeUnion.CtrlRec.OutputType == SAHPI_CTRL_GENERIC))
+ { /* This is the Reset control */
+ printf("RDR[%d]: %d,%d %s\n",
+ rdr.RecordId,
+ rdr.RdrTypeUnion.CtrlRec.Type,
+ rdr.RdrTypeUnion.CtrlRec.OutputType,
+ rdr.IdString.Data);
+#ifdef MAYBELATER
+ {
+ SaHpiResetActionT resetact;
+ rv = saHpiResourceResetStateGet(sessionid,
+ resourceid, &resetact);
+ printf("ResetStateGet status = %d, act=%d\n",
+ rv,resetact);
+ rv = saHpiResourceResetStateSet(sessionid,
+ resourceid, resetact);
+ printf("ResetStateSet status = %d\n",rv);
+ }
+#endif
+
+ ctlstate.Type = SAHPI_CTRL_TYPE_DIGITAL;
+ if (breset == 0) { /*power off*/
+ ctlstate.StateUnion.Digital = SAHPI_CTRL_STATE_OFF;
+ printf("Powering down ... \n");
+ } else {
+ ctlstate.StateUnion.Digital = SAHPI_CTRL_STATE_ON;
+ printf("Resetting ... \n");
+ }
+#ifdef HPI_A
+ rv = saHpiControlStateSet(sessionid,
+ resourceid, ctlnum,&ctlstate);
+#else
+ rv = saHpiControlSet(sessionid, resourceid,
+ ctlnum, SAHPI_CTRL_MODE_MANUAL,
+ &ctlstate);
+#endif
+ printf("Reset status = %d\n",rv);
+ break;
+ }
+ }
+ j++;
+ entryid = nextentryid;
+ }
+ }
+ rptentryid = nextrptentryid;
+ }
+ }
+
+ rv = saHpiSessionClose(sessionid);
+#ifdef HPI_A
+ rv = saHpiFinalize();
+#endif
+
+ exit(0);
+}
+
+/* end hpireset.c */
diff --git a/hpiutil/hpisel.c b/hpiutil/hpisel.c
new file mode 100644
index 0000000..e922b81
--- /dev/null
+++ b/hpiutil/hpisel.c
@@ -0,0 +1,934 @@
+/*
+ * hpisel.c
+ *
+ * Author: Andy Cress arcress at users.sourceforge.net
+ * Copyright (c) 2003-2005 Intel Corporation.
+ *
+ * 04/28/03 Andy Cress - created
+ * 04/30/03 Andy Cress v0.6 first good run with common use cases
+ * 05/06/03 Andy Cress v0.7 added -c option to clear it
+ * 05/29/03 Andy Cress v0.8 fixed pstr warnings
+ * 06/13/03 Andy Cress v0.9 fixed strcpy bug,
+ * workaround for SensorEvent.data3
+ * 06/19/03 Andy Cress 0.91 added low SEL free space warning
+ * 06/25/03 Andy Cress v1.0 rework event data logic
+ * 07/23/03 Andy Cress workaround for OpenHPI BUGGY stuff
+ * 11/12/03 Andy Cress v1.1 check for CAPABILITY_SEL
+ * 03/03/04 Andy Cress v1.2 use better free space logic now
+ * 10/14/04 Andy Cress v1.3 added HPI_A/HPI_B logic
+ * 02/11/05 Andy Cress v1.4 added decode routines from showsel.c
+ * 03/30/05 Dave Howell v1.5 added support to enable displaying domain
+ * event log for HPI_B
+ * 04/07/05 Andy Cress v1.6 fix domain resourceid & HPI_A/B flags,
+ * add logic to clear domain event log.
+ *
+ * Note that hpiutil 1.0.0 did not return all event data fields, so event
+ * types other than 'user' did not have all bytes filled in as they
+ * would have from IPMI alone. A patch to the Intel HPI library in
+ * version 1.0.1 resolved this.
+ */
+/*M*
+Copyright (c) 2003-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 <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include <time.h>
+#include "SaHpi.h"
+
+#ifdef HPI_A
+/* HPI A (1.0) spec */
+char progver[] = "1.6 HPI-A";
+#else
+/* HPI B name changes */
+#define SaHpiSelEntryT SaHpiEventLogEntryT
+#define SaHpiSelEntryIdT SaHpiEventLogEntryIdT
+#define SaHpiSelInfoT SaHpiEventLogInfoT
+#define SAHPI_CAPABILITY_SEL SAHPI_CAPABILITY_EVENT_LOG /*0x00000004*/
+#define SAHPI_EC_USER SAHPI_EC_SENSOR_SPECIFIC /*0x7E*/
+char progver[] = "1.6 HPI-B";
+#endif
+int fdebug = 0;
+int fclear = 0;
+int fdomain = 0;
+
+#ifdef HPI_A
+#define NEVTYPES 5
+char *evtypes[NEVTYPES] = {"sensor","hotswap","watchdog","oem ","user "};
+#else
+#define NEVTYPES 9
+char *evtypes[NEVTYPES] = {"resource","domain","sensor","sens_enable",
+ "hotswap","watchdog","HPI sw", "oem ","user "};
+#endif
+
+#define NECODES 27
+struct { int code; char *str;
+} ecodes[NECODES] = {
+ { 0, "Success" },
+ { -1001, "HPI unspecified error" },
+ { -1002, "HPI unsupported function" },
+ { -1003, "HPI busy" },
+ { -1004, "HPI request invalid" },
+ { -1005, "HPI command invalid" },
+ { -1006, "HPI timeout" },
+ { -1007, "HPI out of space" },
+ { -1008, "HPI data truncated" },
+#ifdef HPI_A
+ { -1009, "HPI data length invalid" },
+#else
+ { -1009, "HPI invalid parameter" },
+#endif
+ { -1010, "HPI data exceeds limits" },
+ { -1011, "HPI invalid params" },
+ { -1012, "HPI invalid data" },
+ { -1013, "HPI not present" },
+ { -1014, "HPI invalid data field" },
+ { -1015, "HPI invalid sensor command" },
+ { -1016, "HPI no response" },
+ { -1017, "HPI duplicate request" },
+ { -1018, "HPI updating" },
+ { -1019, "HPI initializing" },
+ { -1020, "HPI unknown error" },
+ { -1021, "HPI invalid session" },
+ { -1022, "HPI invalid domain" },
+ { -1023, "HPI invalid resource id" },
+ { -1024, "HPI invalid request" },
+ { -1025, "HPI entity not present" },
+ { -1026, "HPI uninitialized" }
+};
+char def_estr[15] = "HPI error %d ";
+
+#define NUM_EC 14
+struct { int val; char *str;
+} eventcats[NUM_EC] = {
+{ /*0x00*/ SAHPI_EC_UNSPECIFIED, "unspecified"},
+{ /*0x01*/ SAHPI_EC_THRESHOLD, "Threshold"},
+{ /*0x02*/ SAHPI_EC_USAGE, "Usage "},
+{ /*0x03*/ SAHPI_EC_STATE, "State "},
+{ /*0x04*/ SAHPI_EC_PRED_FAIL, "Predictive"},
+{ /*0x05*/ SAHPI_EC_LIMIT, "Limit "},
+{ /*0x06*/ SAHPI_EC_PERFORMANCE, "Performnc"},
+{ /*0x07*/ SAHPI_EC_SEVERITY, "Severity "},
+{ /*0x08*/ SAHPI_EC_PRESENCE, "DevPresen"},
+{ /*0x09*/ SAHPI_EC_ENABLE, "DevEnable"},
+{ /*0x0a*/ SAHPI_EC_AVAILABILITY, "Availabil"},
+{ /*0x0b*/ SAHPI_EC_REDUNDANCY, "Redundanc"},
+{ /*0x7e*/ SAHPI_EC_USER, "SensorSpc"}, /*UserDefin*/
+{ /*0x7f*/ SAHPI_EC_GENERIC, "OemDefin " }};
+
+#define NUM_ES 6
+struct { int val; char *str; } eventstates[NUM_ES] = {
+{ SAHPI_ES_LOWER_MINOR , "lo-min" },
+{ SAHPI_ES_LOWER_MAJOR , "lo-maj" },
+{ SAHPI_ES_LOWER_CRIT , "lo-crt" },
+{ SAHPI_ES_UPPER_MINOR , "hi-min" },
+{ SAHPI_ES_UPPER_MAJOR , "hi-maj" },
+{ SAHPI_ES_UPPER_CRIT , "hi-crt" } };
+
+#define uchar unsigned char
+#define ushort unsigned short
+#define uint unsigned int
+#define ulong unsigned long
+typedef struct
+{
+ short record_id;
+ uchar record_type;
+ uint timestamp;
+ short 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;
+
+/* sensor_types: See IPMI 1.5 Table 36-3, IPMI 2.0 Table 42-3 */
+#define NSTYPES 0x2D
+static char *sensor_types[NSTYPES] = {
+/* 00h */ "reserved",
+/* 01h */ "Temperature",
+/* 02h */ "Voltage",
+/* 03h */ "Current",
+/* 04h */ "Fan",
+/* 05h */ "Platform Chassis Intrusion",
+/* 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 */ "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",
+/* 2Ah */ "Session Audit",
+/* 2Bh */ "Version Change",
+/* 2Ch */ "FRU State"
+};
+
+#define NFWERRS 15
+static struct { /* See Table 36-3, type 0Fh, offset 00h */
+ int code; char *msg;
+ } fwerrs[NFWERRS] = {
+ { 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 27
+static struct { /* See Table 36-3, type 0Fh, offset 01h & 02h */
+ int code; char *msg;
+ } fwstat[NFWSTAT] = {
+ { 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 7
+struct {
+ ushort g_id;
+ char desc[10];
+} gen_desc[NGDESC] = { /*empirical, format defined in IPMI 1.5 Table 23-5 */
+ { 0x0000, "IPMB"},
+ { 0x0001, "EFI "},
+ { 0x0003, "BIOS"},
+ { 0x0020, "BMC "},
+ { 0x0021, "SMI "},
+ { 0x0028, "CHAS"}, /* Chassis Bridge Controller */
+/*{0x0031, "SMI/IPMB"}, * ia64/mBMC POST errors (rqSa/rqLun) */
+/*{0x0033, "MemCtlr"}, * ia64 memory controller? (rqSa/rqLun) */
+ { 0x00c0, "HSC "} /* 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 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 NSDESC 47
+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;
+ char desc[40];
+} sens_desc[NSDESC] = {
+{0xffff,0x05, 0x05, 0x6f, 0x44, 0xff, 0xff, "LAN unplugged"}, /*chassis*/
+{0xffff,0x05, 0x05, 0xef, 0x44, 0xff, 0xff, "LAN restored "}, /*chassis*/
+{0xffff,0x06, 0xff, 0xff, 0x45, 0xff, 0xff, "Password"}, /*security*/
+{0xffff,0x07, 0xff, 0xff, 0x41, 0xff, 0xff, "Thermal trip"}, /*processor*/
+{0xffff,0x08, 0xff, 0x6f, 0x40, 0xff, 0xff, "Presence detected"},/*PowerSupply*/
+{0xffff,0x08, 0xff, 0x6f, 0x41, 0xff, 0xff, "Failure detected"},/*power supply*/
+{0xffff,0x08, 0xff, 0x6f, 0x42, 0xff, 0xff, "Predictive failure"},
+{0xffff,0x08, 0xff, 0x6f, 0x43, 0xff, 0xff, "AC Lost"},
+{0xffff,0x08, 0xff, 0xef, 0x40, 0xff, 0xff, "not present"}, /*power supply*/
+{0xffff,0x08, 0xff, 0xef, 0x41, 0xff, 0xff, "is OK "}, /*power supply*/
+{0xffff,0x08, 0xff, 0xef, 0x42, 0xff, 0xff, "Predictive OK"},
+{0xffff,0x08, 0xff, 0xef, 0x43, 0xff, 0xff, "AC Regained"}, /*power supply*/
+{0xffff,0x09, 0xff, 0xff, 0x40, 0xff, 0xff, "Redundancy OK "}, /*power unit*/
+{0xffff,0x09, 0xff, 0xff, 0x41, 0xff, 0xff, "Redundancy Lost"},
+{0xffff,0x09, 0xff, 0xff, 0x44, 0xff, 0xff, "AC Lost"},
+{0xffff,0x09, 0xff, 0xff, 0x46, 0xff, 0xff, "Failure detected"},
+{0xffff,0x09, 0xff, 0xff, 0x47, 0xff, 0xff, "Predictive failure"},/*power unit*/
+{0xffff,0x0c, 0xff, 0xff, 0x00, 0xff, 0xff, "Correctable ECC"}, /*memory*/
+{0xffff,0x0f, 0x06, 0xff, 0xff, 0xff, 0xff, "POST Code"},
+{0xffff,0x10, 0x09, 0xff, 0x42, 0x0f, 0xff, "Log Cleared"},
+{0xffff,0x10, 0x09, 0xff, 0xc0, 0x03, 0xff, "ECC Memory Errors"},
+ /* Often see these 3 Boot records with reboot:
+ * 12 83 6f 05 00 ff = System/SEL Time Sync 1 (going down)
+ * 12 83 6f 05 80 ff = System/SEL Time Sync 2 (coming up)
+ * 12 83 6f 01 ff ff = OEM System Boot Event (Completed POST) */
+{0xffff,0x12, 0x83, 0xff, 0x05, 0x00, 0xff, "Boot: ClockSync 1"},
+{0xffff,0x12, 0x83, 0xff, 0x05, 0x80, 0xff, "Boot: ClockSync 2"},
+{0xffff,0x12, 0x83, 0xff, 0x01, 0xff, 0xff, "OEM System Booted"},
+{0xffff,0x12, 0x08, 0xff, 0x01, 0xff, 0xff, "OEM System Booted"}, /*ia64*/
+{0xffff,0x12, 0x00, 0x6f, 0xff, 0xff, 0xff, "PEF Action"}, /*ia64*/
+{0xffff,0x12, 0x83, 0x6f, 0x80, 0xff, 0xff, "System Reconfigured"}, /*BMC*/
+{0x00c0,0x0d, 0xff, 0x08, 0x00, 0xff, 0xff, "Device Removed"}, /*HSC*/
+{0x00c0,0x0d, 0xff, 0x08, 0x01, 0xff, 0xff, "Device Inserted"}, /*HSC*/
+{0xffff,0x14, 0xff, 0xff, 0x42, 0xff, 0xff, "Reset Button pressed"},
+{0xffff,0x14, 0xff, 0xff, 0x40, 0xff, 0xff, "Power Button pressed"},
+{0xffff,0x14, 0xff, 0xff, 0x01, 0xff, 0xff, "ID Button pressed"},
+{0xffff,0x23, 0xff, 0xff, 0x40, 0xff, 0xff, "Expired, no action"},/*watchdog2*/
+{0xffff,0x23, 0xff, 0xff, 0x41, 0xff, 0xff, "Hard Reset action"}, /*watchdog2*/
+{0xffff,0x23, 0xff, 0xff, 0x42, 0xff, 0xff, "Power down action"}, /*watchdog2*/
+{0xffff,0x23, 0xff, 0xff, 0x43, 0xff, 0xff, "Power cycle action"},/*watchdog2*/
+{0xffff,0x23, 0xff, 0xff, 0x48, 0xff, 0xff, "Timer interrupt"}, /*watchdog2*/
+{0xffff,0xf3, 0x85, 0xff, 0x41, 0xff, 0xff, "State is now OK"},
+{0xffff,0x20, 0x00, 0xff, 0xff, 0xff, 0xff, "OS Kernel Panic"},
+{0xffff,0xff, 0xff, 0x01, 0x57, 0xff, 0xff, "Hi Noncrit thresh"},
+{0xffff,0xff, 0xff, 0x01, 0x59, 0xff, 0xff, "Hi Crit thresh"},
+{0xffff,0xff, 0xff, 0x01, 0x50, 0xff, 0xff, "Lo Noncrit thresh"},
+{0xffff,0xff, 0xff, 0x01, 0x52, 0xff, 0xff, "Lo Crit thresh"},
+{0xffff,0xff, 0xff, 0x81, 0x57, 0xff, 0xff, "HiN thresh OK now"},
+{0xffff,0xff, 0xff, 0x81, 0x59, 0xff, 0xff, "HiC thresh OK now"},
+{0xffff,0xff, 0xff, 0x81, 0x50, 0xff, 0xff, "LoN thresh OK now"},
+{0xffff,0xff, 0xff, 0x81, 0x52, 0xff, 0xff, "LoC thresh OK now"}
+ /*Thresholds apply to sensor types 1=temp, 2=voltage, 4=fan */
+ /*Note that last 2 bytes usu show actual & threshold values*/
+ /*evtrg: 0x01=thresh, 0x81=restored */
+};
+
+/*------------------------------------------------------------------------
+ * get_misc_desc
+ * Uses the sens_desc array to decode misc entries not otherwise handled.
+ * Called by decode_sel_entry
+ *------------------------------------------------------------------------*/
+char * get_misc_desc(uchar type, uchar num, ushort genid, uchar trig,
+ uchar data1, uchar data2, uchar data3);
+char *
+get_misc_desc(uchar type, uchar num, ushort genid, uchar trig,
+ uchar data1, uchar data2, uchar data3)
+{
+ 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)
+ 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;
+ break;
+ }
+ } /*end for*/
+ return(pstr);
+} /* end get_misc_desc() */
+
+void decode_sensor_event(uchar sensor_type, uchar sensor_number, ushort gen_id,
+ uchar event_trigger, uchar data1, uchar data2, uchar data3,
+ char *outbuf);
+void
+decode_sensor_event(uchar sensor_type, uchar sensor_number, ushort gen_id,
+ uchar event_trigger, uchar data1, uchar data2, uchar data3,
+ char *outbuf)
+{
+ char mystr[26] = "(123)"; /*for panic string*/
+ char poststr[24] = "OEM Post Code = %x%x";
+ char genstr[10] = "03 ";
+ char *gstr;
+ char *pstr;
+ uchar dtype;
+ int i;
+
+ /* set dtype, used as array index below */
+ if (sensor_type >= NSTYPES) dtype = 0;
+ else dtype = sensor_type;
+ switch(sensor_type) {
+ case 0x20: /*OS Crit Stop*/
+ /* Show first 3 chars of panic string */
+ mystr[0] = '(';
+ mystr[1] = sensor_number & 0x7f;
+ mystr[2] = data2 & 0x7f;
+ mystr[3] = data3 & 0x7f;
+ mystr[4] = ')';
+ mystr[5] = 0;
+ pstr = mystr;
+ if (sensor_number & 0x80) strcat(mystr,"Oops!");
+ if (data2 & 0x80) strcat(mystr,"Int!");
+ if (data3 & 0x80) strcat(mystr,"NullPtr!");
+ break;
+ case 0x0f: /*Post Errs*/
+ switch (data1)
+ {
+ case 0x00: /* System firmware errors */
+ i = data2;
+ if (i >= NFWERRS) i = NFWERRS - 1;
+ pstr = fwerrs[i].msg;
+ break;
+ case 0x01: /* System firmware hang */
+ i = data2;
+ if (i >= NFWSTAT) i = NFWSTAT - 1;
+ sprintf(poststr,"hang, %s",fwstat[i].msg);
+ pstr = poststr;
+ break;
+ case 0x02: /* System firmware progress */
+ i = data2;
+ if (i >= NFWSTAT) i = NFWSTAT - 1;
+ sprintf(poststr,"prog, %s",fwstat[i].msg);
+ pstr = poststr;
+ break;
+ case 0xa0: /* OEM post codes */
+ /* OEM post codes in bytes 2 & 3 (lo-hi) */
+ sprintf(poststr,"POST Code %02x%02x",
+ data3,data2);
+ pstr = poststr;
+ break;
+ default:
+ pstr = "POST Error"; /*default string*/
+ } /*end switch(data1)*/
+ break;
+ case 0x13: /*Crit Int*/
+ i = data1 & 0x0f;
+ if (i >= NCRITS) i = NCRITS - 1;
+ pstr = crit_int_str[i];
+ break;
+ case 0x21: /*Slot/Con*/
+ i = data1 & 0x0f;
+ if (i >= NSLOTC) i = NSLOTC - 1;
+ sprintf(mystr,"%s",slot_str[i]);
+ /* could also decode data2/data3 here if valid */
+ pstr = mystr;
+ break;
+ default: /* all other sensor types, see sens_desc */
+ pstr = get_misc_desc( sensor_type,
+ sensor_number, gen_id,
+ event_trigger, data1, data2, data3);
+ if (pstr == NULL) {
+ mystr[0] = '-'; mystr[1] = 0;
+ pstr = mystr;
+ }
+
+ } /*end switch(sensor_type)*/
+
+ /* show the Generator ID */
+ sprintf(genstr,"%04x",gen_id);
+ gstr = genstr; /* default */
+ for (i = 0; i < NGDESC; i++)
+ {
+ if (gen_desc[i].g_id == gen_id)
+ gstr = (char *)gen_desc[i].desc;
+ }
+
+ /*firmware timestamp is #seconds since 1/1/1970 localtime*/
+ /* timestamp handled by caller in HPI */
+
+ if ((event_trigger == 0x01) || /*threshold*/
+ (event_trigger == 0x81)) { /*threshold ok*/
+ sprintf(outbuf,
+ "%s %02x %s act=%02x thr=%02x",
+ sensor_types[dtype], sensor_number, pstr,
+ data2, /*actual reading*/
+ data3 ); /*threshold value*/
+ } else {
+ sprintf(outbuf,
+ "%s %02x %s %02x [%02x %02x %02x]",
+ sensor_types[dtype] , sensor_number, pstr,
+ event_trigger, data1, data2, data3 );
+ }
+}
+
+/*------------------------------------------------------------------------
+ * decode_ipmi_event
+ * Parse and decode the SEL record into readable format.
+ * This routine is constructed so that it could be used as a library
+ * function.
+ * Input: psel, a pointer to the IPMI SEL record
+ * Output: outbuf, a description of the event, max 80 chars.
+ * Called by ReadSEL
+ *------------------------------------------------------------------------*/
+void decode_ipmi_event( SEL_RECORD *psel, char *outbuf);
+void decode_ipmi_event( SEL_RECORD *psel, char *outbuf)
+{
+ char genstr[10] = "03 ";
+ int i, j;
+
+ if (psel->record_type >= 0xe0) { /*OEM Record 26.3*/
+ char *pc;
+ pc = (char *)&psel->timestamp; /*bytes 4:16*/
+ sprintf(outbuf," OEM Event %02x %02x ", pc[0], pc[1]);
+ j = strlen(outbuf);
+ for (i = 2; i < 13; i++) { /* 4:16 = 13 bytes data */
+ if (psel->record_type == 0xf0) {
+ /* panic string will be type 0xf0 */
+ 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 == 0x02) {
+ /* most records are record type 2 */
+ decode_sensor_event(psel->sensor_type,
+ psel->sensor_number, psel->generator_id,
+ psel->event_trigger, psel->event_data1,
+ psel->event_data2, psel->event_data3, outbuf);
+
+ } /*endif type 2 */
+ else { /* other misc record type */
+ uchar *pc;
+ pc = (uchar *)&psel->record_type;
+ sprintf(outbuf," Type%02x ", pc[0]);
+ j = strlen(outbuf);
+ for (i = 1; i < 14; i++) {
+ sprintf(genstr,"%02x ",pc[i]);
+ strcat(outbuf,genstr);
+ }
+ } /*endif misc type*/
+ return;
+} /*end decode_ipmi_event()*/
+
+#define IF_IPMI 0 /* other interfaces, like H8, have diff numbers */
+ /*Note that OpenHPI 2.0.0 does not yet fill this in*/
+
+/*------------------------------------------------------------------------
+ * decode_hpi_event
+ * Parse and decode the SensorEvent record into readable format.
+ * Input: pevent, a pointer to the HPI SensorEvent record
+ * Output: outbuf, a description of the event, max 80 chars.
+ * Called by ReadSEL
+ *------------------------------------------------------------------------*/
+void decode_hpi_event( SaHpiSensorEventT *pevent, char *outbuf);
+void decode_hpi_event( SaHpiSensorEventT *pevent, char *outbuf)
+{
+ int ec, eci;
+ int es, esi;
+ int styp;
+ uchar data1, data2, data3, if_type;
+ uchar etrig;
+ ushort genid;
+ char estag[8];
+ char sbuf[80];
+ char *ecstr;
+ // char *pstr;
+
+ /* decode event category */
+ ec = pevent->EventCategory;
+ for (eci = 0; eci < NUM_EC; eci++)
+ if (eventcats[eci].val == ec) break;
+ if (eci >= NUM_EC) eci = 0;
+ ecstr = eventcats[eci].str;
+ genid = 0x0020; /* default to BMC */
+ etrig = 0x6f; /* default to sensor-specific*/
+ /* decode event state */
+ es = pevent->EventState;
+ if (ec == SAHPI_EC_USER) { /*OpenHPI usu returns this (0x7e)*/
+ sprintf(estag,"%02x",es);
+ } else if (eci == SAHPI_EC_THRESHOLD ) { /*0x01*/
+ for (esi = 0; esi < NUM_ES; esi++)
+ if (eventstates[esi].val == es) break;
+ if (esi >= NUM_ES) esi = 0;
+ strcpy(estag,eventstates[esi].str);
+ if (pevent->Assertion) etrig = 0x01;
+ else etrig = 0x81;
+ } else {
+ sprintf(estag,"%02x:%02x",ec,es);
+ }
+
+ /* decode sensor type */
+ styp = pevent->SensorType;
+ if (styp >= NSTYPES) { styp = 0; }
+
+ /* get if_type from SensorSpecific h.o. byte */
+ if_type = (pevent->SensorSpecific & 0xff000000) >> 24;
+ data3 = (pevent->SensorSpecific & 0x00ff0000) >> 16;
+ data2 = (pevent->SensorSpecific & 0x0000ff00) >> 8;
+ data1 = (pevent->SensorSpecific & 0x000000ff);
+ if (if_type == IF_IPMI) { /* handle IPMI SensorSpecific stuff */
+ /* fortunately, HPI & IPMI have the same sensor_type values */
+ decode_sensor_event(styp, pevent->SensorNum, genid,
+ etrig, data1, data2, data3, sbuf);
+ sprintf(outbuf,"%s %s", estag, sbuf);
+ }
+ else {
+ sprintf(outbuf,"%s, %s %s %x [%02x %02x %02x]",
+ sensor_types[styp], ecstr, estag,
+ pevent->SensorNum, data1, data2, data3);
+ }
+
+ return;
+}
+
+static
+char *decode_error(SaErrorT code)
+{
+ int i;
+ char *str = NULL;
+ for (i = 0; i < NECODES; i++) {
+ if (code == ecodes[i].code) { str = ecodes[i].str; break; }
+ }
+ if (str == NULL) {
+ sprintf(&def_estr[10],"%d",code);
+ str = &def_estr[0];
+ }
+ return(str);
+}
+
+void ShowSel( SaHpiSelEntryT *sel, SaHpiRdrT *rdr, SaHpiRptEntryT *rptentry);
+void ShowSel( SaHpiSelEntryT *sel, SaHpiRdrT *rdr,
+ SaHpiRptEntryT *rptentry )
+{
+ unsigned char evtype;
+ char timestr[40];
+ time_t tt1;
+ char *srctag;
+ char *rdrtag;
+ char *pstr;
+ unsigned char *pd;
+ int outlen;
+ char outbuf[132];
+ int styp;
+ unsigned char data3;
+
+ /*format & print the EventLog entry*/
+ if (sel->Event.Timestamp > SAHPI_TIME_MAX_RELATIVE) { /*absolute time*/
+ tt1 = sel->Event.Timestamp / 1000000000;
+ strftime(timestr,sizeof(timestr),"%x %H:%M:%S", localtime(&tt1));
+ } else if (sel->Event.Timestamp > SAHPI_TIME_UNSPECIFIED) { /*invalid time*/
+ strcpy(timestr,"invalid time ");
+ } else { /*relative time*/
+ tt1 = sel->Event.Timestamp / 1000000000;
+ sprintf(timestr,"rel(%lx)", (unsigned long)tt1);
+ }
+ if (rptentry->ResourceId == sel->Event.Source)
+ srctag = rptentry->ResourceTag.Data;
+ else srctag = "unspec "; /* SAHPI_UNSPECIFIED_RESOURCE_ID */
+ evtype = sel->Event.EventType;
+ if (evtype > NEVTYPES) evtype = NEVTYPES - 1;
+ if (rdr->RdrType == SAHPI_NO_RECORD) rdrtag = "rdr-unkn";
+ else {
+ rdr->IdString.Data[rdr->IdString.DataLength] = 0;
+ rdrtag = &rdr->IdString.Data[0];
+ }
+ sprintf(outbuf,"%04x %s %s ", sel->EntryId, timestr, evtypes[evtype] );
+ outlen = strlen(outbuf);
+ pstr = "";
+#ifdef HPI_A
+ pd = &sel->Event.EventDataUnion.UserEvent.UserEventData[0];
+#else
+ pd = &sel->Event.EventDataUnion.UserEvent.UserEventData.Data[0];
+#endif
+
+ switch(evtype)
+ {
+ case SAHPI_ET_SENSOR: /*Sensor*/
+ pd = (void *)&(sel->Event.EventDataUnion.SensorEvent);
+ decode_hpi_event((void *)pd,&outbuf[outlen]);
+ break;
+ case SAHPI_ET_USER: /*User, usu 16-byte IPMI SEL record */
+ decode_ipmi_event((void *)pd,&outbuf[outlen]);
+ break;
+ default:
+ // decode_ipmi_event((void *)pd,&outbuf[outlen]);
+ styp = pd[10];
+ data3 = pd[15];
+ /* *sel->Event.EventDataUnion.SensorEvent.SensorSpecific+1 */
+ if (styp >= NSTYPES) {
+ if (fdebug) printf("sensor type %d >= max %d\n",styp,NSTYPES);
+ styp = 0;
+ }
+ pstr = (char *)sensor_types[styp];
+ sprintf(&outbuf[outlen], "%s, %x %x, %02x %02x %02x [%02x %02x %02x/%02x]",
+ pstr, pd[0], pd[7], pd[10], pd[11], pd[12],
+ pd[13], pd[14], pd[15], data3);
+ break;
+ }
+ printf("%s\n",outbuf);
+}
+
+static SaErrorT
+DoEventLogForResource(SaHpiSessionIdT sessionid,
+ SaHpiResourceIdT resourceid,
+ char *tagname)
+{
+ SaErrorT rv;
+ SaHpiSelInfoT info;
+ int free = 50;
+ SaHpiSelEntryIdT entryid;
+ SaHpiSelEntryIdT nextentryid;
+ SaHpiSelEntryIdT preventryid;
+ SaHpiSelEntryT sel;
+ SaHpiRdrT rdr;
+ SaHpiRptEntryT rptentry;
+
+ printf("rptentry[%d] tag: %s\n", resourceid, tagname);
+
+ rv = saHpiEventLogInfoGet(sessionid, resourceid, &info);
+ if (fdebug)
+ printf("saHpiEventLogInfoGet %s\n", decode_error(rv));
+ if (rv == SA_OK) {
+ free = info.Size - info.Entries;
+ printf("EventLog entries=%d, size=%d, enabled=%d, free=%d\n",
+ info.Entries, info.Size, info.Enabled, free);
+ }
+
+ entryid = SAHPI_OLDEST_ENTRY;
+ while ((rv == SA_OK) && (entryid != SAHPI_NO_MORE_ENTRIES))
+ {
+ /* rv = saHpiEventLogEntryGet(sessionid,SAHPI_DOMAIN_CONTROLLER_ID,entryid, */
+ rv = saHpiEventLogEntryGet(sessionid, resourceid, entryid,
+ &preventryid, &nextentryid, &sel, &rdr, &rptentry);
+ if (fdebug)
+ printf("saHpiEventLogEntryGet[%x] %s, next=%x\n",
+ entryid, decode_error(rv), nextentryid);
+ if (rv == SA_OK) {
+ ShowSel(&sel, &rdr, &rptentry);
+ if (entryid == nextentryid)
+ break;
+ preventryid = entryid;
+ entryid = nextentryid;
+ }
+ }
+
+ if (free < 6) {
+ /*
+ * This test could be more generic if the log info fields above
+ * were accurate. IPMI SEL logs have a fixed size of 0x10000
+ * bytes. New log records are thrown away when it gets full.
+ * (OLDEST = 0, NO_MORE = fffffffe , so these are ok.)
+ */
+ /* free = (0x10000 - 20) - preventryid; */
+ printf( "WARNING: Log free space is very low (%d records)\n"
+ " Clear log with hpisel -c\n", free);
+ }
+
+ return SA_OK;
+}
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ SaErrorT rv;
+ SaHpiSessionIdT sessionid;
+#ifdef HPI_A
+ SaHpiVersionT hpiVer;
+ SaHpiRptInfoT rptinfo;
+#endif
+ SaHpiRptEntryT rptentry;
+ SaHpiEntryIdT rptentryid;
+ SaHpiEntryIdT nextrptentryid;
+ SaHpiResourceIdT resourceid;
+
+ printf("%s: version %s\n",argv[0],progver);
+
+#ifdef HPI_A
+#define ARGSTR "cx?"
+#else
+#define ARGSTR "cdx?"
+#endif
+
+ while ( (c = getopt( argc, argv, ARGSTR)) != EOF )
+ switch(c) {
+ case 'c': fclear = 1; break;
+#ifndef HPI_A
+ case 'd': fdomain = 1; break;
+#endif
+ case 'x': fdebug = 1; break;
+ default:
+ printf("Usage %s [-cx]\n",argv[0]);
+ printf("where -c clears the event log\n");
+#ifndef HPI_A
+ printf(" -d displays the domain event log\n");
+#endif
+ printf(" -x displays eXtra debug messages\n");
+ exit(1);
+ }
+#ifdef HPI_A
+ rv = saHpiInitialize(&hpiVer);
+ if (rv != SA_OK) {
+ printf("saHpiInitialize: %s\n",decode_error(rv));
+ exit(-1);
+ }
+ rv = saHpiSessionOpen(SAHPI_DEFAULT_DOMAIN_ID,&sessionid,NULL);
+ if (rv != SA_OK) {
+ if (rv == SA_ERR_HPI_ERROR)
+ printf("saHpiSessionOpen: error %d, SpiLibd not running\n",rv);
+ else
+ printf("saHpiSessionOpen: %s\n",decode_error(rv));
+ exit(-1);
+ }
+ rv = saHpiResourcesDiscover(sessionid);
+ if (fdebug) printf("saHpiResourcesDiscover %s\n",decode_error(rv));
+ rv = saHpiRptInfoGet(sessionid,&rptinfo);
+ if (fdebug) printf("saHpiRptInfoGet %s\n",decode_error(rv));
+ printf("RptInfo: UpdateCount = %x, UpdateTime = %lx\n",
+ rptinfo.UpdateCount, (unsigned long)rptinfo.UpdateTimestamp);
+#else
+ rv = saHpiSessionOpen(SAHPI_UNSPECIFIED_DOMAIN_ID,&sessionid,NULL);
+ if (rv != SA_OK) {
+ printf("saHpiSessionOpen: %s\n",decode_error(rv));
+ exit(-1);
+ }
+ rv = saHpiDiscover(sessionid);
+ if (fdebug) printf("saHpiDiscover %s\n",decode_error(rv));
+#endif
+
+#ifndef HPI_A
+ if (fdomain != 0) /* saw option for domain event log */
+ {
+ /* resourceid = 1; * oh_get_default_domain_id() */
+ resourceid = SAHPI_UNSPECIFIED_DOMAIN_ID;
+ if (fclear) {
+ rv = saHpiEventLogClear(sessionid,resourceid);
+ if (rv == SA_OK) printf("Domain EventLog successfully cleared\n");
+ else printf("Domain EventLog clear, error = %d\n",rv);
+ } else {
+ rv = DoEventLogForResource(sessionid, resourceid, "Domain Event Log");
+ }
+ }
+ else /* walk the RPT list */
+#endif
+ {
+ rptentryid = SAHPI_OLDEST_ENTRY;
+ while ((rv == SA_OK) && (rptentryid != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiRptEntryGet(sessionid,rptentryid,&nextrptentryid,&rptentry);
+ if (fdebug)
+ printf("saHpiRptEntryGet[%d] %s\n",rptentryid,decode_error(rv));
+ if (rv != SA_OK)
+ goto skip_to_next;
+ resourceid = rptentry.ResourceId;
+ if (fdebug) printf("RPT %x capabilities = %x\n", resourceid,
+ rptentry.ResourceCapabilities);
+ if ((rptentry.ResourceCapabilities & SAHPI_CAPABILITY_SEL) == 0)
+ goto skip_to_next;
+ if (fclear) {
+ rv = saHpiEventLogClear(sessionid,resourceid);
+ if (rv == SA_OK) printf("EventLog successfully cleared\n");
+ else printf("EventLog clear, error = %d\n",rv);
+ break;
+ }
+ // rptentry.ResourceTag.Data[rptentry.ResourceTag.DataLength] = 0;
+
+ rv = DoEventLogForResource(sessionid, resourceid,
+ rptentry.ResourceTag.Data);
+ skip_to_next:
+ rptentryid = nextrptentryid;
+ }
+ }
+
+ rv = saHpiSessionClose(sessionid);
+#ifdef HPI_A
+ rv = saHpiFinalize();
+#endif
+
+ exit(0);
+}
+
+/* end hpisel.c */
diff --git a/hpiutil/hpisensor.c b/hpiutil/hpisensor.c
new file mode 100644
index 0000000..f7eef8f
--- /dev/null
+++ b/hpiutil/hpisensor.c
@@ -0,0 +1,467 @@
+/*
+ * hpisensor.c
+ *
+ * Author: Andy Cress arcress at users.sourceforge.net
+ * Copyright (c) 2003 Intel Corporation.
+ *
+ * 04/15/03 Andy Cress - created
+ * 04/17/03 Andy Cress - mods for resourceid, first good run
+ * 04/28/03 Andy Cress - adding Convert
+ * 05/02/03 Andy Cress v0.6 more Convert changes in ShowSensor (e.g. units)
+ * 06/06/03 Andy Cress v0.7 add more units, and buffer type
+ * 06/09/03 Andy Cress v0.8 added more for Compact Sensors
+ * 06/26/03 Andy Cress v1.0 added -t for thresholds
+ * 02/19/04 Andy Cress v1.1 recognize common errors for Compact & mBMC sensors.
+ * 10/14/04 Andy Cress v1.2 added HPI_A/HPI_B logic
+ * 01/07/05 Andy Cress v1.3 added HPI_B sleep for OpenHPI bug
+ */
+/*M*
+Copyright (c) 2003, 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 <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include <unistd.h>
+#include "SaHpi.h"
+
+#ifdef HPI_A
+char progver[] = "1.3 HPI-A";
+#else
+char progver[] = "1.3 HPI-B";
+#endif
+int fdebug = 0;
+int fshowthr = 0;
+char *rtypes[5] = {"None ", "Control ", "Sensor ", "Invent ", "Watchdog"};
+
+#define NSU 77
+char *units[NSU] = {
+"units", "degrees C", "degrees F", "degrees K", "volts", "amps",
+"watts", "joules", "coulombs", "va", "nits", "lumen",
+"lux", "candela", "kpa", "psi", "newton", "cfm",
+"rpm", "Hz", "us", "ms", "sec", "min",
+"hours", "days", "weeks", "mil", "in", "ft",
+/*30*/ "cu in", "cu ft", "mm", "cm", "m", "cu cm", "cu m",
+"liters", "fl oz", "radians", "sterad", "rev",
+"cycles", "grav", "oz", "lbs", "ft lb", "oz in", "gauss",
+"gilberts", "henry", "mhenry", "farad", "ufarad", "ohms",
+/*55*/ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "Gb",
+/*70*/ "bytes", "KB", "MB", "GB",
+/*74*/ "", "", "line"
+};
+
+#define NECODES 27
+struct { int code; char *str;
+} ecodes[NECODES] = {
+ { 0, "Success" },
+ { -1001, "HPI unspecified error" },
+ { -1002, "HPI unsupported function" },
+ { -1003, "HPI busy" },
+ { -1004, "HPI request invalid" },
+ { -1005, "HPI command invalid" },
+ { -1006, "HPI timeout" },
+ { -1007, "HPI out of space" },
+ { -1008, "HPI data truncated" },
+#ifdef HPI_A
+ { -1009, "HPI data length invalid" },
+#else
+ { -1009, "HPI invalid parameter" },
+#endif
+ { -1010, "HPI data exceeds limits" },
+ { -1011, "HPI invalid params" },
+ { -1012, "HPI invalid data" },
+ { -1013, "HPI not present" },
+ { -1014, "HPI invalid data field" },
+ { -1015, "HPI invalid sensor command" },
+ { -1016, "HPI no response" },
+ { -1017, "HPI duplicate request" },
+ { -1018, "HPI updating" },
+ { -1019, "HPI initializing" },
+ { -1020, "HPI unknown error" },
+ { -1021, "HPI invalid session" },
+ { -1022, "HPI invalid domain" },
+ { -1023, "HPI invalid resource id" },
+ { -1024, "HPI invalid request" },
+ { -1025, "HPI entity not present" },
+ { -1026, "HPI uninitialized" }
+};
+char def_estr[15] = "HPI error %d ";
+
+static
+char *decode_error(SaErrorT code)
+{
+ int i;
+ char *str = NULL;
+ for (i = 0; i < NECODES; i++) {
+ if (code == ecodes[i].code) { str = ecodes[i].str; break; }
+ }
+ if (str == NULL) {
+ sprintf(&def_estr[10],"%d",code);
+ str = &def_estr[0];
+ }
+ return(str);
+}
+
+static
+void ShowSensor(
+ SaHpiSessionIdT sessionid,
+ SaHpiResourceIdT resourceid,
+ SaHpiSensorRecT *sensorrec )
+{
+ SaHpiSensorNumT sensornum;
+ SaHpiSensorReadingT reading;
+ SaHpiSensorThresholdsT senstbuff;
+#ifdef HPI_A
+ SaHpiSensorReadingT conv_reading;
+#else
+ SaHpiEventStateT evtstate;
+#endif
+ SaErrorT rv;
+ char *unit;
+ int i;
+
+ sensornum = sensorrec->Num;
+#ifdef HPI_A
+ rv = saHpiSensorReadingGet(sessionid,resourceid, sensornum, &reading);
+#else
+ rv = saHpiSensorReadingGet(sessionid,resourceid, sensornum, &reading,&evtstate);
+#endif
+ /* ReadingGet returns -1024 if SDR type is mBMC */
+ if (!fdebug && rv == SA_ERR_HPI_INVALID_REQUEST) {
+ printf(" = no reading\n");
+ return;
+ } else if (rv != SA_OK) {
+ printf("ReadingGet ret=%d\n", rv);
+ return;
+ }
+
+#ifdef HPI_A
+ if ((reading.ValuesPresent & SAHPI_SRF_INTERPRETED) == 0) {
+ if ((reading.ValuesPresent & SAHPI_SRF_RAW) == 0) {
+ /* no raw or interpreted, so just show event status */
+ /* This is a Compact Sensor */
+ if (reading.ValuesPresent & SAHPI_SRF_EVENT_STATE)
+ printf(" = %x %x\n", reading.EventStatus.SensorStatus,
+ reading.EventStatus.EventStatus);
+ else printf(" = no reading\n");
+ return;
+ } else {
+ /* have raw, but not interpreted, so try convert. */
+ rv = saHpiSensorReadingConvert(sessionid, resourceid, sensornum,
+ &reading, &conv_reading);
+ if (rv != SA_OK) {
+ /* conv rv=-1012 on Compact sensors */
+ if (!fdebug && rv == SA_ERR_HPI_INVALID_DATA)
+ printf(" = %02x raw\n", reading.Raw);
+ else printf("raw=%x conv_ret=%d\n", reading.Raw, rv);
+ /* printf("conv_rv=%s\n", decode_error(rv)); */
+ return;
+ }
+ else {
+ if (fdebug) printf("conv ok: raw=%x conv=%x\n", reading.Raw,
+ conv_reading.Interpreted.Value.SensorUint32);
+ reading.Interpreted.Type = conv_reading.Interpreted.Type;
+ if (reading.Interpreted.Type == SAHPI_SENSOR_INTERPRETED_TYPE_BUFFER)
+ {
+ memcpy(reading.Interpreted.Value.SensorBuffer,
+ conv_reading.Interpreted.Value.SensorBuffer,
+ 4); /* SAHPI_SENSOR_BUFFER_LENGTH); */
+ /* IPMI 1.5 only returns 4 bytes */
+ } else
+ reading.Interpreted.Value.SensorUint32 =
+ conv_reading.Interpreted.Value.SensorUint32;
+ }
+ }
+ }
+ /* Also show units of interpreted reading */
+ i = sensorrec->DataFormat.BaseUnits;
+ if (i >= NSU) i = 0;
+ unit = units[i];
+ switch(reading.Interpreted.Type)
+ {
+ case SAHPI_SENSOR_INTERPRETED_TYPE_FLOAT32:
+ printf(" = %5.2f %s\n",
+ reading.Interpreted.Value.SensorFloat32,unit);
+ break;
+ case SAHPI_SENSOR_INTERPRETED_TYPE_UINT32:
+ printf(" = %d %s\n",
+ reading.Interpreted.Value.SensorUint32, unit);
+ break;
+ case SAHPI_SENSOR_INTERPRETED_TYPE_BUFFER:
+ printf(" = %02x %02x %02x %02x\n",
+ reading.Interpreted.Value.SensorBuffer[0],
+ reading.Interpreted.Value.SensorBuffer[1],
+ reading.Interpreted.Value.SensorBuffer[2],
+ reading.Interpreted.Value.SensorBuffer[3]);
+ break;
+ default:
+ printf(" = %x (itype=%x)\n",
+ reading.Interpreted.Value.SensorUint32,
+ reading.Interpreted.Type);
+ }
+
+ if (fshowthr) { /* Show thresholds, if any */
+#ifdef SHOWMAX
+ if ( sensorrec->DataFormat.Range.Flags & SAHPI_SRF_MAX )
+ printf( " Max of Range: %5.2f\n",
+ sensorrec->DataFormat.Range.Max.Interpreted.Value.SensorFloat32);
+ if ( sensorrec->DataFormat.Range.Flags & SAHPI_SRF_MIN )
+ printf( " Min of Range: %5.2f\n",
+ sensorrec->DataFormat.Range.Min.Interpreted.Value.SensorFloat32);
+#endif
+ if ((!sensorrec->Ignore) && (sensorrec->ThresholdDefn.IsThreshold)) {
+ rv = saHpiSensorThresholdsGet(sessionid, resourceid,
+ sensornum, &senstbuff);
+ if (rv != 0) { printf("ThresholdsGet ret=%d\n", rv); return; }
+ printf( "\t\t\t");
+ if ( sensorrec->ThresholdDefn.ReadThold & SAHPI_STM_LOW_MINOR ) {
+ printf( "LoMin %5.2f ",
+ senstbuff.LowMinor.Interpreted.Value.SensorFloat32);
+ }
+ if ( sensorrec->ThresholdDefn.ReadThold & SAHPI_STM_LOW_MAJOR ) {
+ printf( "LoMaj %5.2f ",
+ senstbuff.LowMajor.Interpreted.Value.SensorFloat32);
+ }
+ if ( sensorrec->ThresholdDefn.ReadThold & SAHPI_STM_LOW_CRIT ) {
+ printf( "LoCri %5.2f ",
+ senstbuff.LowCritical.Interpreted.Value.SensorFloat32);
+ }
+ if ( sensorrec->ThresholdDefn.ReadThold & SAHPI_STM_UP_MINOR ) {
+ printf( "HiMin %5.2f ",
+ senstbuff.UpMinor.Interpreted.Value.SensorFloat32);
+ }
+ if ( sensorrec->ThresholdDefn.ReadThold & SAHPI_STM_UP_MAJOR ) {
+ printf( "HiMaj %5.2f ",
+ senstbuff.UpMajor.Interpreted.Value.SensorFloat32);
+ }
+ if ( sensorrec->ThresholdDefn.ReadThold & SAHPI_STM_UP_CRIT ) {
+ printf( "HiCri %5.2f ",
+ senstbuff.UpCritical.Interpreted.Value.SensorFloat32);
+ }
+#ifdef SHOWMAX
+ if ( sensorrec->ThresholdDefn.ReadThold & SAHPI_STM_UP_HYSTERESIS ) {
+ printf( "Hi Hys %5.2f ",
+ senstbuff.PosThdHysteresis.Interpreted.Value.SensorFloat32);
+ }
+ if ( sensorrec->ThresholdDefn.ReadThold & SAHPI_STM_LOW_HYSTERESIS ) {
+ printf( "Lo Hys %5.2f ",
+ senstbuff.NegThdHysteresis.Interpreted.Value.SensorFloat32);
+ }
+#endif
+ printf( "\n");
+ } /* endif valid threshold */
+ } /* endif showthr */
+
+#else /* HPI_B: HPI B.01.01 logic */
+ i = sensorrec->DataFormat.BaseUnits;
+ if (i >= NSU) i = 0;
+ unit = units[i];
+ switch(reading.Type)
+ {
+ case SAHPI_SENSOR_READING_TYPE_FLOAT64:
+ printf(" = %5.2f %s\n",
+ reading.Value.SensorFloat64,unit);
+ break;
+ case SAHPI_SENSOR_READING_TYPE_UINT64:
+ printf(" = %lld %s\n",
+ reading.Value.SensorUint64, unit);
+ break;
+ case SAHPI_SENSOR_READING_TYPE_INT64:
+ printf(" = %lld %s\n",
+ reading.Value.SensorInt64, unit);
+ break;
+ case SAHPI_SENSOR_READING_TYPE_BUFFER:
+ printf(" = %02x %02x %02x %02x\n",
+ reading.Value.SensorBuffer[0],
+ reading.Value.SensorBuffer[1],
+ reading.Value.SensorBuffer[2],
+ reading.Value.SensorBuffer[3]);
+ break;
+ default:
+ printf(" = %llx (itype=%x)\n",
+ reading.Value.SensorUint64,
+ reading.Type);
+ }
+ if (fshowthr) { /* Show thresholds, if any */
+ if (sensorrec->ThresholdDefn.IsAccessible) {
+ rv = saHpiSensorThresholdsGet(sessionid, resourceid,
+ sensornum, &senstbuff);
+ if (rv != SA_OK) { printf("ThresholdsGet ret=%d\n", rv);
+ } else {
+ printf( "\t\t\t");
+ if ( sensorrec->ThresholdDefn.ReadThold & SAHPI_STM_LOW_MINOR ) {
+ printf( "LoMin %5.2f ",
+ senstbuff.LowMinor.Value.SensorFloat64);
+ }
+ if ( sensorrec->ThresholdDefn.ReadThold & SAHPI_STM_LOW_MAJOR ) {
+ printf( "LoMaj %5.2f ",
+ senstbuff.LowMajor.Value.SensorFloat64);
+ }
+ if ( sensorrec->ThresholdDefn.ReadThold & SAHPI_STM_LOW_CRIT ) {
+ printf( "LoCri %5.2f ",
+ senstbuff.LowCritical.Value.SensorFloat64);
+ }
+ if ( sensorrec->ThresholdDefn.ReadThold & SAHPI_STM_UP_MINOR ) {
+ printf( "HiMin %5.2f ",
+ senstbuff.UpMinor.Value.SensorFloat64);
+ }
+ if ( sensorrec->ThresholdDefn.ReadThold & SAHPI_STM_UP_MAJOR ) {
+ printf( "HiMaj %5.2f ",
+ senstbuff.UpMajor.Value.SensorFloat64);
+ }
+ if ( sensorrec->ThresholdDefn.ReadThold & SAHPI_STM_UP_CRIT ) {
+ printf( "HiCri %5.2f ",
+ senstbuff.UpCritical.Value.SensorFloat64);
+ }
+ printf( "\n");
+ } /*endif get ok*/
+ } /* endif valid threshold */
+ } /* endif showthr */
+#endif
+ return;
+} /*end ShowSensor*/
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ SaErrorT rv;
+ SaHpiSessionIdT sessionid;
+#ifdef HPI_A
+ SaHpiVersionT hpiVer;
+ SaHpiRptInfoT rptinfo;
+#endif
+ SaHpiRptEntryT rptentry;
+ SaHpiEntryIdT rptentryid;
+ SaHpiEntryIdT nextrptentryid;
+ SaHpiEntryIdT entryid;
+ SaHpiEntryIdT nextentryid;
+ SaHpiResourceIdT resourceid;
+ SaHpiRdrT rdr;
+
+ printf("%s: version %s\n",argv[0],progver);
+
+ while ( (c = getopt( argc, argv,"tx?")) != EOF )
+ switch(c) {
+ case 't': fshowthr = 1; break;
+ case 'x': fdebug = 1; break;
+ default:
+ printf("Usage %s [-t -x]\n",argv[0]);
+ printf("where -t = show Thresholds also\n");
+ printf(" -x = show eXtra debug messages\n");
+ exit(1);
+ }
+ if (fdebug) printf("fshowthr = %d, fdebug = %d\n",fshowthr,fdebug);
+#ifdef HPI_A
+ rv = saHpiInitialize(&hpiVer);
+ if (rv != SA_OK) {
+ printf("saHpiInitialize: %s\n",decode_error(rv));
+ exit(-1);
+ }
+ rv = saHpiSessionOpen(SAHPI_DEFAULT_DOMAIN_ID,&sessionid,NULL);
+ if (rv != SA_OK) {
+ if (rv == SA_ERR_HPI_ERROR)
+ printf("saHpiSessionOpen: error %d, SpiLibd not running\n",rv);
+ else
+ printf("saHpiSessionOpen: %s\n",decode_error(rv));
+ exit(-1);
+ }
+ if (fdebug) printf("Starting Discovery ...\n");
+ rv = saHpiResourcesDiscover(sessionid);
+ if (fdebug) printf("saHpiResourcesDiscover %s\n",decode_error(rv));
+ rv = saHpiRptInfoGet(sessionid,&rptinfo);
+ if (fdebug) printf("saHpiRptInfoGet %s\n",decode_error(rv));
+ printf("RptInfo: UpdateCount = %x, UpdateTime = %lx\n",
+ rptinfo.UpdateCount, (unsigned long)rptinfo.UpdateTimestamp);
+#else
+ rv = saHpiSessionOpen(SAHPI_UNSPECIFIED_DOMAIN_ID,&sessionid,NULL);
+ if (rv != SA_OK) {
+ printf("saHpiSessionOpen: %s\n",decode_error(rv));
+ exit(-1);
+ }
+ if (fdebug) printf("Starting Discovery ...\n");
+ rv = saHpiDiscover(sessionid);
+ if (fdebug) printf("saHpiDiscover %s\n",decode_error(rv));
+ if (fshowthr) {
+ /*
+ * If OpenHPI, we need to wait extra time before doing
+ * ThresholdsGet because its discovery isn't really done.
+ */
+ sleep(5);
+ }
+#endif
+
+ /* walk the RPT list */
+ rptentryid = SAHPI_FIRST_ENTRY;
+ while ((rv == SA_OK) && (rptentryid != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiRptEntryGet(sessionid,rptentryid,&nextrptentryid,&rptentry);
+ if (fdebug) printf("saHpiRptEntryGet %s\n",decode_error(rv));
+ if (rv == SA_OK) {
+ /* walk the RDR list for this RPT entry */
+ entryid = SAHPI_FIRST_ENTRY;
+ resourceid = rptentry.ResourceId;
+#ifdef HPI_A
+ rptentry.ResourceTag.Data[rptentry.ResourceTag.DataLength] = 0;
+#endif
+ printf("rptentry[%d] resourceid=%d tag: %s\n",
+ rptentryid,resourceid, rptentry.ResourceTag.Data);
+ while ((rv == SA_OK) && (entryid != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiRdrGet(sessionid,resourceid,
+ entryid,&nextentryid, &rdr);
+ if (fdebug) printf("saHpiRdrGet[%d] rv = %d\n",entryid,rv);
+ if (rv == SA_OK) {
+ char *eol;
+ rdr.IdString.Data[rdr.IdString.DataLength] = 0;
+ if (rdr.RdrType == SAHPI_SENSOR_RDR) eol = " \t";
+ else eol = "\n";
+ printf("RDR[%02d]: %s %s %s",rdr.RecordId,
+ rtypes[rdr.RdrType],rdr.IdString.Data,eol);
+ if (rdr.RdrType == SAHPI_SENSOR_RDR) {
+ ShowSensor(sessionid,resourceid,
+ &rdr.RdrTypeUnion.SensorRec);
+ }
+ entryid = nextentryid;
+ }
+ }
+ rptentryid = nextrptentryid;
+ }
+ }
+
+ rv = saHpiSessionClose(sessionid);
+#ifdef HPI_A
+ rv = saHpiFinalize();
+#endif
+
+ exit(0);
+ return(0);
+}
+
+/* end hpisensor.c */
diff --git a/hpiutil/hpiutil.spec b/hpiutil/hpiutil.spec
new file mode 100644
index 0000000..9fe7a5e
--- /dev/null
+++ b/hpiutil/hpiutil.spec
@@ -0,0 +1,199 @@
+Name: hpiutil
+%define Version 1.1.11
+Version: %Version
+Release: 1
+Summary: Contains HPI server management utilities and library.
+License: BSD
+Group: System/Management
+Source: hpiutil-%Version.tar.gz
+URL: http://ipmiutil.sourceforge.net
+BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
+BuildRequires: gcc
+
+%ifarch x86_pentium3
+AutoReqProv: No
+%endif
+%ifarch x86_pentium4
+AutoReqProv: No
+%endif
+
+%description
+The HPI utilities package provides system management utilities that
+conform to the SA Forum's Hardware Platform Interface specification, and
+as such are hardware-independent across platforms that have an HPI
+library implementation. The HPI library on Intel platforms requires
+an IPMI driver. An IPMI driver can be provided by either the Intel
+IPMI driver (/dev/imb) or the OpenIPMI driver (/dev/ipmi0) in Linux
+kernel versions 2.4.20 and greater.
+
+This package includes the HPI binary libraries and the following
+HPI utilities.
+ hpisensor
+ hpisel
+ hpireset
+ hpiwdt
+ hpifru
+ hpialarmpanel
+
+%prep
+#%setup -q
+
+#%build
+#sh configure
+#make
+
+#%install
+#RPM_BUILD_ROOT=`pwd`
+#make DESTDIR=${RPM_BUILD_ROOT} install
+#( cd ${RPM_BUILD_ROOT}/usr/man/man8; gzip -f *.8 )
+
+%files
+%defattr(0755,root,root)
+/usr/bin/hpifru
+/usr/bin/hpisensor
+/usr/bin/hpialarmpanel
+/usr/bin/hpisel
+/usr/bin/hpiwdt
+/usr/bin/hpireset
+/usr/bin/SpiLibd
+/usr/lib/libSaHpi.so
+/usr/lib/libSpiDaemonCore.so
+/usr/lib/libSpiModGeneric.so
+/usr/lib/libSpiModIpmi.so
+/usr/lib/libSpiModIpmi.so-open
+/usr/lib/libSpiIpmiImb.so
+/usr/lib/libSpiIpmiOpenIpmi.so
+/usr/lib/libSpiTsdMaplx.so
+/etc/hpi/hpiinit.sh
+/usr/share/hpiutil/env.hpi
+%defattr(0664,root,root)
+/usr/share/hpiutil/README
+/usr/share/hpiutil/COPYING
+/etc/hpi/spi-daemon.conf
+/etc/hpi/spi-lib.conf
+# %defattr(-,root,root)
+# %doc README TODO COPYING ChangeLog
+
+%pre
+# before install
+sdir=/usr/share/hpiutil
+edir=/etc/hpi
+echo "Installing HPI Utilities ..."
+mkdir -p $sdir
+mkdir -p $edir
+
+# Check for an IPMI driver
+rpm -qa |grep ipmidrvr >/dev/null
+if [ $? -ne 0 ]
+then
+ # Intel ipmidrvr package is not installed, but other IPMI drivers
+ # could also be used, so test for device files.
+ dev1=/dev/imb
+ dev2=/dev/ipmi0
+ dev3=/dev/ipmi/0
+ dev4=/dev/ipmikcs
+ if [ ! -c $dev1 ]
+ then
+ if [ ! -c $dev2 ]
+ then
+ if [ ! -c $dev3 ]
+ then
+ echo "WARNING: No IPMI devices found ($dev1, $dev2 or $dev3)."
+ echo "The HPI utilities depend on an IPMI driver. "
+ fi
+ fi
+ fi
+fi
+
+%post
+# after install
+sdir=/usr/share/hpiutil
+edir=/etc/hpi
+
+echo "hpiutil install started `date`"
+# Assumes that the kernel modules are already in place.
+
+# The spi-daemon.conf file should have 'localhost' as the
+# server name. User can modify this if remote.
+
+# set up the init.d jobs
+loadhpi=/etc/hpi/hpiinit.sh
+if [ -d /etc/rc.d/init.d ]
+then
+ # RedHat init.d structure
+ cd /etc/rc.d/init.d
+ cp $loadhpi ./hpi
+ echo "To autostart hpi, enter: chkconfig --add hpi"
+# chkconfig --add hpi
+# Or manually create links
+# cd ../rc3.d
+# ln -s ../init.d/hpi S81hpi 2>/dev/null
+# ln -s ../init.d/hpi K35hpi 2>/dev/null
+# cd ../rc5.d
+# ln -s ../init.d/hpi S81hpi 2>/dev/null
+# ln -s ../init.d/hpi K35hpi 2>/dev/null
+# cd ../rc6.d
+# ln -s ../init.d/hpi K35hpi 2>/dev/null
+# cd ../rc0.d
+# ln -s ../init.d/hpi K35hpi 2>/dev/null
+else
+ # SuSE init.d structure
+ cd /etc/init.d
+ cp $loadhpi ./hpi
+ echo "To autostart hpi, enter: /usr/lib/lsb/install_initd /etc/init.d/hpi "
+# /usr/lib/lsb/install_initd /etc/init.d/hpi
+# Or manually create links
+# cd rc3.d
+# ln -s ../hpi S81hpi 2>/dev/null
+# ln -s ../hpi K35hpi 2>/dev/null
+# cd ../rc5.d
+# ln -s ../hpi S81hpi 2>/dev/null
+# ln -s ../hpi K35hpi 2>/dev/null
+# cd ../rc6.d
+# ln -s ../hpi K35hpi 2>/dev/null
+# cd ../rc0.d
+# ln -s ../hpi K35hpi 2>/dev/null
+fi
+
+echo "done `date`"
+
+%preun
+# before uninstall
+echo "Uninstalling HPI Utilities feature ..."
+/etc/hpi/hpiinit.sh stop 2>/dev/null
+
+%postun
+# after uninstall, clean up anything left over
+sdir=/usr/share/hpiutil
+edir=/etc/hpi
+tmped=/tmp/edmk.tmp
+
+if [ -d /etc/rc.d/init.d ]
+then
+ # RedHat init.d structure
+# chkconfig --del hpi
+ cd /etc/rc.d/init.d
+ rm -f hpi ../rc?.d/S81hpi ../rc?.d/K35hpi
+else
+ # SuSE init.d structure
+# /usr/lib/lsb/remove_initd /etc/init.d/hpi
+ cd /etc/init.d
+ rm -f hpi rc?.d/S81hpi rc?.d/K35hpi
+fi
+rm -rf $sdir 2>/dev/null
+
+%changelog
+* Tue Apr 06 2004 Andrew Cress <arcress at users.sourceforge.net>
+ changed to not turn on hpi autostart scripts at rpm install
+* Fri Mar 26 2004 Andrew Cress <arcress at users.sourceforge.net>
+- changed to include proper kill scripts and chkconfig info
+* Thu Feb 12 2004 Andrew Cress <arcress at users.sourceforge.net>
+- changed naming from /etc/init.d/hpiinit.sh to /etc/init.d/hpi
+* Fri Jun 27 2003 Andrew Cress <arcress at users.sourceforge.net>
+- updated to check for ipmidrvr rpm, since no /dev/imb until reboot.
+* Fri Jun 20 2003 Andrew Cress <arcress at users.sourceforge.net>
+- updated for README & released file locations
+* Thu Jun 12 2003 Andrew Cress <arcress at users.sourceforge.net>
+- updated for beta2 file naming
+* Tue May 05 2003 Andrew Cress <arcress at users.sourceforge.net>
+- created
diff --git a/hpiutil/hpiwdt.c b/hpiutil/hpiwdt.c
new file mode 100644
index 0000000..efa732d
--- /dev/null
+++ b/hpiutil/hpiwdt.c
@@ -0,0 +1,272 @@
+/*
+ * hpiwdt.c
+ *
+ * Copyright (c) 2003-2004 Intel Corporation.
+ *
+ * This tool reads and enables the watchdog timer via HPI.
+ * 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/reset the watchdog, make sure you have
+ * something set up to keep resetting the timer at regular intervals,
+ * or it will reset your system.
+ *
+ * Author: Andy Cress arcress at users.sourceforge.net
+ *
+ * 05/02/03 Andy Cress - created
+ * 06/06/03 Andy Cress - added more logic with beta2 SPI release
+ * 06/11/03 Andy Cress - successful test of options to set WDT values.
+ * 03/15/04 Andy Cress v1.0 - added strings for use & actions in show_wdt
+ * 12/02/04 Andy Cress v1.1 - fixed RPT loop, added more decoding,
+ * added flags for HPI_A/HPI_B.
+ */
+/*M*
+Copyright (c) 2004, 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include "SaHpi.h"
+
+#define uchar unsigned char
+#ifdef HPI_A
+char *progver = "1.1 HPI-A";
+#else
+char *progver = "1.1 HPI-B";
+#endif
+char fdebug = 0;
+#define NUSE 6
+char *usedesc[NUSE] = {"reserved", "BIOS FRB2", "BIOS/POST",
+ "OS Load", "SMS/OS", "OEM" };
+#define NACT 5
+char *actions[NACT] = {"No action", "Hard Reset", "Power down",
+ "Power cycle", "Reserved" };
+
+static void
+show_wdt(SaHpiWatchdogNumT wdnum, SaHpiWatchdogT *wdt)
+{
+ int icount, pcount;
+ char ustr[12];
+ char astr[16];
+ char estr[30];
+ char *pstr;
+ icount = wdt->InitialCount /1000; /*1000 msec = 1 sec*/
+ pcount = wdt->PresentCount /1000;
+
+ if (wdt->TimerUse > NUSE) sprintf(ustr,"%d", wdt->TimerUse );
+ else strcpy(ustr, usedesc[wdt->TimerUse]);
+ if (wdt->TimerAction > NACT) sprintf(astr,"%d", wdt->TimerAction );
+ else strcpy(astr, actions[wdt->TimerAction]);
+ printf("Watchdog: Num=%d, Log=%d, Running=%d, TimerUse=%s, TimerAction=%s\n",
+ wdnum,wdt->Log,wdt->Running,ustr, astr);
+ if (wdt->TimerUseExpFlags == 0) strcpy(estr,"none");
+ else {
+ estr[0] = 0;
+ if (wdt->TimerUseExpFlags & 0x01) strcat(estr,"FRB2 ");
+ if (wdt->TimerUseExpFlags & 0x02) strcat(estr,"POST ");
+ if (wdt->TimerUseExpFlags & 0x04) strcat(estr,"OS_Load ");
+ if (wdt->TimerUseExpFlags & 0x08) strcat(estr,"SMS_OS ");
+ if (wdt->TimerUseExpFlags & 0x10) strcat(estr,"OEM ");
+ }
+ printf(" ExpiredUse=%s, Timeout=%d sec, Counter=%d sec\n",
+ estr, icount,pcount);
+ switch(wdt->PretimerInterrupt) {
+ case 1: pstr = "SMI"; break;
+ case 2: pstr = "NMI"; break;
+ case 3: pstr = "MsgInt"; break;
+ default: pstr = "none"; break;
+ }
+ printf(" PreTimerInterrupt=%s, PreTimeoutInterval=%d msec\n",
+ pstr,wdt->PreTimeoutInterval);
+ return;
+} /*end show_wdt*/
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ SaErrorT rv;
+ SaHpiSessionIdT sessionid;
+#ifdef HPI_A
+ SaHpiVersionT hpiVer;
+ SaHpiRptInfoT rptinfo;
+#else
+ SaHpiDomainInfoT domainInfo;
+#endif
+ SaHpiRptEntryT rptentry;
+ SaHpiEntryIdT rptentryid;
+ SaHpiEntryIdT nextrptentryid;
+ SaHpiResourceIdT resourceid;
+ SaHpiWatchdogNumT wdnum;
+ SaHpiWatchdogT wdt;
+ int t = 0;
+ char freset = 0;
+ char fenable = 0;
+ char fdisable = 0;
+
+ printf("%s ver %s\n", argv[0],progver);
+ while ( (c = getopt( argc, argv,"dert:x?")) != EOF )
+ switch(c) {
+ case 'r': /* reset wdt */
+ freset = 1;
+ break;
+ case 'e': /* disable wdt */
+ fenable = 1;
+ break;
+ case 'd': /* disable wdt */
+ fdisable = 1;
+ break;
+ case 't': /* timeout (enable implied) */
+ t = atoi(optarg);
+ fenable = 1;
+ break;
+ case 'x': fdebug = 1; break; /* debug messages */
+ default:
+ printf("Usage: %s [-derx -t sec]\n", argv[0]);
+ printf(" where -e enables the watchdog timer\n");
+ printf(" -d disables the watchdog timer\n");
+ printf(" -r resets the watchdog timer\n");
+ printf(" -t N sets timeout to N seconds\n");
+ printf(" -x show eXtra debug messages\n");
+ exit(1);
+ }
+ if (t == 0) t = 120;
+
+#ifdef HPI_A
+ rv = saHpiInitialize(&hpiVer);
+ if (rv != SA_OK) {
+ printf("saHpiInitialize error %d\n",rv);
+ exit(-1);
+ }
+ rv = saHpiSessionOpen(SAHPI_DEFAULT_DOMAIN_ID,&sessionid,NULL);
+ if (rv != SA_OK) {
+ if (rv == SA_ERR_HPI_ERROR)
+ printf("saHpiSessionOpen: error %d, library not running\n",rv);
+ else printf("saHpiSessionOpen error %d\n",rv);
+ exit(-1);
+ }
+ rv = saHpiResourcesDiscover(sessionid);
+ if (fdebug) printf("saHpiResourcesDiscover rv = %d\n",rv);
+ rv = saHpiRptInfoGet(sessionid,&rptinfo);
+ if (fdebug) printf("saHpiRptInfoGet rv = %d\n",rv);
+ printf("RptInfo: UpdateCount = %x, UpdateTime = %lx\n",
+ rptinfo.UpdateCount, (unsigned long)rptinfo.UpdateTimestamp);
+#else
+ rv = saHpiSessionOpen(SAHPI_UNSPECIFIED_DOMAIN_ID, &sessionid, NULL);
+ if (rv != SA_OK) {
+ printf("saHpiSessionOpen error %d\n",rv);
+ exit(-1);
+ }
+ rv = saHpiDiscover(sessionid);
+ if (fdebug) printf("saHpiDiscover rv = %d\n",rv);
+ rv = saHpiDomainInfoGet(sessionid, &domainInfo);
+ if (fdebug) printf("saHpiDomainInfoGet rv = %d\n",rv);
+ printf("DomainInfo: UpdateCount = %x, UpdateTime = %lx\n",
+ domainInfo.RptUpdateCount, (unsigned long)domainInfo.RptUpdateTimestamp);
+#endif
+
+ /* walk the RPT list */
+ rptentryid = SAHPI_FIRST_ENTRY;
+ while ((rv == SA_OK) && (rptentryid != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiRptEntryGet(sessionid,rptentryid,&nextrptentryid,&rptentry);
+ if (rv != SA_OK) printf("RptEntryGet: rv = %d\n",rv);
+ if (rv == SA_OK) {
+ /* handle WDT for this RPT entry */
+ resourceid = rptentry.ResourceId;
+#ifdef HPI_A
+ rptentry.ResourceTag.Data[rptentry.ResourceTag.DataLength] = 0;
+#endif
+ if (fdebug)
+ printf("rptentry[%d] resourceid=%d capab=%x tag: %s\n",
+ rptentryid, resourceid, rptentry.ResourceCapabilities,
+ rptentry.ResourceTag.Data);
+
+ if (rptentry.ResourceCapabilities & SAHPI_CAPABILITY_WATCHDOG) {
+ printf("%s has watchdog capability\n",rptentry.ResourceTag.Data);
+
+ wdnum = SAHPI_DEFAULT_WATCHDOG_NUM;
+ rv = saHpiWatchdogTimerGet(sessionid,resourceid,wdnum,&wdt);
+ if (fdebug) printf("saHpiWatchdogTimerGet rv = %d\n",rv);
+ if (rv != 0) {
+ printf("saHpiWatchdogTimerGet error = %d\n",rv);
+ rv = 0;
+ rptentryid = nextrptentryid;
+ continue;
+ }
+ show_wdt(wdnum,&wdt);
+
+ if (fdisable) {
+ printf("Disabling watchdog timer ...\n");
+ /* clear FRB2, timeout back to 120 sec */
+ /* TODO: add setting wdt values here */
+ wdt.TimerUse = SAHPI_WTU_NONE; /* 1=FRB2 2=POST 3=OSLoad 4=SMS_OS 5=OEM */
+ wdt.TimerAction = SAHPI_WAE_NO_ACTION; /* 0=none 1=reset 2=powerdown 3=powercycle */
+ wdt.PretimerInterrupt = SAHPI_WPI_NONE; /* 0=none 1=SMI 2=NMI 3=message */
+ wdt.PreTimeoutInterval = 60000; /*msec*/
+ wdt.InitialCount = 120000; /*msec*/
+ wdt.PresentCount = 120000; /*msec*/
+
+ rv = saHpiWatchdogTimerSet(sessionid,resourceid,wdnum,&wdt);
+ if (fdebug) printf("saHpiWatchdogTimerSet rv = %d\n",rv);
+ if (rv == 0) show_wdt(wdnum,&wdt);
+ } else if (fenable) {
+ printf("Enabling watchdog timer ...\n");
+ /* hard reset action, no pretimeout, clear SMS/OS when done */
+ /* use t for timeout */
+ wdt.TimerUse = SAHPI_WTU_SMS_OS; /* 1=FRB2 2=POST 3=OSLoad 4=SMS_OS 5=OEM */
+ wdt.TimerAction = SAHPI_WAE_RESET; /* 0=none 1=reset 2=powerdown 3=powercycle */
+ wdt.PretimerInterrupt = SAHPI_WPI_NMI; /* 0=none 1=SMI 2=NMI 3=message */
+ wdt.PreTimeoutInterval = (t / 2) * 1000; /*msec*/
+ wdt.InitialCount = t * 1000; /*msec*/
+ wdt.PresentCount = t * 1000; /*msec*/
+
+ rv = saHpiWatchdogTimerSet(sessionid,resourceid,wdnum,&wdt);
+ if (fdebug) printf("saHpiWatchdogTimerSet rv = %d\n",rv);
+ if (rv == 0) show_wdt(wdnum,&wdt);
+ }
+ if (freset && !fdisable) {
+ printf("Resetting watchdog timer ...\n");
+ rv = saHpiWatchdogTimerReset(sessionid,resourceid,wdnum);
+ if (fdebug) printf("saHpiWatchdogTimerReset rv = %d\n",rv);
+ }
+ } /*watchdog capability*/
+ rptentryid = nextrptentryid; /* get next RPT (usu only one anyway) */
+ } /*endif RPT ok*/
+ } /*end while loop*/
+
+ rv = saHpiSessionClose(sessionid);
+
+#ifdef HPI_A
+ rv = saHpiFinalize();
+#endif
+ exit(0);
+}
+
+/* end hpiwdt.c */
diff --git a/hpiutil/mkrpm b/hpiutil/mkrpm
new file mode 100755
index 0000000..e64f995
--- /dev/null
+++ b/hpiutil/mkrpm
@@ -0,0 +1,135 @@
+# mkrpm
+# Make the rpms for hpiutil
+#
+# Reliab11 = RedHat 8.0 (rh80)
+# Reliab12 = RedHat 9.0 (rh90)
+# Reliab13 = MV CGE 2.1 (mv21)
+# Reliab14 = MV CGE 3.0 (mv30p3)
+# Reliab01 = MV CGE 3.1 (mv31p3)
+# Reliab03 = RedHat AS 2.1 (as21)
+# chapin4 = MV CGE 3.1 (mv31p4)
+# grumpy = RedHat EL 3 (el3)
+# chesnee1 = RedHat EL 3 (el3)
+# telcoraid= SuSE UL 1.0 (ul10)
+#
+ROOT=`pwd`
+# usually /mnt/pub/panich/hpi/hpiutil
+RTARG=rpm
+RSPEC=hpiutil.spec
+RTO=$ROOT/$RTARG/usr/bin
+STO=$ROOT/$RTARG/usr/share/hpiutil
+ETO=$ROOT/$RTARG/etc/hpi
+OS=el3
+VER=`grep "^%define Version" $RSPEC |cut -f3 -d' '`
+tmpe=/tmp/ed.tmp
+rpmcmd=rpmbuild
+
+if [ $# -ge 1 ]
+then
+ OS=$1
+fi
+case $OS in
+"mv21")
+ archv=x86_pentium3
+ ;;
+"mv30")
+ archv=x86_pentium3
+ ;;
+"mv30wv")
+ archv=x86_pentium4
+ ;;
+"mv31p4")
+ archv=x86_pentium4
+ ;;
+"mv31p3")
+ archv=x86_pentium3
+ ;;
+"ul10")
+ rpmcmd=rpm
+ archv=i386
+ ;;
+*)
+ archv=i386
+ ;;
+esac
+
+# Modify the env for EL3 & others
+if [ "$OS" = "el3" ]
+then
+ cmt=
+else
+ cmt="#"
+fi
+cat - <<%%% >$tmpe
+1
+/LD_ASSUME_KERNEL
+c
+$cmt export LD_ASSUME_KERNEL=2.4.1
+.
+w
+q
+%%%
+ed hpiinit.sh <$tmpe
+ed env.hpi <$tmpe
+ed obj/env.hpi <$tmpe
+
+echo "Copying lib files to rpm, OS=$OS ..."
+mkdir -p $RTO
+mkdir -p $ROOT/$RTARG/usr/lib
+cp -uf $ROOT/obj/${OS}/SpiLibd $RTO
+cp -uf $ROOT/obj/${OS}/*.so $ROOT/$RTARG/usr/lib
+cp -uf $ROOT/obj/${OS}/*.so-open $ROOT/$RTARG/usr/lib
+
+# Make the matching hpiutil binaries
+cd $ROOT
+make clean
+make
+echo "Copying files for rpm, OS=$OS ..."
+mkdir -p $ETO
+mkdir -p $ROOT/$RTARG/etc/init.d
+mkdir -p $STO
+cp -uf $ROOT/hpialarmpanel $RTO
+cp -uf $ROOT/hpisensor $RTO
+cp -uf $ROOT/hpisel $RTO
+cp -uf $ROOT/hpifru $RTO
+cp -uf $ROOT/hpiwdt $RTO
+cp -uf $ROOT/hpireset $RTO
+cp -uf $ROOT/hpiinit.sh $ETO
+cp -uf $ROOT/README $STO
+cp -uf $ROOT/COPYING $STO
+cp -uf $ROOT/obj/env.hpi $STO
+cp -uf $ROOT/obj/spi-daemon.conf $ETO
+cp -uf $ROOT/obj/spi-lib.conf $ETO
+
+
+# (new:)
+# libSaHpi.so libSpiIpmiImb.so libSpiModIpmi.so SpiLibd
+# libSpiDaemonCore.so libSpiModGeneric.so libSpiTsdMaplx.so
+# (old:)
+# libSaHpi.so libSpiDaemonCore.so libSpiGenericMaplx.so libSpiModGeneric.so
+# libSpiModIpmi.so libSpiModMullins.so libSpiMullinsMaplx.so
+# libSpiIpmiImb.so libSpiIpmiOpenIpmi.so
+
+echo "Making hpiutil rpm ..."
+#rpmbuild -bb $RSPEC
+#HOME=`pwd`
+#export HOME
+rm -f $ROOT/$RTARG/$archv/hpiutil*.rpm
+echo "%_rpmdir ${ROOT}/${RTARG}" > $HOME/.rpmmacros
+$rpmcmd -bb --buildroot ${ROOT}/${RTARG} $RSPEC
+rm -f $HOME/.rpmmacros
+
+# save the rpm
+rfil=$ROOT/$RTARG/$archv/hpiutil-$VER-?.$archv.rpm
+echo $OS |grep mv31p4 >/dev/null 2>&1
+if [ $? -eq 0 ]
+then
+ rfil=/usr/src/montavista/RPMS/$archv/hpiutil-$VER-?.$archv.rpm
+fi
+cp $rfil $ROOT/obj/hpiutil-$VER-$OS.$archv.rpm
+if [ $? -eq 0 ]
+then
+ # remove the directory
+ rm -rf $ROOT/$RTARG
+fi
+
diff --git a/hpiutil/upd b/hpiutil/upd
new file mode 100755
index 0000000..0967595
--- /dev/null
+++ b/hpiutil/upd
@@ -0,0 +1,24 @@
+# upd
+# update hpi library objects to public share
+#
+# todir=/mnt/pub/panich/hpi/hpiutil
+todir=/mnt/pub/cress/hpi/hpiutil
+hdir=/root/hpi
+cdir=`pwd`
+
+if [ $# -ge 1 ]
+then
+ OS=$1
+else
+ OS=el3
+fi
+mkdir -p $todir/obj/$OS
+# cd $SAHPI_HOME
+cd $hdir
+cp bin/SpiLibd $todir/obj/$OS
+cp lib/*.so* $todir/obj/$OS
+if [ -f lib/Server ]
+then
+ cp lib/Server $todir/obj/$OS
+fi
+cd $cdir
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..4d4a951
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,323 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2005-05-14.22
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+chmodcmd="$chmodprog 0755"
+chowncmd=
+chgrpcmd=
+stripcmd=
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=
+dst=
+dir_arg=
+dstarg=
+no_target_directory=
+
+usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+-c (ignored)
+-d create directories instead of installing files.
+-g GROUP $chgrpprog installed files to GROUP.
+-m MODE $chmodprog installed files to MODE.
+-o USER $chownprog installed files to USER.
+-s $stripprog installed files.
+-t DIRECTORY install into DIRECTORY.
+-T report an error if DSTFILE is a directory.
+--help display this help and exit.
+--version display version info and exit.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
+"
+
+while test -n "$1"; do
+ case $1 in
+ -c) shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd=$stripprog
+ shift
+ continue;;
+
+ -t) dstarg=$2
+ shift
+ shift
+ continue;;
+
+ -T) no_target_directory=true
+ shift
+ continue;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ *) # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ test -n "$dir_arg$dstarg" && break
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dstarg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dstarg"
+ shift # fnord
+ fi
+ shift # arg
+ dstarg=$arg
+ done
+ break;;
+ esac
+done
+
+if test -z "$1"; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+for src
+do
+ # Protect names starting with `-'.
+ case $src in
+ -*) src=./$src ;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ src=
+
+ if test -d "$dst"; then
+ mkdircmd=:
+ chmodcmd=
+ else
+ mkdircmd=$mkdirprog
+ fi
+ else
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dstarg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+
+ dst=$dstarg
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst ;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dstarg: Is a directory" >&2
+ exit 1
+ fi
+ dst=$dst/`basename "$src"`
+ fi
+ fi
+
+ # This sed command emulates the dirname command.
+ dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
+
+ # Make sure that the destination directory exists.
+
+ # Skip lots of stat calls in the usual case.
+ if test ! -d "$dstdir"; then
+ defaultIFS='
+ '
+ IFS="${IFS-$defaultIFS}"
+
+ oIFS=$IFS
+ # Some sh's can't handle IFS=/ for some reason.
+ IFS='%'
+ set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
+ shift
+ IFS=$oIFS
+
+ pathcomp=
+
+ while test $# -ne 0 ; do
+ pathcomp=$pathcomp$1
+ shift
+ if test ! -d "$pathcomp"; then
+ $mkdirprog "$pathcomp"
+ # mkdir can fail with a `File exist' error in case several
+ # install-sh are creating the directory concurrently. This
+ # is OK.
+ test -d "$pathcomp" || exit
+ fi
+ pathcomp=$pathcomp/
+ done
+ fi
+
+ if test -n "$dir_arg"; then
+ $doit $mkdircmd "$dst" \
+ && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
+ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
+ && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
+ && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
+
+ else
+ dstfile=`basename "$dst"`
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+ trap '(exit $?); exit' 1 2 13 15
+
+ # Copy the file name to the temp name.
+ $doit $cpprog "$src" "$dsttmp" &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
+ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
+ && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
+ && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
+
+ # Now rename the file to the real destination.
+ { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
+ || {
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ if test -f "$dstdir/$dstfile"; then
+ $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
+ || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
+ || {
+ echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
+ (exit 1); exit 1
+ }
+ else
+ :
+ fi
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
+ }
+ }
+ fi || { (exit 1); exit 1; }
+done
+
+# The final little trick to "correctly" pass the exit status to the exit trap.
+{
+ (exit 0); exit 0
+}
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/kern/alarms.h b/kern/alarms.h
new file mode 100644
index 0000000..c0ca46a
--- /dev/null
+++ b/kern/alarms.h
@@ -0,0 +1,43 @@
+/*
+ * alarms.h
+ *
+ * Description of what the alarm panel bits mean.
+ *
+ * Note that bit = 0 means on, and bit = 1 means off for these LEDs
+ * (e.g. 0xFF is everything off).
+ * The low nibble (bits 0x0F) is for LEDs, and the high nibble (bits 0x30) is
+ * for the relays. The relays are triggered from the LED settings so the high
+ * nibble doesn't really matter when setting alarms (usu 0xF* in TAM though).
+ *
+ * The TAM API is available with the TAM rpm, for your convenience.
+ * See the bmcpanic.patch for an example of how to set an LED,
+ * at http://panicsel.sourceforge.net
+ */
+
+//
+// masks used to set LED states
+//
+#define AP_SET_NO_LED_MASK 0x0F // bits 0-3 = 1
+#define AP_SET_POWER_MASK 0x0E // bit0 = 0, others = 1
+#define AP_SET_CRITICAL_MASK 0x0D // bit1 = 0
+#define AP_SET_MAJOR_MASK 0x0B // bit2 = 0
+#define AP_SET_MINOR_MASK 0x07 // bit3 = 0
+
+//
+// masks used to get LED states
+//
+#define AP_NO_LED_SET 0x0E
+#define AP_POWER_SET 0x01
+#define AP_CRITICAL_SET 0x0C
+#define AP_MAJOR_SET 0x0A
+#define AP_MINOR_SET 0x06
+
+//
+// masks used to get relay state
+//
+#define AP_ALL_RELAY_MASK 0x00
+#define AP_MINOR_RELAY_MASK 0x10
+#define AP_MAJOR_RELAY_MASK 0x20
+#define AP_NO_RELAY_MASK 0x30
+
+/* end alarms.h */
diff --git a/kern/bmcpanic-2.4.18.patch b/kern/bmcpanic-2.4.18.patch
new file mode 100644
index 0000000..9eae959
--- /dev/null
+++ b/kern/bmcpanic-2.4.18.patch
@@ -0,0 +1,997 @@
+--- linux-2.4.18-orig/drivers/char/misc.c Fri Nov 2 20:46:47 2001
++++ linux-2.4.18/drivers/char/misc.c Thu Feb 27 14:28:39 2003
+@@ -70,6 +70,7 @@
+ extern void gfx_register(void);
+ #endif
+ extern void streamable_init(void);
++extern int bmc_panic_init(void);
+ extern int rtc_DP8570A_init(void);
+ extern int rtc_MK48T08_init(void);
+ extern int ds1286_init(void);
+@@ -264,6 +265,9 @@
+ #endif
+ #ifdef CONFIG_PMAC_PBOOK
+ pmu_device_init();
++#endif
++#ifdef CONFIG_BMCPANIC
++ bmc_panic_init();
+ #endif
+ #ifdef CONFIG_SGI_NEWPORT_GFX
+ gfx_register ();
+--- linux-2.4.18-orig/kernel/panic.c Sun Sep 30 15:26:08 2001
++++ linux-2.4.18/kernel/panic.c Thu Feb 27 14:28:39 2003
+@@ -17,6 +17,10 @@
+ #include <linux/sysrq.h>
+ #include <linux/interrupt.h>
+
++char *panic_string;
++#ifdef CONFIG_BMCPANIC
++ extern void bmcpanic_action(void);
++#endif
+ asmlinkage void sys_sync(void); /* it's really int */
+
+ int panic_timeout;
+@@ -53,6 +57,7 @@
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
++ panic_string = buf;
+ printk(KERN_EMERG "Kernel panic: %s\n",buf);
+ if (in_interrupt())
+ printk(KERN_EMERG "In interrupt handler - not syncing\n");
+@@ -81,7 +86,11 @@
+ * choosing not too. It might crash, be corrupt or do
+ * more harm than good for other reasons.
+ */
+- machine_restart(NULL);
++#ifdef CONFIG_BMCPANIC
++ bmcpanic_action();
++#else
++ machine_restart(NULL);
++#endif
+ }
+ #ifdef __sparc__
+ {
+--- linux-2.4.18-orig/kernel/ksyms.c Mon Feb 25 14:38:13 2002
++++ linux-2.4.18/kernel/ksyms.c Thu Feb 27 14:29:30 2003
+@@ -60,6 +60,7 @@
+
+ extern void *sys_call_table;
+
++extern char *panic_string;
+ extern struct timezone sys_tz;
+ extern int request_dma(unsigned int dmanr, char * deviceID);
+ extern void free_dma(unsigned int dmanr);
+@@ -559,3 +560,5 @@
+
+ EXPORT_SYMBOL(tasklist_lock);
+ EXPORT_SYMBOL(pidhash);
++EXPORT_SYMBOL(panic_notifier_list);
++EXPORT_SYMBOL(panic_string);
+--- linux-2.4.18-orig/Documentation/Configure.help Mon Feb 25 14:37:51 2002
++++ linux-2.4.18/Documentation/Configure.help Thu Feb 27 14:28:39 2003
+@@ -16277,6 +16277,20 @@
+
+ If unsure, say N.
+
++BMC Panic Handler
++CONFIG_BMCPANIC
++ If you say Y here, additional functions will be added to the
++ panic handler via the panic notifier list.
++
++ If your system has IPMI support and a BMC (Baseboard Management
++ Controller) on the motherboard, then the following additional
++ functions will be performed if a panic occurs:
++ - Write an OS Critical Stop message to the firmware System Event Log
++ - Turn on the Critical LED on the Telco Alarms panel (if present)
++ - Send a BMC LAN alert via SNMP to a network operations center,
++ if the firmware Platform Event Filter configuration is set to
++ enable this.
++
+ Cobalt Networks support
+ CONFIG_COBALT
+ Support for Cobalt Networks x86-based servers.
+--- linux-2.4.18-orig/drivers/char/Makefile Mon Feb 25 14:37:57 2002
++++ linux-2.4.18/drivers/char/Makefile Thu Feb 27 14:28:39 2003
+@@ -209,6 +209,9 @@
+ obj-y += ftape/ftape.o
+ endif
+
++bmc_panic-objs := bmc_ipmi.o bmc_selmsg.o
++obj-$(CONFIG_BMCPANIC) += bmc_panic.o
++
+ obj-$(CONFIG_H8) += h8.o
+ obj-$(CONFIG_PPDEV) += ppdev.o
+ obj-$(CONFIG_DZ) += dz.o
+@@ -252,6 +255,9 @@
+ ./conmakehash $(FONTMAPFILE) > consolemap_deftbl.c
+
+ consolemap_deftbl.o: consolemap_deftbl.c $(TOPDIR)/include/linux/types.h
++
++bmc_panic.o: $(bmc_panic-objs)
++ $(LD) -r -o $@ $(bmc_panic-objs)
+
+ .DELETE_ON_ERROR:
+
+--- linux-2.4.18-orig/drivers/char/Config.in Mon Feb 25 14:37:57 2002
++++ linux-2.4.18/drivers/char/Config.in Thu Feb 27 14:28:39 2003
+@@ -97,6 +97,10 @@
+ if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
+ int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
+ fi
++bool 'BMC Panic Handler' CONFIG_BMCPANIC
++if [ "$CONFIG_BMCPANIC" != "n" ]; then
++ int ' Action after Panic (0=reset,1=power down,2=power cycle)' CONFIG_BMCPANIC_ACTION 0
++fi
+ if [ "$CONFIG_PARPORT" != "n" ]; then
+ dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
+ if [ "$CONFIG_PRINTER" != "n" ]; then
+--- /dev/null Fri Mar 23 23:37:44 2001
++++ linux-2.4.18/drivers/char/bmc_ipmi.c Thu Feb 27 14:28:39 2003
+@@ -0,0 +1,531 @@
++/*
++ * bmc_ipmi.c
++ *
++ * This code is needed to run a streamlined IPMI KCS command when
++ * the rest of the system may be dead (panic time). It must wait
++ * for completion of the receive function also.
++ * There will be zero or one BMC, with KCS as a minimum and perhaps
++ * other interfaces, so doing KCS to a default BMC LUN is valid here.
++ *
++ * Note that CONFIG_BMCPANIC should be =y (rather than =m) to
++ * ensure that this handler is loaded early enough to cover boot
++ * time panic conditions. CONFIG_BMCPANIC_ACTION can only be
++ * defined if CONFIG_BMCPANIC=y.
++ *
++ * Author: Andy Cress <arcress at users.sourceforge.net>
++ *
++ * Change History:
++ * 01/31/03 Andy Cress - created from valinux ipmi_kcs driver v2.1
++ *
++ * Copyright 2003 Intel Corp.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/semaphore.h>
++#include <linux/delay.h>
++
++#define uchar unsigned char
++
++#define KCS_READY_DELAY 5
++#define BMC_RESPONSE_DELAY 5
++#define BMC_RETRY_DELAY 60
++
++#if defined(__ia64__)
++#define KCS_BASE 0x8a2
++#else
++#define KCS_BASE 0xca2
++#endif
++#define KCS_STATUS_REG (KCS_BASE + 1)
++#define KCS_COMMAND_REG (KCS_BASE + 1)
++#define KCS_DATAIN_REG (KCS_BASE + 0)
++#define KCS_DATAOUT_REG (KCS_BASE + 0)
++
++/* State bits based on S1 & S0 below */
++#define KCS_STATE_MASK 0xC0
++#define KCS_IDLE_STATE 0x00
++#define KCS_READ_STATE 0x40
++#define KCS_WRITE_STATE 0x80
++#define KCS_ERROR_STATE 0xC0
++
++#define KCS_IBF 0x02
++#define KCS_OBF 0x01
++#define KCS_SMS_ATN 0x04
++
++#define SEND_INIT 1
++#define SEND_START 2
++#define SEND_NEXT 3
++#define SEND_END 4
++#define RECV_START 5
++#define RECV_INIT 6
++#define RECV_NEXT 7
++#define RECV_INIT2 8
++#define RECV_END 9
++#define END 10
++#define ERROR 0
++
++/* SMS Transfer Stream Control Codes */
++#define GET_STATUS_ABORT 0x60
++#define WRITE_START 0x61
++#define WRITE_END 0x62
++#define KCS_READ 0x68
++
++#define MAX_INVALID_RESPONSE_COUNT 2
++#define MIN_BMC_RESPONSE_SIZE 3
++#define MAX_IMB_PACKET_SIZE 33
++#define MAX_BMC_RESPONSE_SIZE (MIN_BMC_RESPONSE_SIZE + MAX_IMB_PACKET_SIZE)
++#define MAX_XFER_LENGTH (MAX_IMB_PACKET_SIZE * 2)
++
++#define MAX_BUFFER_SIZE 64
++
++typedef struct bmc_response
++ {
++ unsigned char lun :2;
++ unsigned char netfn :6;
++ unsigned char cmd;
++ unsigned char cc;
++ unsigned char data[1];
++ }BMC_RESPONSE;
++
++typedef struct bmc_request
++ {
++ unsigned char lun :2;
++ unsigned char netfn :6;
++ unsigned char cmd;
++ unsigned char data[1];
++ }BMC_REQUEST;
++
++/* GET_DEVICE_ID RESPONSE (11 bytes) */
++typedef struct device_id_response
++ {
++ unsigned char device_id;
++
++ unsigned char device_revision :4;
++ unsigned char reserved :3;
++ unsigned char provides_sdr :1;
++
++ unsigned char major_firmware_revision :7;
++ #define NORMAL_OPERATION 0
++ #define DEVICE_BUSY 1
++ unsigned char device_available :1;
++
++ unsigned char minor_firmware_revision;
++ unsigned char ipmi_version_major :4;
++ unsigned char ipmi_version_minor :4;
++
++ unsigned char supports_sensor_device :1;
++ unsigned char supports_sdr_device :1;
++ unsigned char supports_sel_device :1;
++ unsigned char supports_fru_device :1;
++ unsigned char supports_ipmb_receiver :1;
++ unsigned char supports_ipmb_generator :1;
++ unsigned char supports_bridge :1;
++ unsigned char supports_chassis_device :1;
++
++ unsigned char manufacturer_id1;
++ unsigned char manufacturer_id2;
++ unsigned char manufacturer_id3;
++ unsigned short product_id;
++ } DEVICE_ID_RESPONSE;
++
++/*************************************/
++
++#if defined(__ia64__)
++static char kcs_new = 1; /* don't even try old kcs */
++#else
++static char kcs_new = 0;
++#endif
++DECLARE_MUTEX(kcs_sem);
++
++/*************************************/
++
++/*
++ * kcs chip mashing stuff
++ */
++static int wait_while_ibf(void)
++{
++ unsigned char status_byte;
++
++ status_byte = inb_p(KCS_STATUS_REG);
++ if ((status_byte & KCS_IBF) == 0) return (0);
++ mdelay(KCS_READY_DELAY);
++ status_byte = inb_p(KCS_STATUS_REG);
++ if (status_byte & KCS_IBF) return (-1);
++ return (0);
++}
++
++static int is_obf_set(void)
++{
++ unsigned char cs;
++ cs = inb_p(KCS_STATUS_REG);
++ return ((cs & KCS_OBF) == KCS_OBF);
++}
++
++static int wait_until_obf(void)
++{
++ int retries = 0;
++
++ while (retries < 2) {
++ if (is_obf_set()) return (0);
++ mdelay(KCS_READY_DELAY);
++ retries++;
++ }
++ return (-ETIMEDOUT);
++}
++
++static unsigned char get_kcs_state(void)
++{
++ unsigned char cs;
++
++ cs = inb_p(KCS_STATUS_REG);
++ return (cs & KCS_STATE_MASK);
++}
++
++static unsigned char read_kcs_data(void)
++{
++ unsigned char data;
++
++ data = inb_p(KCS_DATAOUT_REG);
++ return (data);
++}
++
++static void write_kcs_data(unsigned char data)
++{
++ outb_p(data, KCS_DATAIN_REG);
++}
++
++static void write_kcs_cmd(unsigned char cmd)
++{
++ outb_p(cmd, KCS_COMMAND_REG);
++}
++
++static int clear_obf(void)
++{
++ read_kcs_data();
++ return (0);
++}
++
++static int kcs_xfer(BMC_REQUEST * request, int request_len,
++ BMC_RESPONSE * response, int *response_len)
++{
++ unsigned char *xmit_buffer, *recv_buffer;
++ int i = 0, rc = 0, state = SEND_INIT, bad = 0;
++
++ xmit_buffer = (unsigned char *) request;
++ recv_buffer = (unsigned char *) response;
++
++ while (1) {
++ if (state == END)
++ break;
++ else if (bad > 2) {
++ printk("[ipmi_panic] Maximum retries exceeded.\n");
++ rc = -EIO;
++ break;
++ }
++ switch (state) {
++ case SEND_INIT:
++ {
++ i = 0;
++ state = SEND_START;
++ wait_while_ibf();
++ if (kcs_new) clear_obf();
++ }
++ case SEND_START:
++ {
++ state = SEND_NEXT;
++ write_kcs_cmd(WRITE_START);
++ wait_while_ibf();
++ }
++ case SEND_NEXT:
++ {
++ if (i == (request_len - 1)) {
++ state = SEND_END;
++ break;
++ }
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ write_kcs_data(xmit_buffer[i++]);
++ wait_while_ibf();
++ if (kcs_new) clear_obf();
++ break;
++ }
++ case SEND_END:
++ {
++ if (!kcs_new) wait_while_ibf();
++ write_kcs_cmd(WRITE_END);
++ wait_while_ibf();
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ if (kcs_new) clear_obf();
++ write_kcs_data(xmit_buffer[i++]);
++ wait_while_ibf();
++ state = RECV_START;
++ }
++ case RECV_START:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_WRITE_STATE:
++ case KCS_IDLE_STATE:
++ {
++ mdelay(BMC_RESPONSE_DELAY);
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ i = 0;
++ memset(recv_buffer, 0,
++ *response_len);
++ state = RECV_INIT;
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_INIT:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ case KCS_WRITE_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_IDLE_STATE:
++ {
++ state = RECV_END;
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ if (is_obf_set())
++ state = RECV_NEXT;
++ else mdelay(1);
++ break;
++ }
++ default:
++ {
++ mdelay(1);
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_NEXT:
++ {
++ if (i >= *response_len) {
++ rc = -EOVERFLOW;
++ state = ERROR;
++ break;
++ }
++ recv_buffer[i++] = read_kcs_data();
++ if (!kcs_new) wait_while_ibf();
++ write_kcs_data(KCS_READ);
++ if (kcs_new) wait_while_ibf();
++ state = RECV_INIT2;
++ break;
++ }
++ case RECV_INIT2:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ case KCS_WRITE_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_IDLE_STATE:
++ {
++ if (kcs_new) {
++ if (wait_until_obf() == 0) {
++ clear_obf();
++ state = RECV_END;
++ } else {
++ state = ERROR;
++ }
++ } else {
++ state = RECV_END;
++ }
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ if (kcs_new) {
++ if (wait_until_obf() == 0)
++ state = RECV_NEXT;
++ else state = ERROR;
++ } else {
++ if (is_obf_set())
++ state = RECV_NEXT;
++ }
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_END:
++ {
++ if ((i < MIN_BMC_RESPONSE_SIZE) ||
++ (response->netfn != (request->netfn | 0x01))
++ || (response->cmd != request->cmd)) {
++ if (request->cmd == 0x01 &&
++ request->netfn == 0x06 &&
++ response->netfn == 0x2b) /*ok*/;
++ else { /* flag the error */
++ printk("[ipmi_panic] Request/Response CMD/NETFN mismatch error\n");
++
++ printk(" i=%d, RQcmd/RQnetfn=0x%x/0x%x,RScmd/RSnetfn=0x%x/0x%x\n",
++ i, request->cmd, request->netfn,
++ response->cmd, response->netfn);
++ mdelay(BMC_RETRY_DELAY);
++ bad++;
++ state = SEND_INIT;
++ break;
++ }
++ }
++
++ *response_len = i;
++ rc = 0;
++ state = END;
++ break;
++ }
++ case ERROR:
++ default:
++ {
++ printk("[ipmi_panic] BMC in bad state (%d) cmd=%02x. Retrying transfer\n", state,request->cmd);
++ mdelay(BMC_RETRY_DELAY);
++ bad++;
++ state = SEND_INIT;
++ break;
++ }
++ }
++ }
++ return (rc);
++}
++
++int ipmi_send_recv(uchar cmd, uchar netfn, uchar lun, uchar *sbuf, int slen,
++ uchar *rbuf, int rlen, int *nret, uchar *cc)
++{
++ uchar bmc_outbuf[MAX_BUFFER_SIZE];
++ uchar bmc_inbuf[MAX_BUFFER_SIZE];
++ BMC_REQUEST *bmc_req;
++ BMC_RESPONSE *bmc_resp;
++ int bmc_outlen;
++ int bmc_inlen;
++ int rc = 0;
++
++ if (kcs_new == 2) return (-ENXIO);
++
++ memset(bmc_outbuf,0, sizeof(bmc_outbuf));
++ memset(bmc_inbuf,0, sizeof(bmc_inbuf));
++ bmc_req = (BMC_REQUEST *)bmc_outbuf;
++ bmc_resp = (BMC_RESPONSE *)bmc_inbuf;
++ bmc_req->cmd = cmd;
++ bmc_req->netfn = netfn;
++ bmc_req->lun = lun;
++ bmc_outlen = slen + 2;
++ bmc_inlen = sizeof(bmc_inbuf);
++ if (slen > 0) memcpy(bmc_req->data,sbuf,slen);
++
++ rc = kcs_xfer(bmc_req, bmc_outlen, bmc_resp, &bmc_inlen);
++ if (bmc_resp->cc == 0xcc) /* flaky NMI fixup */
++ rc = kcs_xfer(bmc_req, bmc_outlen, bmc_resp, &bmc_inlen); /*retry*/
++
++ /* copy the response */
++ *cc = bmc_resp->cc;
++ if (bmc_inlen > rlen) bmc_inlen = rlen;
++ *nret = bmc_inlen;
++ if (bmc_inlen > 0) memcpy(rbuf,bmc_resp->data,bmc_inlen);
++
++ return(rc);
++}
++
++extern void init_SEL(void);
++extern void cleanup_SEL(void);
++
++int bmc_panic_init(void)
++{
++ int i, rc;
++ uchar cc;
++ uchar bdev[16];
++ DEVICE_ID_RESPONSE *dev_id;
++
++ printk("bmc_panic ipmi driver at io 0x%x\n", KCS_BASE);
++ if ((inb_p(KCS_STATUS_REG) == 0xFF) &&
++ (inb_p(KCS_DATAIN_REG) == 0xFF)) {
++ printk("--KCS ISA window not present, exiting.\n");
++ return (-ENXIO);
++ }
++
++ /* Get Device ID */
++ rc = ipmi_send_recv(0x01,0x06,0,NULL,0,bdev,sizeof(bdev),&i,&cc);
++ if (rc != 0) kcs_new = 2; /* bad */
++ else if (cc != 0) kcs_new = 2; /* bad */
++ else
++ {
++ dev_id = (DEVICE_ID_RESPONSE *)&bdev[0];
++ printk("--BMC version %x.%x, IPMI version %d.%d\n",
++ dev_id->major_firmware_revision,
++ dev_id->minor_firmware_revision,
++ dev_id->ipmi_version_major, dev_id->ipmi_version_minor);
++ if ((dev_id->ipmi_version_major == 0) &&
++ (dev_id->ipmi_version_minor == 9)) {
++ printk("--Using legacy KCS state machine\n");
++ kcs_new = 0;
++ } else {
++ printk("--Using new KCS state machine\n");
++ kcs_new = 1;
++ }
++ }
++ init_SEL();
++
++ return(rc);
++}
++
++#ifdef MODULE
++int init_module(void)
++{
++ return (bmc_panic_init());
++}
++
++void cleanup_module(void)
++{
++ printk("bmc_panic: Driver shutting down.\n");
++ cleanup_SEL();
++}
++#endif
++
++/* end bmc_ipmi.c */
+--- /dev/null Fri Mar 23 23:37:44 2001
++++ linux-2.4.18/drivers/char/bmc_selmsg.c Thu Feb 27 14:28:39 2003
+@@ -0,0 +1,269 @@
++/*
++ * bmc_selmsg.c
++ * routines to send IMB and BMC requests to the SEL and alarms panel.
++ *
++ * 05/07/01 Todd Davis - created
++ * 09/17/01 Andy Cress - some cleanup
++ * 09/26/01 Andy Cress - added setAlarmLED, changed notifier priority
++ * 10/05/01 Andy Cress - fixed setAlarmLED, changed OEM bytes in panic
++ * 10/08/01 Andy Cress - added getAlarmLED
++ * 10/09/01 Andy Cress - save 3 chars of panic_string in SEL
++ * 10/25/01 Andy Cress - fixed confusion w DEBUG macro & LINUX_DEBUG
++ * 11/05/01 Andy Cress - adapted to open source driver calls
++ * 11/14/01 Andy Cress - code complete, see also bmc_ipmi.c
++ * 01/15/02 Andy Cress - changed to show BMC_PANIC tags
++ * 03/22/02 Andy Cress - changed printk messages
++ * 04/16/02 Andy Cress - added bmcpanic_action() routine
++ * 06/04/02 Andy Cress - added bmc_poweroff() routine
++ * 02/26/02 Andy Cress - major rework to use ipmi_send_recv, trim bloat
++ */
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/notifier.h> /* Routines to manage notifier chains for passing
++ * status changes to any interested routines. */
++
++///////////////////////////////////////////////////////////
++// Global definitions
++//////////////////////////////////////////////////////////
++#define uchar unsigned char
++#define ulong unsigned long
++
++#define BMC_SA 0x20 // BMC slave address
++#define NETFN_CHAS 0x00
++#define NETFN_SENS_EVENT 0x04
++#define NETFN_APP 0x06
++#define NETFN_STORAGE 0x0A
++
++#define CHASSIS_CTL 0x02
++#define GET_SEL_INFO 0x40
++#define PLATFORM_EVENT 0x02
++#define KERNEL_SENSOR_ID 0x21
++
++/* Defines for the Alarms Panel */
++#define MASTER_WRITE_READ 0x52 // Command from IPMI 1.5 Table 38-8
++#define ALARMS_PANEL_WRITE 0x40 // I2C Address 0x40 write to front panel
++#define ALARMS_PANEL_READ 0x41 // I2C Address 0x41 read from front panel
++#define PRIVATE_BUS_ID 0x03 // TAM 8574 lives on 2ndary private bus
++
++// See Table 36-3 for sensor types - 20h for OS critical stop
++// See Table 36-1 for event types - 6Fh Sensor Specific
++// discrete sensor class
++// See Table 23-6/36-3 for event data
++// data1 - 00b 00b 0001b (runtime) 0000b (initialization stop)
++// data2 - ffh (unspecified)
++// data3 - ffh (unspecified)
++
++///////////////////////////////////////////////////////////
++// Global variables
++//////////////////////////////////////////////////////////
++static int fIPMIok = 1; /* Are IPMI commands supported? */
++static int has_paniced;
++
++extern struct notifier_block *panic_notifier_list;
++extern char *panic_string;
++extern char *die_str;
++extern long die_err;
++
++extern void machine_restart(char *cmd); /*from include/linux/reboot.h*/
++extern int ipmi_panic_init(void);
++extern int ipmi_send_recv(uchar cmd, uchar netfn, uchar lun,
++ uchar *sbuf, int slen, uchar *rbuf, int rlen,
++ int *nret, uchar *cc);
++
++///////////////////////////////////////////////////////////
++// Subroutines
++//////////////////////////////////////////////////////////
++
++static int ReadSELinfo(void)
++{
++ unsigned char cc;
++ unsigned char obuf[16];
++ unsigned char ibuf[16];
++ int rc, i;
++
++ rc = ipmi_send_recv(GET_SEL_INFO,NETFN_STORAGE,0,obuf,0,
++ ibuf,sizeof(ibuf),&i,&cc);
++ if (rc == 0 && cc != 0) rc = cc;
++ if (rc == 0)
++ printk("bmc_panic: Code %d SEL Ver %d Support %d\n",
++ ibuf[0],ibuf[1],ibuf[14]);
++ return(rc);
++} /* end ReadSELinfo()*/
++
++static unsigned char getAlarmLED(void)
++{
++ unsigned char cc;
++ unsigned char obuf[16];
++ unsigned char ibuf[16];
++ int olen, rc, i;
++ unsigned char alarms;
++
++ /* Get Alarm LED values */
++ obuf[0] = PRIVATE_BUS_ID; // 0x03;
++ obuf[1] = ALARMS_PANEL_READ; // 0x41;
++ obuf[2] = 1; // one byte of alarms data
++ obuf[3] = 0; // initial alarms value
++ olen = 3;
++ rc = ipmi_send_recv(MASTER_WRITE_READ,NETFN_APP,0,
++ obuf,olen,ibuf,4,&i,&cc);
++ alarms = ibuf[0];
++ printk("ipmi_panic: get alarms rc=%d cc=%x, alarms=%02x\n",
++ rc,cc,alarms);
++ return(alarms);
++} /*end getAlarmLED*/
++
++static int setAlarmLED(unsigned char alarms)
++{
++ unsigned char cc;
++ unsigned char obuf[16];
++ unsigned char ibuf[16];
++ int olen, rc, i;
++
++ obuf[0] = PRIVATE_BUS_ID; // 0x03;
++ obuf[1] = ALARMS_PANEL_WRITE; // 0x40;
++ obuf[2] = 1; // one byte of alarms data
++ obuf[3] = (alarms & 0x0D) | 0xF0; // turn on critical alarm
++ olen = 4;
++ rc = ipmi_send_recv(MASTER_WRITE_READ,NETFN_APP,0,
++ obuf,olen,ibuf,0,&i,&cc);
++ printk("ipmi_panic: set crit alarm rc=%d cc=%x\n",rc,cc);
++ if (rc == 0 && cc != 0) rc = cc;
++ return(rc);
++} /*end setAlarmLED*/
++
++static int insertPanicRecord(ulong event)
++{
++ unsigned char cc;
++ unsigned char obuf[16];
++ unsigned char ibuf[16];
++ int olen, rc, i;
++
++ /* Log the OS Critical Stop to the SEL (BMC firmware log). */
++ obuf[0] = 0x21; /* Kernel generator ID, IPMI table 5-4 */
++ obuf[1] = 0x03; /* 3=IPMI10, 4=IPMI15, set as back-compatible w 1.0 */
++ obuf[2] = 0x20; /* OS Critical Stop, IPMI table 36-3 */
++ obuf[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
++ obuf[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
++ /*
++ * Most panics only have event codes == 0, so use panic_string.
++ * Start of panic string usu indicates module name.
++ */
++ obuf[3] = panic_string[0];
++ obuf[6] = panic_string[1];
++ obuf[7] = panic_string[2];
++ /*
++ * Add some bits to decode panic type
++ * String above is ASCII, so it will be betw 0x20 and 0x7f.
++ */
++ if (die_str != NULL && strncmp(die_str,"Oops",4) == 0)
++ obuf[3] |= 0x80; /* Is an Oops */
++ if (event == 1) obuf[6] |= 0x80; /* In interrupt handler */
++ if (die_err & 0x01) obuf[7] |= 0x80; /* Null ptr dereference */
++ olen = 8;
++ rc = ipmi_send_recv(PLATFORM_EVENT,NETFN_SENS_EVENT,0,
++ obuf,olen,ibuf,0,&i,&cc);
++ printk("bmc_panic: log OS Critical Stop rc=%d cc=%x, %c%c%c\n",
++ rc,cc, obuf[3],obuf[6],obuf[7]);
++ if (rc == 0 && cc != 0) rc = cc;
++ return(rc);
++} /*end insertPanicRecord()*/
++
++
++static int panic_event(struct notifier_block *this, unsigned long event,
++ void *ptr)
++{
++ unsigned char alarm;
++
++ if (has_paniced) return NOTIFY_DONE;
++ has_paniced = 1;
++
++#ifdef LINUX_DEBUG
++ SELprintf("panic_string(%p): %s\n",panic_string,panic_string);
++#endif
++
++ if (fIPMIok) {
++ insertPanicRecord(event);
++ alarm = getAlarmLED();
++ if (alarm != 0) // valid, ok to setAlarmLED
++ setAlarmLED(alarm);
++ }
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block panic_block = {
++ panic_event,
++ NULL,
++ 200 /* priority: INT_MAX >= x >= 0 */
++};
++
++/* Initialize the module - Try SEL routines */
++void init_SEL(void)
++{
++#ifdef LINUX_DEBUG
++ printk (KERN_INFO "init_SEL: Reading SEL info\n");
++#endif
++ if (ReadSELinfo() != 0) {
++ /* Nothing to do if the system can't do SEL functions. */
++ fIPMIok = 0;
++ printk(KERN_ERR "bmc_panic: IPMI failure. unregister device\n");
++ }
++ else {
++ fIPMIok = 1;
++ printk (KERN_INFO "Registering bmc_panic with panic notifier\n");
++ notifier_chain_register(&panic_notifier_list, &panic_block);
++ }
++ return ;
++}
++
++
++/* Cleanup - unregister the appropriate file from /proc */
++void cleanup_SEL(void)
++{
++ printk ( KERN_INFO "Unregistering with panic notifier\n");
++ notifier_chain_unregister(&panic_notifier_list, &panic_block);
++}
++
++#ifdef CONFIG_BMCPANIC_ACTION
++#define BMCPANIC_ACTION CONFIG_BMCPANIC_ACTION
++#else
++#define BMCPANIC_ACTION 0
++#endif
++void bmcpanic_action(void)
++{
++ int ret, i;
++ unsigned char obuf, cc;
++
++ if (fIPMIok) ret = BMCPANIC_ACTION;
++ else ret = 0; /* do machine_reset */
++ switch(ret)
++ {
++ case 1: /* power down */
++ obuf = 0;
++ ret = ipmi_send_recv(CHASSIS_CTL,NETFN_CHAS,0,&obuf,1,NULL,0,&i,&cc);
++ break;
++ case 2: /* power cycle */
++ obuf = 2;
++ ret = ipmi_send_recv(CHASSIS_CTL,NETFN_CHAS,0,&obuf,1,NULL,0,&i,&cc);
++ break;
++ case 3: /* hard reset */
++ obuf = 3; /* IPMI hard reset */
++ ret = ipmi_send_recv(CHASSIS_CTL,NETFN_CHAS,0,&obuf,1,NULL,0,&i,&cc);
++ break;
++ case 0: /* soft reset */
++ default:
++ machine_restart(NULL); /* normal Linux reset (arch/i386/) */
++ }
++}
++
++void bmc_poweroff(void)
++{
++ int ret, i;
++ unsigned char obuf, cc;
++
++ if (fIPMIok) {
++ obuf = 0;
++ ret = ipmi_send_recv(CHASSIS_CTL,NETFN_CHAS,0,&obuf,1,NULL,0,&i,&cc);
++ }
++}
++
++/* end bmc_selmsg.c */
+--- linux-2.4.18-orig/arch/i386/kernel/process.c Mon Feb 25 14:37:53 2002
++++ linux-2.4.18/arch/i386/kernel/process.c Thu Feb 27 14:28:39 2003
+@@ -426,10 +426,19 @@
+ {
+ }
+
++#ifdef CONFIG_BMCPANIC
++extern void bmc_poweroff(void);
++#endif
++
+ void machine_power_off(void)
+ {
+ if (pm_power_off)
+ pm_power_off();
++
++#ifdef CONFIG_BMCPANIC
++ bmc_poweroff();
++#endif
++
+ }
+
+ extern void show_trace(unsigned long* esp);
+--- linux-2.4.18-orig/arch/i386/kernel/traps.c Sun Sep 30 15:26:08 2001
++++ linux-2.4.18/arch/i386/kernel/traps.c Thu Feb 27 14:28:39 2003
+@@ -238,6 +238,8 @@
+ }
+
+ spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
++char die_str[64] = "";
++long die_err = 0;
+
+ void die(const char * str, struct pt_regs * regs, long err)
+ {
+@@ -245,6 +247,8 @@
+ spin_lock_irq(&die_lock);
+ bust_spinlocks(1);
+ printk("%s: %04lx\n", str, err & 0xffff);
++ die_err = err;
++ strncpy(die_str,str,sizeof(die_str)-1);
+ show_registers(regs);
+ bust_spinlocks(0);
+ spin_unlock_irq(&die_lock);
+--- linux-2.4.18-orig/arch/i386/kernel/i386_ksyms.c Mon Feb 25 14:37:53 2002
++++ linux-2.4.18/arch/i386/kernel/i386_ksyms.c Thu Feb 27 14:28:39 2003
+@@ -31,6 +31,8 @@
+
+ extern void dump_thread(struct pt_regs *, struct user *);
+ extern spinlock_t rtc_lock;
++extern char *die_str;
++extern long die_err;
+
+ #if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+ extern void machine_real_restart(unsigned char *, int);
+@@ -140,6 +142,9 @@
+ EXPORT_SYMBOL(__global_save_flags);
+ EXPORT_SYMBOL(__global_restore_flags);
+ EXPORT_SYMBOL(smp_call_function);
++
++EXPORT_SYMBOL(die_str);
++EXPORT_SYMBOL(die_err);
+
+ /* TLB flushing */
+ EXPORT_SYMBOL(flush_tlb_page);
diff --git a/kern/bmcpanic-2.4.19.patch b/kern/bmcpanic-2.4.19.patch
new file mode 100644
index 0000000..ab1d5dd
--- /dev/null
+++ b/kern/bmcpanic-2.4.19.patch
@@ -0,0 +1,997 @@
+--- linux-2.4.19-orig/drivers/char/misc.c Fri Aug 2 20:39:43 2002
++++ linux-2.4.19/drivers/char/misc.c Thu Feb 27 15:07:25 2003
+@@ -70,6 +70,7 @@
+ extern void gfx_register(void);
+ #endif
+ extern void streamable_init(void);
++extern int bmc_panic_init(void);
+ extern int rtc_DP8570A_init(void);
+ extern int rtc_MK48T08_init(void);
+ extern int ds1286_init(void);
+@@ -266,6 +267,9 @@
+ #endif
+ #ifdef CONFIG_PMAC_PBOOK
+ pmu_device_init();
++#endif
++#ifdef CONFIG_BMCPANIC
++ bmc_panic_init();
+ #endif
+ #ifdef CONFIG_SGI_NEWPORT_GFX
+ gfx_register ();
+--- linux-2.4.19-orig/kernel/panic.c Fri Aug 2 20:39:46 2002
++++ linux-2.4.19/kernel/panic.c Thu Feb 27 15:07:25 2003
+@@ -17,6 +17,10 @@
+ #include <linux/sysrq.h>
+ #include <linux/interrupt.h>
+
++char *panic_string;
++#ifdef CONFIG_BMCPANIC
++ extern void bmcpanic_action(void);
++#endif
+ asmlinkage void sys_sync(void); /* it's really int */
+
+ int panic_timeout;
+@@ -53,6 +57,7 @@
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
++ panic_string = buf;
+ printk(KERN_EMERG "Kernel panic: %s\n",buf);
+ if (in_interrupt())
+ printk(KERN_EMERG "In interrupt handler - not syncing\n");
+@@ -81,7 +86,11 @@
+ * choosing not too. It might crash, be corrupt or do
+ * more harm than good for other reasons.
+ */
+- machine_restart(NULL);
++#ifdef CONFIG_BMCPANIC
++ bmcpanic_action();
++#else
++ machine_restart(NULL);
++#endif
+ }
+ #ifdef __sparc__
+ {
+--- linux-2.4.19-orig/kernel/ksyms.c Fri Aug 2 20:39:46 2002
++++ linux-2.4.19/kernel/ksyms.c Thu Feb 27 15:07:25 2003
+@@ -60,6 +60,7 @@
+
+ extern void *sys_call_table;
+
++extern char *panic_string;
+ extern struct timezone sys_tz;
+ extern int request_dma(unsigned int dmanr, char * deviceID);
+ extern void free_dma(unsigned int dmanr);
+@@ -570,3 +571,5 @@
+
+ EXPORT_SYMBOL(tasklist_lock);
+ EXPORT_SYMBOL(pidhash);
++EXPORT_SYMBOL(panic_notifier_list);
++EXPORT_SYMBOL(panic_string);
+--- linux-2.4.19-orig/Documentation/Configure.help Fri Aug 2 20:39:42 2002
++++ linux-2.4.19/Documentation/Configure.help Thu Feb 27 15:07:25 2003
+@@ -16640,6 +16640,20 @@
+
+ If unsure, say N.
+
++BMC Panic Handler
++CONFIG_BMCPANIC
++ If you say Y here, additional functions will be added to the
++ panic handler via the panic notifier list.
++
++ If your system has IPMI support and a BMC (Baseboard Management
++ Controller) on the motherboard, then the following additional
++ functions will be performed if a panic occurs:
++ - Write an OS Critical Stop message to the firmware System Event Log
++ - Turn on the Critical LED on the Telco Alarms panel (if present)
++ - Send a BMC LAN alert via SNMP to a network operations center,
++ if the firmware Platform Event Filter configuration is set to
++ enable this.
++
+ Cobalt Networks support
+ CONFIG_COBALT
+ Support for Cobalt Networks x86-based servers.
+--- linux-2.4.19-orig/drivers/char/Makefile Fri Aug 2 20:39:43 2002
++++ linux-2.4.19/drivers/char/Makefile Thu Feb 27 15:07:25 2003
+@@ -230,6 +230,9 @@
+ obj-y += ftape/ftape.o
+ endif
+
++bmc_panic-objs := bmc_ipmi.o bmc_selmsg.o
++obj-$(CONFIG_BMCPANIC) += bmc_panic.o
++
+ obj-$(CONFIG_H8) += h8.o
+ obj-$(CONFIG_PPDEV) += ppdev.o
+ obj-$(CONFIG_DZ) += dz.o
+@@ -279,6 +282,9 @@
+ ./conmakehash $(FONTMAPFILE) > consolemap_deftbl.c
+
+ consolemap_deftbl.o: consolemap_deftbl.c $(TOPDIR)/include/linux/types.h
++
++bmc_panic.o: $(bmc_panic-objs)
++ $(LD) -r -o $@ $(bmc_panic-objs)
+
+ .DELETE_ON_ERROR:
+
+--- linux-2.4.19-orig/drivers/char/Config.in Fri Aug 2 20:39:43 2002
++++ linux-2.4.19/drivers/char/Config.in Thu Feb 27 15:07:25 2003
+@@ -127,6 +127,10 @@
+ if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
+ int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
+ fi
++bool 'BMC Panic Handler' CONFIG_BMCPANIC
++if [ "$CONFIG_BMCPANIC" != "n" ]; then
++ int ' Action after Panic (0=reset,1=power down,2=power cycle)' CONFIG_BMCPANIC_ACTION 0
++fi
+ if [ "$CONFIG_PARPORT" != "n" ]; then
+ dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
+ if [ "$CONFIG_PRINTER" != "n" ]; then
+--- /dev/null Fri Mar 23 23:37:44 2001
++++ linux-2.4.19/drivers/char/bmc_ipmi.c Thu Feb 27 15:07:25 2003
+@@ -0,0 +1,531 @@
++/*
++ * bmc_ipmi.c
++ *
++ * This code is needed to run a streamlined IPMI KCS command when
++ * the rest of the system may be dead (panic time). It must wait
++ * for completion of the receive function also.
++ * There will be zero or one BMC, with KCS as a minimum and perhaps
++ * other interfaces, so doing KCS to a default BMC LUN is valid here.
++ *
++ * Note that CONFIG_BMCPANIC should be =y (rather than =m) to
++ * ensure that this handler is loaded early enough to cover boot
++ * time panic conditions. CONFIG_BMCPANIC_ACTION can only be
++ * defined if CONFIG_BMCPANIC=y.
++ *
++ * Author: Andy Cress <arcress at users.sourceforge.net>
++ *
++ * Change History:
++ * 01/31/03 Andy Cress - created from valinux ipmi_kcs driver v2.1
++ *
++ * Copyright 2003 Intel Corp.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/semaphore.h>
++#include <linux/delay.h>
++
++#define uchar unsigned char
++
++#define KCS_READY_DELAY 5
++#define BMC_RESPONSE_DELAY 5
++#define BMC_RETRY_DELAY 60
++
++#if defined(__ia64__)
++#define KCS_BASE 0x8a2
++#else
++#define KCS_BASE 0xca2
++#endif
++#define KCS_STATUS_REG (KCS_BASE + 1)
++#define KCS_COMMAND_REG (KCS_BASE + 1)
++#define KCS_DATAIN_REG (KCS_BASE + 0)
++#define KCS_DATAOUT_REG (KCS_BASE + 0)
++
++/* State bits based on S1 & S0 below */
++#define KCS_STATE_MASK 0xC0
++#define KCS_IDLE_STATE 0x00
++#define KCS_READ_STATE 0x40
++#define KCS_WRITE_STATE 0x80
++#define KCS_ERROR_STATE 0xC0
++
++#define KCS_IBF 0x02
++#define KCS_OBF 0x01
++#define KCS_SMS_ATN 0x04
++
++#define SEND_INIT 1
++#define SEND_START 2
++#define SEND_NEXT 3
++#define SEND_END 4
++#define RECV_START 5
++#define RECV_INIT 6
++#define RECV_NEXT 7
++#define RECV_INIT2 8
++#define RECV_END 9
++#define END 10
++#define ERROR 0
++
++/* SMS Transfer Stream Control Codes */
++#define GET_STATUS_ABORT 0x60
++#define WRITE_START 0x61
++#define WRITE_END 0x62
++#define KCS_READ 0x68
++
++#define MAX_INVALID_RESPONSE_COUNT 2
++#define MIN_BMC_RESPONSE_SIZE 3
++#define MAX_IMB_PACKET_SIZE 33
++#define MAX_BMC_RESPONSE_SIZE (MIN_BMC_RESPONSE_SIZE + MAX_IMB_PACKET_SIZE)
++#define MAX_XFER_LENGTH (MAX_IMB_PACKET_SIZE * 2)
++
++#define MAX_BUFFER_SIZE 64
++
++typedef struct bmc_response
++ {
++ unsigned char lun :2;
++ unsigned char netfn :6;
++ unsigned char cmd;
++ unsigned char cc;
++ unsigned char data[1];
++ }BMC_RESPONSE;
++
++typedef struct bmc_request
++ {
++ unsigned char lun :2;
++ unsigned char netfn :6;
++ unsigned char cmd;
++ unsigned char data[1];
++ }BMC_REQUEST;
++
++/* GET_DEVICE_ID RESPONSE (11 bytes) */
++typedef struct device_id_response
++ {
++ unsigned char device_id;
++
++ unsigned char device_revision :4;
++ unsigned char reserved :3;
++ unsigned char provides_sdr :1;
++
++ unsigned char major_firmware_revision :7;
++ #define NORMAL_OPERATION 0
++ #define DEVICE_BUSY 1
++ unsigned char device_available :1;
++
++ unsigned char minor_firmware_revision;
++ unsigned char ipmi_version_major :4;
++ unsigned char ipmi_version_minor :4;
++
++ unsigned char supports_sensor_device :1;
++ unsigned char supports_sdr_device :1;
++ unsigned char supports_sel_device :1;
++ unsigned char supports_fru_device :1;
++ unsigned char supports_ipmb_receiver :1;
++ unsigned char supports_ipmb_generator :1;
++ unsigned char supports_bridge :1;
++ unsigned char supports_chassis_device :1;
++
++ unsigned char manufacturer_id1;
++ unsigned char manufacturer_id2;
++ unsigned char manufacturer_id3;
++ unsigned short product_id;
++ } DEVICE_ID_RESPONSE;
++
++/*************************************/
++
++#if defined(__ia64__)
++static char kcs_new = 1; /* don't even try old kcs */
++#else
++static char kcs_new = 0;
++#endif
++DECLARE_MUTEX(kcs_sem);
++
++/*************************************/
++
++/*
++ * kcs chip mashing stuff
++ */
++static int wait_while_ibf(void)
++{
++ unsigned char status_byte;
++
++ status_byte = inb_p(KCS_STATUS_REG);
++ if ((status_byte & KCS_IBF) == 0) return (0);
++ mdelay(KCS_READY_DELAY);
++ status_byte = inb_p(KCS_STATUS_REG);
++ if (status_byte & KCS_IBF) return (-1);
++ return (0);
++}
++
++static int is_obf_set(void)
++{
++ unsigned char cs;
++ cs = inb_p(KCS_STATUS_REG);
++ return ((cs & KCS_OBF) == KCS_OBF);
++}
++
++static int wait_until_obf(void)
++{
++ int retries = 0;
++
++ while (retries < 2) {
++ if (is_obf_set()) return (0);
++ mdelay(KCS_READY_DELAY);
++ retries++;
++ }
++ return (-ETIMEDOUT);
++}
++
++static unsigned char get_kcs_state(void)
++{
++ unsigned char cs;
++
++ cs = inb_p(KCS_STATUS_REG);
++ return (cs & KCS_STATE_MASK);
++}
++
++static unsigned char read_kcs_data(void)
++{
++ unsigned char data;
++
++ data = inb_p(KCS_DATAOUT_REG);
++ return (data);
++}
++
++static void write_kcs_data(unsigned char data)
++{
++ outb_p(data, KCS_DATAIN_REG);
++}
++
++static void write_kcs_cmd(unsigned char cmd)
++{
++ outb_p(cmd, KCS_COMMAND_REG);
++}
++
++static int clear_obf(void)
++{
++ read_kcs_data();
++ return (0);
++}
++
++static int kcs_xfer(BMC_REQUEST * request, int request_len,
++ BMC_RESPONSE * response, int *response_len)
++{
++ unsigned char *xmit_buffer, *recv_buffer;
++ int i = 0, rc = 0, state = SEND_INIT, bad = 0;
++
++ xmit_buffer = (unsigned char *) request;
++ recv_buffer = (unsigned char *) response;
++
++ while (1) {
++ if (state == END)
++ break;
++ else if (bad > 2) {
++ printk("[ipmi_panic] Maximum retries exceeded.\n");
++ rc = -EIO;
++ break;
++ }
++ switch (state) {
++ case SEND_INIT:
++ {
++ i = 0;
++ state = SEND_START;
++ wait_while_ibf();
++ if (kcs_new) clear_obf();
++ }
++ case SEND_START:
++ {
++ state = SEND_NEXT;
++ write_kcs_cmd(WRITE_START);
++ wait_while_ibf();
++ }
++ case SEND_NEXT:
++ {
++ if (i == (request_len - 1)) {
++ state = SEND_END;
++ break;
++ }
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ write_kcs_data(xmit_buffer[i++]);
++ wait_while_ibf();
++ if (kcs_new) clear_obf();
++ break;
++ }
++ case SEND_END:
++ {
++ if (!kcs_new) wait_while_ibf();
++ write_kcs_cmd(WRITE_END);
++ wait_while_ibf();
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ if (kcs_new) clear_obf();
++ write_kcs_data(xmit_buffer[i++]);
++ wait_while_ibf();
++ state = RECV_START;
++ }
++ case RECV_START:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_WRITE_STATE:
++ case KCS_IDLE_STATE:
++ {
++ mdelay(BMC_RESPONSE_DELAY);
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ i = 0;
++ memset(recv_buffer, 0,
++ *response_len);
++ state = RECV_INIT;
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_INIT:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ case KCS_WRITE_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_IDLE_STATE:
++ {
++ state = RECV_END;
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ if (is_obf_set())
++ state = RECV_NEXT;
++ else mdelay(1);
++ break;
++ }
++ default:
++ {
++ mdelay(1);
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_NEXT:
++ {
++ if (i >= *response_len) {
++ rc = -EOVERFLOW;
++ state = ERROR;
++ break;
++ }
++ recv_buffer[i++] = read_kcs_data();
++ if (!kcs_new) wait_while_ibf();
++ write_kcs_data(KCS_READ);
++ if (kcs_new) wait_while_ibf();
++ state = RECV_INIT2;
++ break;
++ }
++ case RECV_INIT2:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ case KCS_WRITE_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_IDLE_STATE:
++ {
++ if (kcs_new) {
++ if (wait_until_obf() == 0) {
++ clear_obf();
++ state = RECV_END;
++ } else {
++ state = ERROR;
++ }
++ } else {
++ state = RECV_END;
++ }
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ if (kcs_new) {
++ if (wait_until_obf() == 0)
++ state = RECV_NEXT;
++ else state = ERROR;
++ } else {
++ if (is_obf_set())
++ state = RECV_NEXT;
++ }
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_END:
++ {
++ if ((i < MIN_BMC_RESPONSE_SIZE) ||
++ (response->netfn != (request->netfn | 0x01))
++ || (response->cmd != request->cmd)) {
++ if (request->cmd == 0x01 &&
++ request->netfn == 0x06 &&
++ response->netfn == 0x2b) /*ok*/;
++ else { /* flag the error */
++ printk("[ipmi_panic] Request/Response CMD/NETFN mismatch error\n");
++
++ printk(" i=%d, RQcmd/RQnetfn=0x%x/0x%x,RScmd/RSnetfn=0x%x/0x%x\n",
++ i, request->cmd, request->netfn,
++ response->cmd, response->netfn);
++ mdelay(BMC_RETRY_DELAY);
++ bad++;
++ state = SEND_INIT;
++ break;
++ }
++ }
++
++ *response_len = i;
++ rc = 0;
++ state = END;
++ break;
++ }
++ case ERROR:
++ default:
++ {
++ printk("[ipmi_panic] BMC in bad state (%d) cmd=%02x. Retrying transfer\n", state,request->cmd);
++ mdelay(BMC_RETRY_DELAY);
++ bad++;
++ state = SEND_INIT;
++ break;
++ }
++ }
++ }
++ return (rc);
++}
++
++int ipmi_send_recv(uchar cmd, uchar netfn, uchar lun, uchar *sbuf, int slen,
++ uchar *rbuf, int rlen, int *nret, uchar *cc)
++{
++ uchar bmc_outbuf[MAX_BUFFER_SIZE];
++ uchar bmc_inbuf[MAX_BUFFER_SIZE];
++ BMC_REQUEST *bmc_req;
++ BMC_RESPONSE *bmc_resp;
++ int bmc_outlen;
++ int bmc_inlen;
++ int rc = 0;
++
++ if (kcs_new == 2) return (-ENXIO);
++
++ memset(bmc_outbuf,0, sizeof(bmc_outbuf));
++ memset(bmc_inbuf,0, sizeof(bmc_inbuf));
++ bmc_req = (BMC_REQUEST *)bmc_outbuf;
++ bmc_resp = (BMC_RESPONSE *)bmc_inbuf;
++ bmc_req->cmd = cmd;
++ bmc_req->netfn = netfn;
++ bmc_req->lun = lun;
++ bmc_outlen = slen + 2;
++ bmc_inlen = sizeof(bmc_inbuf);
++ if (slen > 0) memcpy(bmc_req->data,sbuf,slen);
++
++ rc = kcs_xfer(bmc_req, bmc_outlen, bmc_resp, &bmc_inlen);
++ if (bmc_resp->cc == 0xcc) /* flaky NMI fixup */
++ rc = kcs_xfer(bmc_req, bmc_outlen, bmc_resp, &bmc_inlen); /*retry*/
++
++ /* copy the response */
++ *cc = bmc_resp->cc;
++ if (bmc_inlen > rlen) bmc_inlen = rlen;
++ *nret = bmc_inlen;
++ if (bmc_inlen > 0) memcpy(rbuf,bmc_resp->data,bmc_inlen);
++
++ return(rc);
++}
++
++extern void init_SEL(void);
++extern void cleanup_SEL(void);
++
++int bmc_panic_init(void)
++{
++ int i, rc;
++ uchar cc;
++ uchar bdev[16];
++ DEVICE_ID_RESPONSE *dev_id;
++
++ printk("bmc_panic ipmi driver at io 0x%x\n", KCS_BASE);
++ if ((inb_p(KCS_STATUS_REG) == 0xFF) &&
++ (inb_p(KCS_DATAIN_REG) == 0xFF)) {
++ printk("--KCS ISA window not present, exiting.\n");
++ return (-ENXIO);
++ }
++
++ /* Get Device ID */
++ rc = ipmi_send_recv(0x01,0x06,0,NULL,0,bdev,sizeof(bdev),&i,&cc);
++ if (rc != 0) kcs_new = 2; /* bad */
++ else if (cc != 0) kcs_new = 2; /* bad */
++ else
++ {
++ dev_id = (DEVICE_ID_RESPONSE *)&bdev[0];
++ printk("--BMC version %x.%x, IPMI version %d.%d\n",
++ dev_id->major_firmware_revision,
++ dev_id->minor_firmware_revision,
++ dev_id->ipmi_version_major, dev_id->ipmi_version_minor);
++ if ((dev_id->ipmi_version_major == 0) &&
++ (dev_id->ipmi_version_minor == 9)) {
++ printk("--Using legacy KCS state machine\n");
++ kcs_new = 0;
++ } else {
++ printk("--Using new KCS state machine\n");
++ kcs_new = 1;
++ }
++ }
++ init_SEL();
++
++ return(rc);
++}
++
++#ifdef MODULE
++int init_module(void)
++{
++ return (bmc_panic_init());
++}
++
++void cleanup_module(void)
++{
++ printk("bmc_panic: Driver shutting down.\n");
++ cleanup_SEL();
++}
++#endif
++
++/* end bmc_ipmi.c */
+--- /dev/null Fri Mar 23 23:37:44 2001
++++ linux-2.4.19/drivers/char/bmc_selmsg.c Thu Feb 27 15:07:25 2003
+@@ -0,0 +1,269 @@
++/*
++ * bmc_selmsg.c
++ * routines to send IMB and BMC requests to the SEL and alarms panel.
++ *
++ * 05/07/01 Todd Davis - created
++ * 09/17/01 Andy Cress - some cleanup
++ * 09/26/01 Andy Cress - added setAlarmLED, changed notifier priority
++ * 10/05/01 Andy Cress - fixed setAlarmLED, changed OEM bytes in panic
++ * 10/08/01 Andy Cress - added getAlarmLED
++ * 10/09/01 Andy Cress - save 3 chars of panic_string in SEL
++ * 10/25/01 Andy Cress - fixed confusion w DEBUG macro & LINUX_DEBUG
++ * 11/05/01 Andy Cress - adapted to open source driver calls
++ * 11/14/01 Andy Cress - code complete, see also bmc_ipmi.c
++ * 01/15/02 Andy Cress - changed to show BMC_PANIC tags
++ * 03/22/02 Andy Cress - changed printk messages
++ * 04/16/02 Andy Cress - added bmcpanic_action() routine
++ * 06/04/02 Andy Cress - added bmc_poweroff() routine
++ * 02/26/02 Andy Cress - major rework to use ipmi_send_recv, trim bloat
++ */
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/notifier.h> /* Routines to manage notifier chains for passing
++ * status changes to any interested routines. */
++
++///////////////////////////////////////////////////////////
++// Global definitions
++//////////////////////////////////////////////////////////
++#define uchar unsigned char
++#define ulong unsigned long
++
++#define BMC_SA 0x20 // BMC slave address
++#define NETFN_CHAS 0x00
++#define NETFN_SENS_EVENT 0x04
++#define NETFN_APP 0x06
++#define NETFN_STORAGE 0x0A
++
++#define CHASSIS_CTL 0x02
++#define GET_SEL_INFO 0x40
++#define PLATFORM_EVENT 0x02
++#define KERNEL_SENSOR_ID 0x21
++
++/* Defines for the Alarms Panel */
++#define MASTER_WRITE_READ 0x52 // Command from IPMI 1.5 Table 38-8
++#define ALARMS_PANEL_WRITE 0x40 // I2C Address 0x40 write to front panel
++#define ALARMS_PANEL_READ 0x41 // I2C Address 0x41 read from front panel
++#define PRIVATE_BUS_ID 0x03 // TAM 8574 lives on 2ndary private bus
++
++// See Table 36-3 for sensor types - 20h for OS critical stop
++// See Table 36-1 for event types - 6Fh Sensor Specific
++// discrete sensor class
++// See Table 23-6/36-3 for event data
++// data1 - 00b 00b 0001b (runtime) 0000b (initialization stop)
++// data2 - ffh (unspecified)
++// data3 - ffh (unspecified)
++
++///////////////////////////////////////////////////////////
++// Global variables
++//////////////////////////////////////////////////////////
++static int fIPMIok = 1; /* Are IPMI commands supported? */
++static int has_paniced;
++
++extern struct notifier_block *panic_notifier_list;
++extern char *panic_string;
++extern char *die_str;
++extern long die_err;
++
++extern void machine_restart(char *cmd); /*from include/linux/reboot.h*/
++extern int ipmi_panic_init(void);
++extern int ipmi_send_recv(uchar cmd, uchar netfn, uchar lun,
++ uchar *sbuf, int slen, uchar *rbuf, int rlen,
++ int *nret, uchar *cc);
++
++///////////////////////////////////////////////////////////
++// Subroutines
++//////////////////////////////////////////////////////////
++
++static int ReadSELinfo(void)
++{
++ unsigned char cc;
++ unsigned char obuf[16];
++ unsigned char ibuf[16];
++ int rc, i;
++
++ rc = ipmi_send_recv(GET_SEL_INFO,NETFN_STORAGE,0,obuf,0,
++ ibuf,sizeof(ibuf),&i,&cc);
++ if (rc == 0 && cc != 0) rc = cc;
++ if (rc == 0)
++ printk("bmc_panic: Code %d SEL Ver %d Support %d\n",
++ ibuf[0],ibuf[1],ibuf[14]);
++ return(rc);
++} /* end ReadSELinfo()*/
++
++static unsigned char getAlarmLED(void)
++{
++ unsigned char cc;
++ unsigned char obuf[16];
++ unsigned char ibuf[16];
++ int olen, rc, i;
++ unsigned char alarms;
++
++ /* Get Alarm LED values */
++ obuf[0] = PRIVATE_BUS_ID; // 0x03;
++ obuf[1] = ALARMS_PANEL_READ; // 0x41;
++ obuf[2] = 1; // one byte of alarms data
++ obuf[3] = 0; // initial alarms value
++ olen = 3;
++ rc = ipmi_send_recv(MASTER_WRITE_READ,NETFN_APP,0,
++ obuf,olen,ibuf,4,&i,&cc);
++ alarms = ibuf[0];
++ printk("ipmi_panic: get alarms rc=%d cc=%x, alarms=%02x\n",
++ rc,cc,alarms);
++ return(alarms);
++} /*end getAlarmLED*/
++
++static int setAlarmLED(unsigned char alarms)
++{
++ unsigned char cc;
++ unsigned char obuf[16];
++ unsigned char ibuf[16];
++ int olen, rc, i;
++
++ obuf[0] = PRIVATE_BUS_ID; // 0x03;
++ obuf[1] = ALARMS_PANEL_WRITE; // 0x40;
++ obuf[2] = 1; // one byte of alarms data
++ obuf[3] = (alarms & 0x0D) | 0xF0; // turn on critical alarm
++ olen = 4;
++ rc = ipmi_send_recv(MASTER_WRITE_READ,NETFN_APP,0,
++ obuf,olen,ibuf,0,&i,&cc);
++ printk("ipmi_panic: set crit alarm rc=%d cc=%x\n",rc,cc);
++ if (rc == 0 && cc != 0) rc = cc;
++ return(rc);
++} /*end setAlarmLED*/
++
++static int insertPanicRecord(ulong event)
++{
++ unsigned char cc;
++ unsigned char obuf[16];
++ unsigned char ibuf[16];
++ int olen, rc, i;
++
++ /* Log the OS Critical Stop to the SEL (BMC firmware log). */
++ obuf[0] = 0x21; /* Kernel generator ID, IPMI table 5-4 */
++ obuf[1] = 0x03; /* 3=IPMI10, 4=IPMI15, set as back-compatible w 1.0 */
++ obuf[2] = 0x20; /* OS Critical Stop, IPMI table 36-3 */
++ obuf[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
++ obuf[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
++ /*
++ * Most panics only have event codes == 0, so use panic_string.
++ * Start of panic string usu indicates module name.
++ */
++ obuf[3] = panic_string[0];
++ obuf[6] = panic_string[1];
++ obuf[7] = panic_string[2];
++ /*
++ * Add some bits to decode panic type
++ * String above is ASCII, so it will be betw 0x20 and 0x7f.
++ */
++ if (die_str != NULL && strncmp(die_str,"Oops",4) == 0)
++ obuf[3] |= 0x80; /* Is an Oops */
++ if (event == 1) obuf[6] |= 0x80; /* In interrupt handler */
++ if (die_err & 0x01) obuf[7] |= 0x80; /* Null ptr dereference */
++ olen = 8;
++ rc = ipmi_send_recv(PLATFORM_EVENT,NETFN_SENS_EVENT,0,
++ obuf,olen,ibuf,0,&i,&cc);
++ printk("bmc_panic: log OS Critical Stop rc=%d cc=%x, %c%c%c\n",
++ rc,cc, obuf[3],obuf[6],obuf[7]);
++ if (rc == 0 && cc != 0) rc = cc;
++ return(rc);
++} /*end insertPanicRecord()*/
++
++
++static int panic_event(struct notifier_block *this, unsigned long event,
++ void *ptr)
++{
++ unsigned char alarm;
++
++ if (has_paniced) return NOTIFY_DONE;
++ has_paniced = 1;
++
++#ifdef LINUX_DEBUG
++ SELprintf("panic_string(%p): %s\n",panic_string,panic_string);
++#endif
++
++ if (fIPMIok) {
++ insertPanicRecord(event);
++ alarm = getAlarmLED();
++ if (alarm != 0) // valid, ok to setAlarmLED
++ setAlarmLED(alarm);
++ }
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block panic_block = {
++ panic_event,
++ NULL,
++ 200 /* priority: INT_MAX >= x >= 0 */
++};
++
++/* Initialize the module - Try SEL routines */
++void init_SEL(void)
++{
++#ifdef LINUX_DEBUG
++ printk (KERN_INFO "init_SEL: Reading SEL info\n");
++#endif
++ if (ReadSELinfo() != 0) {
++ /* Nothing to do if the system can't do SEL functions. */
++ fIPMIok = 0;
++ printk(KERN_ERR "bmc_panic: IPMI failure. unregister device\n");
++ }
++ else {
++ fIPMIok = 1;
++ printk (KERN_INFO "Registering bmc_panic with panic notifier\n");
++ notifier_chain_register(&panic_notifier_list, &panic_block);
++ }
++ return ;
++}
++
++
++/* Cleanup - unregister the appropriate file from /proc */
++void cleanup_SEL(void)
++{
++ printk ( KERN_INFO "Unregistering with panic notifier\n");
++ notifier_chain_unregister(&panic_notifier_list, &panic_block);
++}
++
++#ifdef CONFIG_BMCPANIC_ACTION
++#define BMCPANIC_ACTION CONFIG_BMCPANIC_ACTION
++#else
++#define BMCPANIC_ACTION 0
++#endif
++void bmcpanic_action(void)
++{
++ int ret, i;
++ unsigned char obuf, cc;
++
++ if (fIPMIok) ret = BMCPANIC_ACTION;
++ else ret = 0; /* do machine_reset */
++ switch(ret)
++ {
++ case 1: /* power down */
++ obuf = 0;
++ ret = ipmi_send_recv(CHASSIS_CTL,NETFN_CHAS,0,&obuf,1,NULL,0,&i,&cc);
++ break;
++ case 2: /* power cycle */
++ obuf = 2;
++ ret = ipmi_send_recv(CHASSIS_CTL,NETFN_CHAS,0,&obuf,1,NULL,0,&i,&cc);
++ break;
++ case 3: /* hard reset */
++ obuf = 3; /* IPMI hard reset */
++ ret = ipmi_send_recv(CHASSIS_CTL,NETFN_CHAS,0,&obuf,1,NULL,0,&i,&cc);
++ break;
++ case 0: /* soft reset */
++ default:
++ machine_restart(NULL); /* normal Linux reset (arch/i386/) */
++ }
++}
++
++void bmc_poweroff(void)
++{
++ int ret, i;
++ unsigned char obuf, cc;
++
++ if (fIPMIok) {
++ obuf = 0;
++ ret = ipmi_send_recv(CHASSIS_CTL,NETFN_CHAS,0,&obuf,1,NULL,0,&i,&cc);
++ }
++}
++
++/* end bmc_selmsg.c */
+--- linux-2.4.19-orig/arch/i386/kernel/process.c Fri Aug 2 20:39:42 2002
++++ linux-2.4.19/arch/i386/kernel/process.c Thu Feb 27 15:07:25 2003
+@@ -426,10 +426,19 @@
+ {
+ }
+
++#ifdef CONFIG_BMCPANIC
++extern void bmc_poweroff(void);
++#endif
++
+ void machine_power_off(void)
+ {
+ if (pm_power_off)
+ pm_power_off();
++
++#ifdef CONFIG_BMCPANIC
++ bmc_poweroff();
++#endif
++
+ }
+
+ extern void show_trace(unsigned long* esp);
+--- linux-2.4.19-orig/arch/i386/kernel/traps.c Fri Aug 2 20:39:42 2002
++++ linux-2.4.19/arch/i386/kernel/traps.c Thu Feb 27 15:07:25 2003
+@@ -273,6 +273,8 @@
+ }
+
+ spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
++char die_str[64] = "";
++long die_err = 0;
+
+ void die(const char * str, struct pt_regs * regs, long err)
+ {
+@@ -281,6 +283,8 @@
+ bust_spinlocks(1);
+ handle_BUG(regs);
+ printk("%s: %04lx\n", str, err & 0xffff);
++ die_err = err;
++ strncpy(die_str,str,sizeof(die_str)-1);
+ show_registers(regs);
+ bust_spinlocks(0);
+ spin_unlock_irq(&die_lock);
+--- linux-2.4.19-orig/arch/i386/kernel/i386_ksyms.c Fri Aug 2 20:39:42 2002
++++ linux-2.4.19/arch/i386/kernel/i386_ksyms.c Thu Feb 27 15:07:25 2003
+@@ -31,6 +31,8 @@
+
+ extern void dump_thread(struct pt_regs *, struct user *);
+ extern spinlock_t rtc_lock;
++extern char *die_str;
++extern long die_err;
+
+ #if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+ extern void machine_real_restart(unsigned char *, int);
+@@ -141,6 +143,9 @@
+ EXPORT_SYMBOL(__global_save_flags);
+ EXPORT_SYMBOL(__global_restore_flags);
+ EXPORT_SYMBOL(smp_call_function);
++
++EXPORT_SYMBOL(die_str);
++EXPORT_SYMBOL(die_err);
+
+ /* TLB flushing */
+ EXPORT_SYMBOL(flush_tlb_page);
diff --git a/kern/bmcpanic-2.4.20.patch b/kern/bmcpanic-2.4.20.patch
new file mode 100644
index 0000000..11caf32
--- /dev/null
+++ b/kern/bmcpanic-2.4.20.patch
@@ -0,0 +1,1000 @@
+--- linux-2.4.20-orig/drivers/char/misc.c Fri Aug 2 20:39:43 2002
++++ linux-2.4.20/drivers/char/misc.c Wed Feb 26 16:33:48 2003
+@@ -70,6 +70,7 @@
+ extern void gfx_register(void);
+ #endif
+ extern void streamable_init(void);
++extern int bmc_panic_init(void);
+ extern int rtc_DP8570A_init(void);
+ extern int rtc_MK48T08_init(void);
+ extern int ds1286_init(void);
+@@ -266,6 +267,9 @@
+ #endif
+ #ifdef CONFIG_PMAC_PBOOK
+ pmu_device_init();
++#endif
++#ifdef CONFIG_BMCPANIC
++ bmc_panic_init();
+ #endif
+ #ifdef CONFIG_SGI_NEWPORT_GFX
+ gfx_register ();
+--- linux-2.4.20-orig/kernel/panic.c Thu Nov 28 18:53:15 2002
++++ linux-2.4.20/kernel/panic.c Wed Feb 26 14:26:36 2003
+@@ -17,6 +17,10 @@
+ #include <linux/sysrq.h>
+ #include <linux/interrupt.h>
+
++char *panic_string;
++#ifdef CONFIG_BMCPANIC
++ extern void bmcpanic_action(void);
++#endif
+ asmlinkage void sys_sync(void); /* it's really int */
+
+ int panic_timeout;
+@@ -53,6 +57,7 @@
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
++ panic_string = buf;
+ printk(KERN_EMERG "Kernel panic: %s\n",buf);
+ if (in_interrupt())
+ printk(KERN_EMERG "In interrupt handler - not syncing\n");
+@@ -81,7 +86,11 @@
+ * choosing not too. It might crash, be corrupt or do
+ * more harm than good for other reasons.
+ */
+- machine_restart(NULL);
++#ifdef CONFIG_BMCPANIC
++ bmcpanic_action();
++#else
++ machine_restart(NULL);
++#endif
+ }
+ #ifdef __sparc__
+ {
+--- linux-2.4.20-orig/kernel/ksyms.c Thu Nov 28 18:53:15 2002
++++ linux-2.4.20/kernel/ksyms.c Wed Feb 26 14:27:26 2003
+@@ -61,6 +61,7 @@
+
+ extern void *sys_call_table;
+
++extern char *panic_string;
+ extern struct timezone sys_tz;
+ extern int request_dma(unsigned int dmanr, char * deviceID);
+ extern void free_dma(unsigned int dmanr);
+@@ -576,6 +577,8 @@
+
+ EXPORT_SYMBOL(tasklist_lock);
+ EXPORT_SYMBOL(pidhash);
++EXPORT_SYMBOL(panic_notifier_list);
++EXPORT_SYMBOL(panic_string);
+
+ /* debug */
+ EXPORT_SYMBOL(dump_stack);
+--- linux-2.4.20-orig/Documentation/Configure.help Thu Nov 28 18:53:08 2002
++++ linux-2.4.20/Documentation/Configure.help Wed Feb 26 14:26:36 2003
+@@ -17414,6 +17414,20 @@
+
+ If unsure, say N.
+
++BMC Panic Handler
++CONFIG_BMCPANIC
++ If you say Y here, additional functions will be added to the
++ panic handler via the panic notifier list.
++
++ If your system has IPMI support and a BMC (Baseboard Management
++ Controller) on the motherboard, then the following additional
++ functions will be performed if a panic occurs:
++ - Write an OS Critical Stop message to the firmware System Event Log
++ - Turn on the Critical LED on the Telco Alarms panel (if present)
++ - Send a BMC LAN alert via SNMP to a network operations center,
++ if the firmware Platform Event Filter configuration is set to
++ enable this.
++
+ Cobalt Networks support
+ CONFIG_COBALT
+ Support for Cobalt Networks x86-based servers.
+--- linux-2.4.20-orig/drivers/char/Makefile Thu Nov 28 18:53:12 2002
++++ linux-2.4.20/drivers/char/Makefile Wed Feb 26 14:26:36 2003
+@@ -249,6 +249,9 @@
+ obj-y += ftape/ftape.o
+ endif
+
++bmc_panic-objs := bmc_ipmi.o bmc_selmsg.o
++obj-$(CONFIG_BMCPANIC) += bmc_panic.o
++
+ obj-$(CONFIG_H8) += h8.o
+ obj-$(CONFIG_PPDEV) += ppdev.o
+ obj-$(CONFIG_DZ) += dz.o
+@@ -300,6 +303,9 @@
+ ./conmakehash $(FONTMAPFILE) > consolemap_deftbl.c
+
+ consolemap_deftbl.o: consolemap_deftbl.c $(TOPDIR)/include/linux/types.h
++
++bmc_panic.o: $(bmc_panic-objs)
++ $(LD) -r -o $@ $(bmc_panic-objs)
+
+ .DELETE_ON_ERROR:
+
+--- linux-2.4.20-orig/drivers/char/Config.in Thu Nov 28 18:53:12 2002
++++ linux-2.4.20/drivers/char/Config.in Wed Feb 26 14:26:36 2003
+@@ -141,6 +141,10 @@
+ if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
+ int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
+ fi
++bool 'BMC Panic Handler' CONFIG_BMCPANIC
++if [ "$CONFIG_BMCPANIC" != "n" ]; then
++ int ' Action after Panic (0=reset,1=power down,2=power cycle)' CONFIG_BMCPANIC_ACTION 0
++fi
+ if [ "$CONFIG_PARPORT" != "n" ]; then
+ dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
+ if [ "$CONFIG_PRINTER" != "n" ]; then
+--- /dev/null Fri Mar 23 23:37:44 2001
++++ linux-2.4.20/drivers/char/bmc_ipmi.c Thu Feb 27 11:54:39 2003
+@@ -0,0 +1,531 @@
++/*
++ * bmc_ipmi.c
++ *
++ * This code is needed to run a streamlined IPMI KCS command when
++ * the rest of the system may be dead (panic time). It must wait
++ * for completion of the receive function also.
++ * There will be zero or one BMC, with KCS as a minimum and perhaps
++ * other interfaces, so doing KCS to a default BMC LUN is valid here.
++ *
++ * Note that CONFIG_BMCPANIC should be =y (rather than =m) to
++ * ensure that this handler is loaded early enough to cover boot
++ * time panic conditions. CONFIG_BMCPANIC_ACTION can only be
++ * defined if CONFIG_BMCPANIC=y.
++ *
++ * Author: Andy Cress <arcress at users.sourceforge.net>
++ *
++ * Change History:
++ * 01/31/03 Andy Cress - created from valinux ipmi_kcs driver v2.1
++ *
++ * Copyright 2003 Intel Corp.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/semaphore.h>
++#include <linux/delay.h>
++
++#define uchar unsigned char
++
++#define KCS_READY_DELAY 5
++#define BMC_RESPONSE_DELAY 5
++#define BMC_RETRY_DELAY 60
++
++#if defined(__ia64__)
++#define KCS_BASE 0x8a2
++#else
++#define KCS_BASE 0xca2
++#endif
++#define KCS_STATUS_REG (KCS_BASE + 1)
++#define KCS_COMMAND_REG (KCS_BASE + 1)
++#define KCS_DATAIN_REG (KCS_BASE + 0)
++#define KCS_DATAOUT_REG (KCS_BASE + 0)
++
++/* State bits based on S1 & S0 below */
++#define KCS_STATE_MASK 0xC0
++#define KCS_IDLE_STATE 0x00
++#define KCS_READ_STATE 0x40
++#define KCS_WRITE_STATE 0x80
++#define KCS_ERROR_STATE 0xC0
++
++#define KCS_IBF 0x02
++#define KCS_OBF 0x01
++#define KCS_SMS_ATN 0x04
++
++#define SEND_INIT 1
++#define SEND_START 2
++#define SEND_NEXT 3
++#define SEND_END 4
++#define RECV_START 5
++#define RECV_INIT 6
++#define RECV_NEXT 7
++#define RECV_INIT2 8
++#define RECV_END 9
++#define END 10
++#define ERROR 0
++
++/* SMS Transfer Stream Control Codes */
++#define GET_STATUS_ABORT 0x60
++#define WRITE_START 0x61
++#define WRITE_END 0x62
++#define KCS_READ 0x68
++
++#define MAX_INVALID_RESPONSE_COUNT 2
++#define MIN_BMC_RESPONSE_SIZE 3
++#define MAX_IMB_PACKET_SIZE 33
++#define MAX_BMC_RESPONSE_SIZE (MIN_BMC_RESPONSE_SIZE + MAX_IMB_PACKET_SIZE)
++#define MAX_XFER_LENGTH (MAX_IMB_PACKET_SIZE * 2)
++
++#define MAX_BUFFER_SIZE 64
++
++typedef struct bmc_response
++ {
++ unsigned char lun :2;
++ unsigned char netfn :6;
++ unsigned char cmd;
++ unsigned char cc;
++ unsigned char data[1];
++ }BMC_RESPONSE;
++
++typedef struct bmc_request
++ {
++ unsigned char lun :2;
++ unsigned char netfn :6;
++ unsigned char cmd;
++ unsigned char data[1];
++ }BMC_REQUEST;
++
++/* GET_DEVICE_ID RESPONSE (11 bytes) */
++typedef struct device_id_response
++ {
++ unsigned char device_id;
++
++ unsigned char device_revision :4;
++ unsigned char reserved :3;
++ unsigned char provides_sdr :1;
++
++ unsigned char major_firmware_revision :7;
++ #define NORMAL_OPERATION 0
++ #define DEVICE_BUSY 1
++ unsigned char device_available :1;
++
++ unsigned char minor_firmware_revision;
++ unsigned char ipmi_version_major :4;
++ unsigned char ipmi_version_minor :4;
++
++ unsigned char supports_sensor_device :1;
++ unsigned char supports_sdr_device :1;
++ unsigned char supports_sel_device :1;
++ unsigned char supports_fru_device :1;
++ unsigned char supports_ipmb_receiver :1;
++ unsigned char supports_ipmb_generator :1;
++ unsigned char supports_bridge :1;
++ unsigned char supports_chassis_device :1;
++
++ unsigned char manufacturer_id1;
++ unsigned char manufacturer_id2;
++ unsigned char manufacturer_id3;
++ unsigned short product_id;
++ } DEVICE_ID_RESPONSE;
++
++/*************************************/
++
++#if defined(__ia64__)
++static char kcs_new = 1; /* don't even try old kcs */
++#else
++static char kcs_new = 0;
++#endif
++DECLARE_MUTEX(kcs_sem);
++
++/*************************************/
++
++/*
++ * kcs chip mashing stuff
++ */
++static int wait_while_ibf(void)
++{
++ unsigned char status_byte;
++
++ status_byte = inb_p(KCS_STATUS_REG);
++ if ((status_byte & KCS_IBF) == 0) return (0);
++ mdelay(KCS_READY_DELAY);
++ status_byte = inb_p(KCS_STATUS_REG);
++ if (status_byte & KCS_IBF) return (-1);
++ return (0);
++}
++
++static int is_obf_set(void)
++{
++ unsigned char cs;
++ cs = inb_p(KCS_STATUS_REG);
++ return ((cs & KCS_OBF) == KCS_OBF);
++}
++
++static int wait_until_obf(void)
++{
++ int retries = 0;
++
++ while (retries < 2) {
++ if (is_obf_set()) return (0);
++ mdelay(KCS_READY_DELAY);
++ retries++;
++ }
++ return (-ETIMEDOUT);
++}
++
++static unsigned char get_kcs_state(void)
++{
++ unsigned char cs;
++
++ cs = inb_p(KCS_STATUS_REG);
++ return (cs & KCS_STATE_MASK);
++}
++
++static unsigned char read_kcs_data(void)
++{
++ unsigned char data;
++
++ data = inb_p(KCS_DATAOUT_REG);
++ return (data);
++}
++
++static void write_kcs_data(unsigned char data)
++{
++ outb_p(data, KCS_DATAIN_REG);
++}
++
++static void write_kcs_cmd(unsigned char cmd)
++{
++ outb_p(cmd, KCS_COMMAND_REG);
++}
++
++static int clear_obf(void)
++{
++ read_kcs_data();
++ return (0);
++}
++
++static int kcs_xfer(BMC_REQUEST * request, int request_len,
++ BMC_RESPONSE * response, int *response_len)
++{
++ unsigned char *xmit_buffer, *recv_buffer;
++ int i = 0, rc = 0, state = SEND_INIT, bad = 0;
++
++ xmit_buffer = (unsigned char *) request;
++ recv_buffer = (unsigned char *) response;
++
++ while (1) {
++ if (state == END)
++ break;
++ else if (bad > 2) {
++ printk("[ipmi_panic] Maximum retries exceeded.\n");
++ rc = -EIO;
++ break;
++ }
++ switch (state) {
++ case SEND_INIT:
++ {
++ i = 0;
++ state = SEND_START;
++ wait_while_ibf();
++ if (kcs_new) clear_obf();
++ }
++ case SEND_START:
++ {
++ state = SEND_NEXT;
++ write_kcs_cmd(WRITE_START);
++ wait_while_ibf();
++ }
++ case SEND_NEXT:
++ {
++ if (i == (request_len - 1)) {
++ state = SEND_END;
++ break;
++ }
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ write_kcs_data(xmit_buffer[i++]);
++ wait_while_ibf();
++ if (kcs_new) clear_obf();
++ break;
++ }
++ case SEND_END:
++ {
++ if (!kcs_new) wait_while_ibf();
++ write_kcs_cmd(WRITE_END);
++ wait_while_ibf();
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ if (kcs_new) clear_obf();
++ write_kcs_data(xmit_buffer[i++]);
++ wait_while_ibf();
++ state = RECV_START;
++ }
++ case RECV_START:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_WRITE_STATE:
++ case KCS_IDLE_STATE:
++ {
++ mdelay(BMC_RESPONSE_DELAY);
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ i = 0;
++ memset(recv_buffer, 0,
++ *response_len);
++ state = RECV_INIT;
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_INIT:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ case KCS_WRITE_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_IDLE_STATE:
++ {
++ state = RECV_END;
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ if (is_obf_set())
++ state = RECV_NEXT;
++ else mdelay(1);
++ break;
++ }
++ default:
++ {
++ mdelay(1);
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_NEXT:
++ {
++ if (i >= *response_len) {
++ rc = -EOVERFLOW;
++ state = ERROR;
++ break;
++ }
++ recv_buffer[i++] = read_kcs_data();
++ if (!kcs_new) wait_while_ibf();
++ write_kcs_data(KCS_READ);
++ if (kcs_new) wait_while_ibf();
++ state = RECV_INIT2;
++ break;
++ }
++ case RECV_INIT2:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ case KCS_WRITE_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_IDLE_STATE:
++ {
++ if (kcs_new) {
++ if (wait_until_obf() == 0) {
++ clear_obf();
++ state = RECV_END;
++ } else {
++ state = ERROR;
++ }
++ } else {
++ state = RECV_END;
++ }
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ if (kcs_new) {
++ if (wait_until_obf() == 0)
++ state = RECV_NEXT;
++ else state = ERROR;
++ } else {
++ if (is_obf_set())
++ state = RECV_NEXT;
++ }
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_END:
++ {
++ if ((i < MIN_BMC_RESPONSE_SIZE) ||
++ (response->netfn != (request->netfn | 0x01))
++ || (response->cmd != request->cmd)) {
++ if (request->cmd == 0x01 &&
++ request->netfn == 0x06 &&
++ response->netfn == 0x2b) /*ok*/;
++ else { /* flag the error */
++ printk("[ipmi_panic] Request/Response CMD/NETFN mismatch error\n");
++
++ printk(" i=%d, RQcmd/RQnetfn=0x%x/0x%x,RScmd/RSnetfn=0x%x/0x%x\n",
++ i, request->cmd, request->netfn,
++ response->cmd, response->netfn);
++ mdelay(BMC_RETRY_DELAY);
++ bad++;
++ state = SEND_INIT;
++ break;
++ }
++ }
++
++ *response_len = i;
++ rc = 0;
++ state = END;
++ break;
++ }
++ case ERROR:
++ default:
++ {
++ printk("[ipmi_panic] BMC in bad state (%d) cmd=%02x. Retrying transfer\n", state,request->cmd);
++ mdelay(BMC_RETRY_DELAY);
++ bad++;
++ state = SEND_INIT;
++ break;
++ }
++ }
++ }
++ return (rc);
++}
++
++int ipmi_send_recv(uchar cmd, uchar netfn, uchar lun, uchar *sbuf, int slen,
++ uchar *rbuf, int rlen, int *nret, uchar *cc)
++{
++ uchar bmc_outbuf[MAX_BUFFER_SIZE];
++ uchar bmc_inbuf[MAX_BUFFER_SIZE];
++ BMC_REQUEST *bmc_req;
++ BMC_RESPONSE *bmc_resp;
++ int bmc_outlen;
++ int bmc_inlen;
++ int rc = 0;
++
++ if (kcs_new == 2) return (-ENXIO);
++
++ memset(bmc_outbuf,0, sizeof(bmc_outbuf));
++ memset(bmc_inbuf,0, sizeof(bmc_inbuf));
++ bmc_req = (BMC_REQUEST *)bmc_outbuf;
++ bmc_resp = (BMC_RESPONSE *)bmc_inbuf;
++ bmc_req->cmd = cmd;
++ bmc_req->netfn = netfn;
++ bmc_req->lun = lun;
++ bmc_outlen = slen + 2;
++ bmc_inlen = sizeof(bmc_inbuf);
++ if (slen > 0) memcpy(bmc_req->data,sbuf,slen);
++
++ rc = kcs_xfer(bmc_req, bmc_outlen, bmc_resp, &bmc_inlen);
++ if (bmc_resp->cc == 0xcc) /* flaky NMI fixup */
++ rc = kcs_xfer(bmc_req, bmc_outlen, bmc_resp, &bmc_inlen); /*retry*/
++
++ /* copy the response */
++ *cc = bmc_resp->cc;
++ if (bmc_inlen > rlen) bmc_inlen = rlen;
++ *nret = bmc_inlen;
++ if (bmc_inlen > 0) memcpy(rbuf,bmc_resp->data,bmc_inlen);
++
++ return(rc);
++}
++
++extern void init_SEL(void);
++extern void cleanup_SEL(void);
++
++int bmc_panic_init(void)
++{
++ int i, rc;
++ uchar cc;
++ uchar bdev[16];
++ DEVICE_ID_RESPONSE *dev_id;
++
++ printk("bmc_panic ipmi driver at io 0x%x\n", KCS_BASE);
++ if ((inb_p(KCS_STATUS_REG) == 0xFF) &&
++ (inb_p(KCS_DATAIN_REG) == 0xFF)) {
++ printk("--KCS ISA window not present, exiting.\n");
++ return (-ENXIO);
++ }
++
++ /* Get Device ID */
++ rc = ipmi_send_recv(0x01,0x06,0,NULL,0,bdev,sizeof(bdev),&i,&cc);
++ if (rc != 0) kcs_new = 2; /* bad */
++ else if (cc != 0) kcs_new = 2; /* bad */
++ else
++ {
++ dev_id = (DEVICE_ID_RESPONSE *)&bdev[0];
++ printk("--BMC version %x.%x, IPMI version %d.%d\n",
++ dev_id->major_firmware_revision,
++ dev_id->minor_firmware_revision,
++ dev_id->ipmi_version_major, dev_id->ipmi_version_minor);
++ if ((dev_id->ipmi_version_major == 0) &&
++ (dev_id->ipmi_version_minor == 9)) {
++ printk("--Using legacy KCS state machine\n");
++ kcs_new = 0;
++ } else {
++ printk("--Using new KCS state machine\n");
++ kcs_new = 1;
++ }
++ }
++ init_SEL();
++
++ return(rc);
++}
++
++#ifdef MODULE
++int init_module(void)
++{
++ return (bmc_panic_init());
++}
++
++void cleanup_module(void)
++{
++ printk("bmc_panic: Driver shutting down.\n");
++ cleanup_SEL();
++}
++#endif
++
++/* end bmc_ipmi.c */
+--- /dev/null Fri Mar 23 23:37:44 2001
++++ linux-2.4.20/drivers/char/bmc_selmsg.c Thu Feb 27 11:58:31 2003
+@@ -0,0 +1,269 @@
++/*
++ * bmc_selmsg.c
++ * routines to send IMB and BMC requests to the SEL and alarms panel.
++ *
++ * 05/07/01 Todd Davis - created
++ * 09/17/01 Andy Cress - some cleanup
++ * 09/26/01 Andy Cress - added setAlarmLED, changed notifier priority
++ * 10/05/01 Andy Cress - fixed setAlarmLED, changed OEM bytes in panic
++ * 10/08/01 Andy Cress - added getAlarmLED
++ * 10/09/01 Andy Cress - save 3 chars of panic_string in SEL
++ * 10/25/01 Andy Cress - fixed confusion w DEBUG macro & LINUX_DEBUG
++ * 11/05/01 Andy Cress - adapted to open source driver calls
++ * 11/14/01 Andy Cress - code complete, see also bmc_ipmi.c
++ * 01/15/02 Andy Cress - changed to show BMC_PANIC tags
++ * 03/22/02 Andy Cress - changed printk messages
++ * 04/16/02 Andy Cress - added bmcpanic_action() routine
++ * 06/04/02 Andy Cress - added bmc_poweroff() routine
++ * 02/26/02 Andy Cress - major rework to use ipmi_send_recv, trim bloat
++ */
++#include <linux/string.h>
++#include <linux/kernel.h>
++#include <linux/notifier.h> /* Routines to manage notifier chains for passing
++ * status changes to any interested routines. */
++
++///////////////////////////////////////////////////////////
++// Global definitions
++//////////////////////////////////////////////////////////
++#define uchar unsigned char
++#define ulong unsigned long
++
++#define BMC_SA 0x20 // BMC slave address
++#define NETFN_CHAS 0x00
++#define NETFN_SENS_EVENT 0x04
++#define NETFN_APP 0x06
++#define NETFN_STORAGE 0x0A
++
++#define CHASSIS_CTL 0x02
++#define GET_SEL_INFO 0x40
++#define PLATFORM_EVENT 0x02
++#define KERNEL_SENSOR_ID 0x21
++
++/* Defines for the Alarms Panel */
++#define MASTER_WRITE_READ 0x52 // Command from IPMI 1.5 Table 38-8
++#define ALARMS_PANEL_WRITE 0x40 // I2C Address 0x40 write to front panel
++#define ALARMS_PANEL_READ 0x41 // I2C Address 0x41 read from front panel
++#define PRIVATE_BUS_ID 0x03 // TAM 8574 lives on 2ndary private bus
++
++// See Table 36-3 for sensor types - 20h for OS critical stop
++// See Table 36-1 for event types - 6Fh Sensor Specific
++// discrete sensor class
++// See Table 23-6/36-3 for event data
++// data1 - 00b 00b 0001b (runtime) 0000b (initialization stop)
++// data2 - ffh (unspecified)
++// data3 - ffh (unspecified)
++
++///////////////////////////////////////////////////////////
++// Global variables
++//////////////////////////////////////////////////////////
++static int fIPMIok = 1; /* Are IPMI commands supported? */
++static int has_paniced;
++
++extern struct notifier_block *panic_notifier_list;
++extern char *panic_string;
++extern char *die_str;
++extern long die_err;
++
++extern void machine_restart(char *cmd); /*from include/linux/reboot.h*/
++extern int ipmi_panic_init(void);
++extern int ipmi_send_recv(uchar cmd, uchar netfn, uchar lun,
++ uchar *sbuf, int slen, uchar *rbuf, int rlen,
++ int *nret, uchar *cc);
++
++///////////////////////////////////////////////////////////
++// Subroutines
++//////////////////////////////////////////////////////////
++
++static int ReadSELinfo(void)
++{
++ unsigned char cc;
++ unsigned char obuf[16];
++ unsigned char ibuf[16];
++ int rc, i;
++
++ rc = ipmi_send_recv(GET_SEL_INFO,NETFN_STORAGE,0,obuf,0,
++ ibuf,sizeof(ibuf),&i,&cc);
++ if (rc == 0 && cc != 0) rc = cc;
++ if (rc == 0)
++ printk("bmc_panic: Code %d SEL Ver %d Support %d\n",
++ ibuf[0],ibuf[1],ibuf[14]);
++ return(rc);
++} /* end ReadSELinfo()*/
++
++static unsigned char getAlarmLED(void)
++{
++ unsigned char cc;
++ unsigned char obuf[16];
++ unsigned char ibuf[16];
++ int olen, rc, i;
++ unsigned char alarms;
++
++ /* Get Alarm LED values */
++ obuf[0] = PRIVATE_BUS_ID; // 0x03;
++ obuf[1] = ALARMS_PANEL_READ; // 0x41;
++ obuf[2] = 1; // one byte of alarms data
++ obuf[3] = 0; // initial alarms value
++ olen = 3;
++ rc = ipmi_send_recv(MASTER_WRITE_READ,NETFN_APP,0,
++ obuf,olen,ibuf,4,&i,&cc);
++ alarms = ibuf[0];
++ printk("ipmi_panic: get alarms rc=%d cc=%x, alarms=%02x\n",
++ rc,cc,alarms);
++ return(alarms);
++} /*end getAlarmLED*/
++
++static int setAlarmLED(unsigned char alarms)
++{
++ unsigned char cc;
++ unsigned char obuf[16];
++ unsigned char ibuf[16];
++ int olen, rc, i;
++
++ obuf[0] = PRIVATE_BUS_ID; // 0x03;
++ obuf[1] = ALARMS_PANEL_WRITE; // 0x40;
++ obuf[2] = 1; // one byte of alarms data
++ obuf[3] = (alarms & 0x0D) | 0xF0; // turn on critical alarm
++ olen = 4;
++ rc = ipmi_send_recv(MASTER_WRITE_READ,NETFN_APP,0,
++ obuf,olen,ibuf,0,&i,&cc);
++ printk("ipmi_panic: set crit alarm rc=%d cc=%x\n",rc,cc);
++ if (rc == 0 && cc != 0) rc = cc;
++ return(rc);
++} /*end setAlarmLED*/
++
++static int insertPanicRecord(ulong event)
++{
++ unsigned char cc;
++ unsigned char obuf[16];
++ unsigned char ibuf[16];
++ int olen, rc, i;
++
++ /* Log the OS Critical Stop to the SEL (BMC firmware log). */
++ obuf[0] = 0x21; /* Kernel generator ID, IPMI table 5-4 */
++ obuf[1] = 0x03; /* 3=IPMI10, 4=IPMI15, set as back-compatible w 1.0 */
++ obuf[2] = 0x20; /* OS Critical Stop, IPMI table 36-3 */
++ obuf[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
++ obuf[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
++ /*
++ * Most panics only have event codes == 0, so use panic_string.
++ * Start of panic string usu indicates module name.
++ */
++ obuf[3] = panic_string[0];
++ obuf[6] = panic_string[1];
++ obuf[7] = panic_string[2];
++ /*
++ * Add some bits to decode panic type
++ * String above is ASCII, so it will be betw 0x20 and 0x7f.
++ */
++ if (die_str != NULL && strncmp(die_str,"Oops",4) == 0)
++ obuf[3] |= 0x80; /* Is an Oops */
++ if (event == 1) obuf[6] |= 0x80; /* In interrupt handler */
++ if (die_err & 0x01) obuf[7] |= 0x80; /* Null ptr dereference */
++ olen = 8;
++ rc = ipmi_send_recv(PLATFORM_EVENT,NETFN_SENS_EVENT,0,
++ obuf,olen,ibuf,0,&i,&cc);
++ printk("bmc_panic: log OS Critical Stop rc=%d cc=%x, %c%c%c\n",
++ rc,cc, obuf[3],obuf[6],obuf[7]);
++ if (rc == 0 && cc != 0) rc = cc;
++ return(rc);
++} /*end insertPanicRecord()*/
++
++
++static int panic_event(struct notifier_block *this, unsigned long event,
++ void *ptr)
++{
++ unsigned char alarm;
++
++ if (has_paniced) return NOTIFY_DONE;
++ has_paniced = 1;
++
++#ifdef LINUX_DEBUG
++ SELprintf("panic_string(%p): %s\n",panic_string,panic_string);
++#endif
++
++ if (fIPMIok) {
++ insertPanicRecord(event);
++ alarm = getAlarmLED();
++ if (alarm != 0) // valid, ok to setAlarmLED
++ setAlarmLED(alarm);
++ }
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block panic_block = {
++ panic_event,
++ NULL,
++ 200 /* priority: INT_MAX >= x >= 0 */
++};
++
++/* Initialize the module - Try SEL routines */
++void init_SEL(void)
++{
++#ifdef LINUX_DEBUG
++ printk (KERN_INFO "init_SEL: Reading SEL info\n");
++#endif
++ if (ReadSELinfo() != 0) {
++ /* Nothing to do if the system can't do SEL functions. */
++ fIPMIok = 0;
++ printk(KERN_ERR "bmc_panic: IPMI failure. unregister device\n");
++ }
++ else {
++ fIPMIok = 1;
++ printk (KERN_INFO "Registering bmc_panic with panic notifier\n");
++ notifier_chain_register(&panic_notifier_list, &panic_block);
++ }
++ return ;
++}
++
++
++/* Cleanup - unregister the appropriate file from /proc */
++void cleanup_SEL(void)
++{
++ printk ( KERN_INFO "Unregistering with panic notifier\n");
++ notifier_chain_unregister(&panic_notifier_list, &panic_block);
++}
++
++#ifdef CONFIG_BMCPANIC_ACTION
++#define BMCPANIC_ACTION CONFIG_BMCPANIC_ACTION
++#else
++#define BMCPANIC_ACTION 0
++#endif
++void bmcpanic_action(void)
++{
++ int ret, i;
++ unsigned char obuf, cc;
++
++ if (fIPMIok) ret = BMCPANIC_ACTION;
++ else ret = 0; /* do machine_reset */
++ switch(ret)
++ {
++ case 1: /* power down */
++ obuf = 0;
++ ret = ipmi_send_recv(CHASSIS_CTL,NETFN_CHAS,0,&obuf,1,NULL,0,&i,&cc);
++ break;
++ case 2: /* power cycle */
++ obuf = 2;
++ ret = ipmi_send_recv(CHASSIS_CTL,NETFN_CHAS,0,&obuf,1,NULL,0,&i,&cc);
++ break;
++ case 3: /* hard reset */
++ obuf = 3; /* IPMI hard reset */
++ ret = ipmi_send_recv(CHASSIS_CTL,NETFN_CHAS,0,&obuf,1,NULL,0,&i,&cc);
++ break;
++ case 0: /* soft reset */
++ default:
++ machine_restart(NULL); /* normal Linux reset (arch/i386/) */
++ }
++}
++
++void bmc_poweroff(void)
++{
++ int ret, i;
++ unsigned char obuf, cc;
++
++ if (fIPMIok) {
++ obuf = 0;
++ ret = ipmi_send_recv(CHASSIS_CTL,NETFN_CHAS,0,&obuf,1,NULL,0,&i,&cc);
++ }
++}
++
++/* end bmc_selmsg.c */
+--- linux-2.4.20-orig/arch/i386/kernel/process.c Fri Aug 2 20:39:42 2002
++++ linux-2.4.20/arch/i386/kernel/process.c Wed Feb 26 14:26:36 2003
+@@ -426,10 +426,19 @@
+ {
+ }
+
++#ifdef CONFIG_BMCPANIC
++extern void bmc_poweroff(void);
++#endif
++
+ void machine_power_off(void)
+ {
+ if (pm_power_off)
+ pm_power_off();
++
++#ifdef CONFIG_BMCPANIC
++ bmc_poweroff();
++#endif
++
+ }
+
+ extern void show_trace(unsigned long* esp);
+--- linux-2.4.20-orig/arch/i386/kernel/traps.c Thu Nov 28 18:53:09 2002
++++ linux-2.4.20/arch/i386/kernel/traps.c Wed Feb 26 15:49:54 2003
+@@ -281,6 +281,8 @@
+ }
+
+ spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
++char die_str[64] = "";
++long die_err = 0;
+
+ void die(const char * str, struct pt_regs * regs, long err)
+ {
+@@ -289,6 +291,8 @@
+ bust_spinlocks(1);
+ handle_BUG(regs);
+ printk("%s: %04lx\n", str, err & 0xffff);
++ die_err = err;
++ strncpy(die_str,str,sizeof(die_str)-1);
+ show_registers(regs);
+ bust_spinlocks(0);
+ spin_unlock_irq(&die_lock);
+--- linux-2.4.20-orig/arch/i386/kernel/i386_ksyms.c Fri Aug 2 20:39:42 2002
++++ linux-2.4.20/arch/i386/kernel/i386_ksyms.c Wed Feb 26 16:01:01 2003
+@@ -31,6 +31,8 @@
+
+ extern void dump_thread(struct pt_regs *, struct user *);
+ extern spinlock_t rtc_lock;
++extern char *die_str;
++extern long die_err;
+
+ #if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+ extern void machine_real_restart(unsigned char *, int);
+@@ -141,6 +143,9 @@
+ EXPORT_SYMBOL(__global_save_flags);
+ EXPORT_SYMBOL(__global_restore_flags);
+ EXPORT_SYMBOL(smp_call_function);
++
++EXPORT_SYMBOL(die_str);
++EXPORT_SYMBOL(die_err);
+
+ /* TLB flushing */
+ EXPORT_SYMBOL(flush_tlb_page);
diff --git a/kern/bmcpanic-2.5.44.patch b/kern/bmcpanic-2.5.44.patch
new file mode 100644
index 0000000..eb0e1d0
--- /dev/null
+++ b/kern/bmcpanic-2.5.44.patch
@@ -0,0 +1,795 @@
+--- linux-2.5.44-orig/kernel/panic.c Sat Oct 19 00:02:32 2002
++++ linux-2.5.44/kernel/panic.c Fri Jan 31 13:03:55 2003
+@@ -20,6 +20,10 @@
+ asmlinkage void sys_sync(void); /* it's really int */
+
+ int panic_timeout;
++char *panic_string;
++#ifdef CONFIG_IPMI_PANIC_ACTION
++ extern void ipmi_reset(int mode);
++#endif
+
+ struct notifier_block *panic_notifier_list;
+
+@@ -53,6 +57,7 @@
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
++ panic_string = buf;
+ printk(KERN_EMERG "Kernel panic: %s\n",buf);
+ if (in_interrupt())
+ printk(KERN_EMERG "In interrupt handler - not syncing\n");
+@@ -81,7 +86,11 @@
+ * choosing not too. It might crash, be corrupt or do
+ * more harm than good for other reasons.
+ */
++#ifdef CONFIG_IPMI_PANIC_ACTION
++ ipmi_reset(CONFIG_IPMI_PANIC_ACTION);
++#else
+ machine_restart(NULL);
++#endif
+ }
+ #ifdef __sparc__
+ {
+--- linux-2.5.44-orig/kernel/ksyms.c Sat Oct 19 00:01:08 2002
++++ linux-2.5.44/kernel/ksyms.c Wed Jan 29 10:09:26 2003
+@@ -63,6 +63,8 @@
+ #endif
+
+ extern void set_device_ro(kdev_t dev,int flag);
++extern int panic_timeout;
++extern char *panic_string;
+
+ extern struct timezone sys_tz;
+
+@@ -601,3 +603,6 @@
+
+ /* debug */
+ EXPORT_SYMBOL(dump_stack);
++EXPORT_SYMBOL(panic_notifier_list);
++EXPORT_SYMBOL(panic_timeout);
++EXPORT_SYMBOL(panic_string);
+--- linux-2.5.44-orig/drivers/char/Config.in Thu Jan 30 12:59:15 2003
++++ linux-2.5.44/drivers/char/Config.in Thu Jan 30 12:55:53 2003
+@@ -110,6 +110,9 @@
+ dep_tristate ' Device interface for IPMI' CONFIG_IPMI_DEVICE_INTERFACE $CONFIG_IPMI_HANDLER
+ dep_tristate ' IPMI KCS handler' CONFIG_IPMI_KCS $CONFIG_IPMI_HANDLER
+ dep_tristate ' IPMI Watchdog Timer' CONFIG_IPMI_WATCHDOG $CONFIG_IPMI_HANDLER
++if [ "$CONFIG_IPMI_HANDLER" == "y" ]; then
++ int ' Action after Panic (0=reset,1=power down,2=power cycle)' CONFIG_IPMI_PANIC_ACTION 0
++fi
+
+ mainmenu_option next_comment
+ comment 'Watchdog Cards'
+--- linux-2.5.44-orig/drivers/char/ipmi/Makefile Thu Jan 30 12:59:15 2003
++++ linux-2.5.44/drivers/char/ipmi/Makefile Fri Jan 31 11:40:33 2003
+@@ -6,7 +6,7 @@
+
+ ipmi_kcs_drv-objs := ipmi_kcs_sm.o ipmi_kcs_intf.o
+
+-obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o
++obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o ipmi_panic.o
+ obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
+ obj-$(CONFIG_IPMI_KCS) += ipmi_kcs_drv.o
+ obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
+--- linux-2.5.44-orig/drivers/char/ipmi/ipmi_msghandler.c Thu Jan 30 12:59:15 2003
++++ linux-2.5.44/drivers/char/ipmi/ipmi_msghandler.c Tue Feb 4 10:46:51 2003
+@@ -44,6 +44,14 @@
+ #include <linux/notifier.h>
+ #include <linux/init.h>
+
++#ifdef CONFIG_IPMI_PANIC_ACTION
++#define uchar unsigned char
++extern int ipmi_panic_init(void);
++extern int ipmi_send_recv(uchar cmd, uchar netfn, uchar lun,
++ uchar *sbuf, int slen, uchar *rbuf, int rlen,
++ int *nret, uchar *cc);
++#endif
++
+ struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
+ static int ipmi_init_msghandler(void);
+
+@@ -369,6 +377,7 @@
+ return rv;
+ }
+
++static int fIPMIok = 0; /* true if an IPMI interface is valid */
+
+ int ipmi_create_user(unsigned int if_num,
+ struct ipmi_user_hndl *handler,
+@@ -413,6 +422,7 @@
+ goto out_unlock;
+ }
+
++ fIPMIok = 1; /* at least one IPMI interface is valid */
+ new_user->handler = handler;
+ new_user->handler_data = handler_data;
+ new_user->intf = ipmi_interfaces[if_num];
+@@ -1618,8 +1628,13 @@
+ return rv;
+ }
+
++extern void machine_restart(char * __unused);
++extern void machine_power_off(void);
++extern char *panic_string;
++
+ #ifdef CONFIG_IPMI_PANIC_EVENT
+
++#ifndef CONFIG_IPMI_PANIC_ACTION
+ static void dummy_smi_done_handler(struct ipmi_smi_msg *msg)
+ {
+ }
+@@ -1652,12 +1667,9 @@
+ data[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
+ data[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
+
+- /* These used to have the first three bytes of the panic string,
+- but not only is that not terribly useful, it's not available
+- any more. */
+- data[3] = 0;
+- data[6] = 0;
+- data[7] = 0;
++ data[3] = panic_string[0];
++ data[6] = panic_string[1];
++ data[7] = panic_string[2];
+
+ smi_msg.done = dummy_smi_done_handler;
+ recv_msg.done = dummy_recv_done_handler;
+@@ -1681,6 +1693,30 @@
+ intf->my_lun);
+ }
+ }
++#endif
++
++void ipmi_reset(int mode)
++{
++#ifdef CONFIG_IPMI_PANIC_ACTION
++ unsigned char imode;
++ unsigned char cc;
++ int rc, i;
++
++ /* Input mode param: 0 = soft reset, 1 = power down, 2 = power cycle */
++ if (!fIPMIok || mode == 0 || mode > 3) {
++ machine_restart(NULL); /* normal Linux reset (arch/i386/) */
++ return;
++ }
++ /*
++ * IPMI Chassis Reset modes:
++ * 0 = power down, 1 = power up, 2 = power cycle, 3 = hard reset
++ */
++ if (mode == 1) imode = 0;
++ else imode = mode;
++ rc = ipmi_send_recv(0x02,0x00,0,&imode,1,NULL,0,&i,&cc);
++#endif
++ return;
++}
+ #endif /* CONFIG_IPMI_PANIC_EVENT */
+
+ static int has_paniced = 0;
+@@ -1699,14 +1735,55 @@
+ /* For every registered interface, set it to run to completion. */
+ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ intf = ipmi_interfaces[i];
+- if (intf == NULL)
+- continue;
+-
++ if (intf == NULL) continue;
+ intf->handlers->set_run_to_completion(intf->send_info, 1);
+ }
+
+ #ifdef CONFIG_IPMI_PANIC_EVENT
+- send_panic_events();
++ if (fIPMIok) {
++#ifdef CONFIG_IPMI_PANIC_ACTION
++ unsigned char alarms, cc;
++ unsigned char obuf[16];
++ unsigned char ibuf[16];
++ int olen, rc;
++
++ /* Get Alarm LED values */
++ obuf[0] = 0x03; // PRIVATE_BUS_ID;
++ obuf[1] = 0x41; // ALARMS_PANEL_READ;
++ obuf[2] = 1; // one byte of alarms data
++ obuf[3] = 0; // initial alarms value
++ olen = 3;
++ rc = ipmi_send_recv(0x52,0x06,0,obuf,olen,ibuf,4,&i,&cc);
++ alarms = ibuf[0];
++ printk("ipmi_panic: get alarms rc=%d cc=%x, alarms=%02x\n",
++ rc,cc,alarms);
++ if (alarms == 0) alarms = 0x0F; /* 0=err, fallback to default */
++ if (rc == 0) { // valid, so ok to set alarm LED
++ /* Set Crit Alarm LED */
++ obuf[0] = 0x03; // PRIVATE_BUS_ID;
++ obuf[1] = 0x40; // ALARMS_PANEL_WRITE;
++ obuf[2] = 1; // one byte of alarms data
++ obuf[3] = (alarms & 0x0D) | 0xF0; // turn on critical alarm
++ olen = 4;
++ rc = ipmi_send_recv(0x52,0x06,0,obuf,olen,NULL,0,&i,&cc);
++ printk("ipmi_panic: set crit alarm rc=%d cc=%x\n",rc,cc);
++ }
++ /* Log the OS Critical Stop to the SEL (BMC firmware log). */
++ obuf[0] = 0x21; /* Kernel generator ID, IPMI table 5-4 */
++ obuf[1] = 0x03; /* This is for IPMI 1.0. */
++ obuf[2] = 0x20; /* OS Critical Stop, IPMI table 36-3 */
++ obuf[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
++ obuf[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
++ obuf[3] = panic_string[0];
++ obuf[6] = panic_string[1];
++ obuf[7] = panic_string[2];
++ olen = 8;
++ rc = ipmi_send_recv(0x02,0x04,0,obuf,olen,NULL,0,&i,&cc);
++ printk("ipmi_panic: log OS Critical Stop rc=%d cc=%x\n",rc,cc);
++#else
++ send_panic_events();
++#endif
++ }
+ #endif
+
+ return NOTIFY_DONE;
+@@ -1738,6 +1815,9 @@
+
+ notifier_chain_register(&panic_notifier_list, &panic_block);
+
++#ifdef CONFIG_IPMI_PANIC_ACTION
++ ipmi_panic_init();
++#endif
+ initialized = 1;
+
+ printk(KERN_INFO "ipmi: message handler initialized\n");
+@@ -1795,3 +1875,6 @@
+ EXPORT_SYMBOL(ipmi_get_my_address);
+ EXPORT_SYMBOL(ipmi_set_my_LUN);
+ EXPORT_SYMBOL(ipmi_get_my_LUN);
++#ifdef CONFIG_IPMI_PANIC_ACTION
++EXPORT_SYMBOL(ipmi_reset);
++#endif
+--- /dev/null Fri Mar 23 23:37:44 2001
++++ linux-2.5.44/drivers/char/ipmi/ipmi_panic.c Tue Feb 4 10:50:45 2003
+@@ -0,0 +1,515 @@
++/*
++ * ipmi_panic.c
++ *
++ * This code is needed to run a streamlined IPMI KCS command when
++ * the rest of the system may be dead (panic time). It must wait
++ * for completion of the receive function also.
++ * There will be zero or one BMC, with KCS as a minimum and perhaps
++ * other interfaces, so doing KCS to a default BMC LUN is valid here.
++ *
++ * Note that CONFIG_IPMI_HANDLER should be =y (rather than =m) to
++ * ensure that this handler is loaded early enough to cover boot
++ * time panic conditions. CONFIG_IPMI_PANIC_ACTION can only be
++ * defined if CONFIG_IPMI_HANDLER=y.
++ *
++ * Author: Andy Cress <arcress at users.sourceforge.net>
++ *
++ * Change History:
++ * 01/31/03 Andy Cress - created for kernel 2.5.44 with OpenIPMI
++ *
++ * Copyright 2003 Intel Corp.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/semaphore.h>
++#include <linux/delay.h>
++
++#define uchar unsigned char
++
++#define KCS_READY_DELAY 5
++#define BMC_RESPONSE_DELAY 5
++#define BMC_RETRY_DELAY 60
++
++#if defined(__ia64__)
++#define KCS_BASE 0x8a2
++#else
++#define KCS_BASE 0xca2
++#endif
++#define KCS_STATUS_REG (KCS_BASE + 1)
++#define KCS_COMMAND_REG (KCS_BASE + 1)
++#define KCS_DATAIN_REG (KCS_BASE + 0)
++#define KCS_DATAOUT_REG (KCS_BASE + 0)
++
++/* State bits based on S1 & S0 below */
++#define KCS_STATE_MASK 0xC0
++#define KCS_IDLE_STATE 0x00
++#define KCS_READ_STATE 0x40
++#define KCS_WRITE_STATE 0x80
++#define KCS_ERROR_STATE 0xC0
++
++#define KCS_IBF 0x02
++#define KCS_OBF 0x01
++#define KCS_SMS_ATN 0x04
++
++#define SEND_INIT 1
++#define SEND_START 2
++#define SEND_NEXT 3
++#define SEND_END 4
++#define RECV_START 5
++#define RECV_INIT 6
++#define RECV_NEXT 7
++#define RECV_INIT2 8
++#define RECV_END 9
++#define END 10
++#define ERROR 0
++
++/* SMS Transfer Stream Control Codes */
++#define GET_STATUS_ABORT 0x60
++#define WRITE_START 0x61
++#define WRITE_END 0x62
++#define KCS_READ 0x68
++
++#define MAX_INVALID_RESPONSE_COUNT 2
++#define MIN_BMC_RESPONSE_SIZE 3
++#define MAX_IMB_PACKET_SIZE 33
++#define MAX_BMC_RESPONSE_SIZE (MIN_BMC_RESPONSE_SIZE + MAX_IMB_PACKET_SIZE)
++#define MAX_XFER_LENGTH (MAX_IMB_PACKET_SIZE * 2)
++
++#define MAX_BUFFER_SIZE 64
++
++typedef struct bmc_response
++ {
++ unsigned char lun :2;
++ unsigned char netfn :6;
++ unsigned char cmd;
++ unsigned char cc;
++ unsigned char data[1];
++ }BMC_RESPONSE;
++
++typedef struct bmc_request
++ {
++ unsigned char lun :2;
++ unsigned char netfn :6;
++ unsigned char cmd;
++ unsigned char data[1];
++ }BMC_REQUEST;
++
++/* GET_DEVICE_ID RESPONSE (11 bytes) */
++typedef struct device_id_response
++ {
++ unsigned char device_id;
++
++ unsigned char device_revision :4;
++ unsigned char reserved :3;
++ unsigned char provides_sdr :1;
++
++ unsigned char major_firmware_revision :7;
++ #define NORMAL_OPERATION 0
++ #define DEVICE_BUSY 1
++ unsigned char device_available :1;
++
++ unsigned char minor_firmware_revision;
++ unsigned char ipmi_version_major :4;
++ unsigned char ipmi_version_minor :4;
++
++ unsigned char supports_sensor_device :1;
++ unsigned char supports_sdr_device :1;
++ unsigned char supports_sel_device :1;
++ unsigned char supports_fru_device :1;
++ unsigned char supports_ipmb_receiver :1;
++ unsigned char supports_ipmb_generator :1;
++ unsigned char supports_bridge :1;
++ unsigned char supports_chassis_device :1;
++
++ unsigned char manufacturer_id1;
++ unsigned char manufacturer_id2;
++ unsigned char manufacturer_id3;
++ unsigned short product_id;
++ } DEVICE_ID_RESPONSE;
++
++/*************************************/
++
++#if defined(__ia64__)
++static char kcs_new = 1;
++#else
++static char kcs_new = 0;
++#endif
++DECLARE_MUTEX(kcs_sem);
++
++/*************************************/
++
++/*
++ * kcs chip mashing stuff
++ */
++static int wait_while_ibf(void)
++{
++ unsigned char status_byte;
++
++ status_byte = inb_p(KCS_STATUS_REG);
++ if ((status_byte & KCS_IBF) == 0) return (0);
++ mdelay(KCS_READY_DELAY);
++ status_byte = inb_p(KCS_STATUS_REG);
++ if (status_byte & KCS_IBF) return (-1);
++ return (0);
++}
++
++static int is_obf_set(void)
++{
++ unsigned char cs;
++ cs = inb_p(KCS_STATUS_REG);
++ return ((cs & KCS_OBF) == KCS_OBF);
++}
++
++static int wait_until_obf(void)
++{
++ int retries = 0;
++
++ while (retries < 2) {
++ if (is_obf_set()) return (0);
++ mdelay(KCS_READY_DELAY);
++ retries++;
++ }
++ return (-ETIMEDOUT);
++}
++
++static unsigned char get_kcs_state(void)
++{
++ unsigned char cs;
++
++ cs = inb_p(KCS_STATUS_REG);
++ return (cs & KCS_STATE_MASK);
++}
++
++static unsigned char read_kcs_data(void)
++{
++ unsigned char data;
++
++ data = inb_p(KCS_DATAOUT_REG);
++ return (data);
++}
++
++static void write_kcs_data(unsigned char data)
++{
++ outb_p(data, KCS_DATAIN_REG);
++}
++
++static void write_kcs_cmd(unsigned char cmd)
++{
++ outb_p(cmd, KCS_COMMAND_REG);
++}
++
++static int clear_obf(void)
++{
++ read_kcs_data();
++ return (0);
++}
++
++static int kcs_xfer(BMC_REQUEST * request, int request_len,
++ BMC_RESPONSE * response, int *response_len)
++{
++ unsigned char *xmit_buffer, *recv_buffer;
++ int i = 0, rc = 0, state = SEND_INIT, bad = 0;
++
++ xmit_buffer = (unsigned char *) request;
++ recv_buffer = (unsigned char *) response;
++
++ while (1) {
++ if (state == END)
++ break;
++ else if (bad > 2) {
++ printk("[ipmi_panic] Maximum retries exceeded.\n");
++ rc = -EIO;
++ break;
++ }
++ switch (state) {
++ case SEND_INIT:
++ {
++ i = 0;
++ state = SEND_START;
++ wait_while_ibf();
++ if (kcs_new) clear_obf();
++ }
++ case SEND_START:
++ {
++ state = SEND_NEXT;
++ write_kcs_cmd(WRITE_START);
++ wait_while_ibf();
++ }
++ case SEND_NEXT:
++ {
++ if (i == (request_len - 1)) {
++ state = SEND_END;
++ break;
++ }
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ write_kcs_data(xmit_buffer[i++]);
++ wait_while_ibf();
++ if (kcs_new) clear_obf();
++ break;
++ }
++ case SEND_END:
++ {
++ if (!kcs_new) wait_while_ibf();
++ write_kcs_cmd(WRITE_END);
++ wait_while_ibf();
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ if (kcs_new) clear_obf();
++ write_kcs_data(xmit_buffer[i++]);
++ wait_while_ibf();
++ state = RECV_START;
++ }
++ case RECV_START:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_WRITE_STATE:
++ case KCS_IDLE_STATE:
++ {
++ mdelay(BMC_RESPONSE_DELAY);
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ i = 0;
++ memset(recv_buffer, 0,
++ *response_len);
++ state = RECV_INIT;
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_INIT:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ case KCS_WRITE_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_IDLE_STATE:
++ {
++ state = RECV_END;
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ if (is_obf_set())
++ state = RECV_NEXT;
++ else mdelay(1);
++ break;
++ }
++ default:
++ {
++ mdelay(1);
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_NEXT:
++ {
++ if (i >= *response_len) {
++ rc = -EOVERFLOW;
++ state = ERROR;
++ break;
++ }
++ recv_buffer[i++] = read_kcs_data();
++ if (!kcs_new) wait_while_ibf();
++ write_kcs_data(KCS_READ);
++ if (kcs_new) wait_while_ibf();
++ state = RECV_INIT2;
++ break;
++ }
++ case RECV_INIT2:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ case KCS_WRITE_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_IDLE_STATE:
++ {
++ if (kcs_new) {
++ if (wait_until_obf() == 0) {
++ clear_obf();
++ state = RECV_END;
++ } else {
++ state = ERROR;
++ }
++ } else {
++ state = RECV_END;
++ }
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ if (kcs_new) {
++ if (wait_until_obf() == 0)
++ state = RECV_NEXT;
++ else state = ERROR;
++ } else {
++ if (is_obf_set())
++ state = RECV_NEXT;
++ }
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_END:
++ {
++ if ((i < MIN_BMC_RESPONSE_SIZE) ||
++ (response->netfn != (request->netfn | 0x01))
++ || (response->cmd != request->cmd)) {
++ if (request->cmd == 0x01 &&
++ request->netfn == 0x06 &&
++ response->netfn == 0x2b) /*ok*/;
++ else { /* flag the error */
++ printk("[ipmi_panic] Request/Response CMD/NETFN mismatch error\n");
++
++ printk(" i=%d, RQcmd/RQnetfn=0x%x/0x%x,RScmd/RSnetfn=0x%x/0x%x\n",
++ i, request->cmd, request->netfn,
++ response->cmd, response->netfn);
++ mdelay(BMC_RETRY_DELAY);
++ bad++;
++ state = SEND_INIT;
++ break;
++ }
++ }
++
++ *response_len = i;
++ rc = 0;
++ state = END;
++ break;
++ }
++ case ERROR:
++ default:
++ {
++ printk("[ipmi_panic] BMC in bad state. Retrying transfer\n");
++ mdelay(BMC_RETRY_DELAY);
++ bad++;
++ state = SEND_INIT;
++ break;
++ }
++ }
++ }
++ return (rc);
++}
++
++int ipmi_send_recv(uchar cmd, uchar netfn, uchar lun, uchar *sbuf, int slen,
++ uchar *rbuf, int rlen, int *nret, uchar *cc)
++{
++ uchar bmc_outbuf[MAX_BUFFER_SIZE];
++ uchar bmc_inbuf[MAX_BUFFER_SIZE];
++ BMC_REQUEST *bmc_req;
++ BMC_RESPONSE *bmc_resp;
++ int bmc_outlen;
++ int bmc_inlen;
++ int rc = 0;
++
++ if (kcs_new == 2) return (-ENXIO);
++
++ memset(bmc_outbuf,0, sizeof(bmc_outbuf));
++ memset(bmc_inbuf,0, sizeof(bmc_inbuf));
++ bmc_req = (BMC_REQUEST *)bmc_outbuf;
++ bmc_resp = (BMC_RESPONSE *)bmc_inbuf;
++ bmc_req->cmd = cmd;
++ bmc_req->netfn = netfn;
++ bmc_req->lun = lun;
++ bmc_outlen = slen + 2;
++ bmc_inlen = sizeof(bmc_inbuf);
++ if (slen > 0) memcpy(bmc_req->data,sbuf,slen);
++
++ rc = kcs_xfer(bmc_req, bmc_outlen, bmc_resp, &bmc_inlen);
++ if (bmc_resp->cc == 0xcc) /* flaky NMI fixup */
++ rc = kcs_xfer(bmc_req, bmc_outlen, bmc_resp, &bmc_inlen); /*retry*/
++
++ /* copy the response */
++ *cc = bmc_resp->cc;
++ if (bmc_inlen > rlen) bmc_inlen = rlen;
++ *nret = bmc_inlen;
++ if (bmc_inlen > 0) memcpy(rbuf,bmc_resp->data,bmc_inlen);
++
++ return(rc);
++}
++
++int ipmi_panic_init(void)
++{
++ int i, rc;
++ uchar cc;
++ uchar bdev[16];
++ DEVICE_ID_RESPONSE *dev_id;
++
++ printk("ipmi_panic driver at io 0x%x\n", KCS_BASE);
++ if ((inb_p(KCS_STATUS_REG) == 0xFF) &&
++ (inb_p(KCS_DATAIN_REG) == 0xFF)) {
++ printk("--KCS ISA window not present, exiting.\n");
++ return (-ENXIO);
++ }
++
++ /* Get Device ID */
++ rc = ipmi_send_recv(0x01,0x06,0,NULL,0,bdev,sizeof(bdev),&i,&cc);
++ if (rc != 0) kcs_new = 2; /* bad */
++ else if (cc != 0) kcs_new = 2; /* bad */
++ else
++ {
++ dev_id = (DEVICE_ID_RESPONSE *)&bdev[0];
++ printk("--BMC version %x.%x, IPMI version %d.%d\n",
++ dev_id->major_firmware_revision,
++ dev_id->minor_firmware_revision,
++ dev_id->ipmi_version_major, dev_id->ipmi_version_minor);
++ if ((dev_id->ipmi_version_major == 0) &&
++ (dev_id->ipmi_version_minor == 9)) {
++ printk("--Using legacy KCS state machine\n");
++ kcs_new = 0;
++ } else {
++ printk("--Using new KCS state machine\n");
++ kcs_new = 1;
++ }
++ }
++ /* dont care about chipset vendor, but test Lancewood & IPF to be sure*/
++
++ return(rc);
++}
++
++/* end ipmi_panic.c */
+--- linux-2.5.44-orig/arch/i386/kernel/reboot.c Sat Oct 19 00:01:20 2002
++++ linux-2.5.44/arch/i386/kernel/reboot.c Thu Jan 30 15:45:32 2003
+@@ -221,6 +221,10 @@
+ : "i" ((void *) (0x1000 - sizeof (real_mode_switch) - 100)));
+ }
+
++#ifdef CONFIG_IPMI_PANIC_ACTION
++extern void ipmi_reset(int mode);
++#endif
++
+ void machine_restart(char * __unused)
+ {
+ #if CONFIG_SMP
+@@ -277,6 +281,9 @@
+ }
+ }
+
++#ifdef CONFIG_IPMI_PANIC_ACTION
++ ipmi_reset(1);
++#endif
+ machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
+ }
+
+@@ -288,5 +295,8 @@
+ {
+ if (pm_power_off)
+ pm_power_off();
++#ifdef CONFIG_IPMI_PANIC_ACTION
++ ipmi_reset(0);
++#endif
+ }
+
diff --git a/kern/bmcpanic-2.5.62.patch b/kern/bmcpanic-2.5.62.patch
new file mode 100644
index 0000000..44e9141
--- /dev/null
+++ b/kern/bmcpanic-2.5.62.patch
@@ -0,0 +1,830 @@
+diff -Naru linux-2.5.62/arch/i386/kernel/reboot.c linux-2.5.62p/arch/i386/kernel/reboot.c
+--- linux-2.5.62/arch/i386/kernel/reboot.c 2003-03-07 16:33:50.000000000 +0800
++++ linux-2.5.62p/arch/i386/kernel/reboot.c 2003-03-06 22:27:16.000000000 +0800
+@@ -221,6 +221,10 @@
+ : "i" ((void *) (0x1000 - sizeof (real_mode_switch) - 100)));
+ }
+
++#ifdef CONFIG_IPMI_PANIC_ACTION
++extern void ipmi_reset(int mode);
++#endif
++
+ void machine_restart(char * __unused)
+ {
+ #if CONFIG_SMP
+@@ -277,6 +281,9 @@
+ }
+ }
+
++#ifdef CONFIG_IPMI_PANIC_ACTION
++ ipmi_reset(1);
++#endif
+ machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
+ }
+
+@@ -288,5 +295,8 @@
+ {
+ if (pm_power_off)
+ pm_power_off();
++#ifdef CONFIG_IPMI_PANIC_ACTION
++ ipmi_reset(0);
++#endif
+ }
+
+diff -Naru linux-2.5.62/drivers/char/ipmi/ipmi_msghandler.c linux-2.5.62p/drivers/char/ipmi/ipmi_msghandler.c
+--- linux-2.5.62/drivers/char/ipmi/ipmi_msghandler.c 2003-03-07 16:34:18.000000000 +0800
++++ linux-2.5.62p/drivers/char/ipmi/ipmi_msghandler.c 2003-03-06 22:27:16.000000000 +0800
+@@ -45,6 +45,14 @@
+ #include <linux/notifier.h>
+ #include <linux/init.h>
+
++#ifdef CONFIG_IPMI_PANIC_ACTION
++#define uchar unsigned char
++extern int ipmi_panic_init(void);
++extern int ipmi_send_recv(uchar cmd, uchar netfn, uchar lun,
++ uchar *sbuf, int slen, uchar *rbuf, int rlen,
++ int *nret, uchar *cc);
++#endif
++
+ struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
+ static int ipmi_init_msghandler(void);
+
+@@ -345,7 +353,7 @@
+ unsigned int i;
+
+ for (i=intf->curr_seq;
+- i!=(intf->curr_seq-1);
++ (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq;
+ i=(i+1)%IPMI_IPMB_NUM_SEQ)
+ {
+ if (! intf->seq_table[i].inuse)
+@@ -437,6 +445,7 @@
+ return rv;
+ }
+
++static int fIPMIok = 0; /* true if an IPMI interface is valid */
+
+ int ipmi_create_user(unsigned int if_num,
+ struct ipmi_user_hndl *handler,
+@@ -480,6 +489,7 @@
+ goto out_unlock;
+ }
+
++ fIPMIok = 1; /* at least one IPMI interface is valid */
+ new_user->handler = handler;
+ new_user->handler_data = handler_data;
+ new_user->intf = ipmi_interfaces[if_num];
+@@ -906,8 +916,6 @@
+ probably, so abort. */
+ spin_unlock_irqrestore(&(intf->seq_lock),
+ flags);
+- ipmi_free_recv_msg(recv_msg);
+- ipmi_free_smi_msg(smi_msg);
+ goto out_err;
+ }
+
+@@ -1794,8 +1802,13 @@
+ return rv;
+ }
+
++extern void machine_restart(char * __unused);
++extern void machine_power_off(void);
++extern char *panic_string;
++
+ #ifdef CONFIG_IPMI_PANIC_EVENT
+
++#ifndef CONFIG_IPMI_PANIC_ACTION
+ static void dummy_smi_done_handler(struct ipmi_smi_msg *msg)
+ {
+ }
+@@ -1828,12 +1841,9 @@
+ data[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
+ data[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
+
+- /* These used to have the first three bytes of the panic string,
+- but not only is that not terribly useful, it's not available
+- any more. */
+- data[3] = 0;
+- data[6] = 0;
+- data[7] = 0;
++ data[3] = panic_string[0];
++ data[6] = panic_string[1];
++ data[7] = panic_string[2];
+
+ smi_msg.done = dummy_smi_done_handler;
+ recv_msg.done = dummy_recv_done_handler;
+@@ -1857,6 +1867,30 @@
+ intf->my_lun);
+ }
+ }
++#endif
++
++void ipmi_reset(int mode)
++{
++#ifdef CONFIG_IPMI_PANIC_ACTION
++ unsigned char imode;
++ unsigned char cc;
++ int rc, i;
++
++ /* Input mode param: 0 = soft reset, 1 = power down, 2 = power cycle */
++ if (!fIPMIok || mode == 0 || mode > 3) {
++ machine_restart(NULL); /* normal Linux reset (arch/i386/) */
++ return;
++ }
++ /*
++ * IPMI Chassis Reset modes:
++ * 0 = power down, 1 = power up, 2 = power cycle, 3 = hard reset
++ */
++ if (mode == 1) imode = 0;
++ else imode = mode;
++ rc = ipmi_send_recv(0x02,0x00,0,&imode,1,NULL,0,&i,&cc);
++#endif
++ return;
++}
+ #endif /* CONFIG_IPMI_PANIC_EVENT */
+
+ static int has_paniced = 0;
+@@ -1875,14 +1909,55 @@
+ /* For every registered interface, set it to run to completion. */
+ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ intf = ipmi_interfaces[i];
+- if (intf == NULL)
+- continue;
+-
++ if (intf == NULL) continue;
+ intf->handlers->set_run_to_completion(intf->send_info, 1);
+ }
+
+ #ifdef CONFIG_IPMI_PANIC_EVENT
+- send_panic_events();
++ if (fIPMIok) {
++#ifdef CONFIG_IPMI_PANIC_ACTION
++ unsigned char alarms, cc;
++ unsigned char obuf[16];
++ unsigned char ibuf[16];
++ int olen, rc;
++
++ /* Get Alarm LED values */
++ obuf[0] = 0x03; // PRIVATE_BUS_ID;
++ obuf[1] = 0x41; // ALARMS_PANEL_READ;
++ obuf[2] = 1; // one byte of alarms data
++ obuf[3] = 0; // initial alarms value
++ olen = 3;
++ rc = ipmi_send_recv(0x52,0x06,0,obuf,olen,ibuf,4,&i,&cc);
++ alarms = ibuf[0];
++ printk("ipmi_panic: get alarms rc=%d cc=%x, alarms=%02x\n",
++ rc,cc,alarms);
++ if (alarms == 0) alarms = 0x0F; /* 0=err, fallback to default */
++ if (rc == 0) { // valid, so ok to set alarm LED
++ /* Set Crit Alarm LED */
++ obuf[0] = 0x03; // PRIVATE_BUS_ID;
++ obuf[1] = 0x40; // ALARMS_PANEL_WRITE;
++ obuf[2] = 1; // one byte of alarms data
++ obuf[3] = (alarms & 0x0D) | 0xF0; // turn on critical alarm
++ olen = 4;
++ rc = ipmi_send_recv(0x52,0x06,0,obuf,olen,NULL,0,&i,&cc);
++ printk("ipmi_panic: set crit alarm rc=%d cc=%x\n",rc,cc);
++ }
++ /* Log the OS Critical Stop to the SEL (BMC firmware log). */
++ obuf[0] = 0x21; /* Kernel generator ID, IPMI table 5-4 */
++ obuf[1] = 0x03; /* This is for IPMI 1.0. */
++ obuf[2] = 0x20; /* OS Critical Stop, IPMI table 36-3 */
++ obuf[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
++ obuf[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
++ obuf[3] = panic_string[0];
++ obuf[6] = panic_string[1];
++ obuf[7] = panic_string[2];
++ olen = 8;
++ rc = ipmi_send_recv(0x02,0x04,0,obuf,olen,NULL,0,&i,&cc);
++ printk("ipmi_panic: log OS Critical Stop rc=%d cc=%x\n",rc,cc);
++#else
++ send_panic_events();
++#endif
++ }
+ #endif
+
+ return NOTIFY_DONE;
+@@ -1914,6 +1989,9 @@
+
+ notifier_chain_register(&panic_notifier_list, &panic_block);
+
++#ifdef CONFIG_IPMI_PANIC_ACTION
++ ipmi_panic_init();
++#endif
+ initialized = 1;
+
+ printk(KERN_INFO "ipmi: message handler initialized\n");
+@@ -1971,3 +2049,6 @@
+ EXPORT_SYMBOL(ipmi_get_my_address);
+ EXPORT_SYMBOL(ipmi_set_my_LUN);
+ EXPORT_SYMBOL(ipmi_get_my_LUN);
++#ifdef CONFIG_IPMI_PANIC_ACTION
++EXPORT_SYMBOL(ipmi_reset);
++#endif
+diff -Naru linux-2.5.62/drivers/char/ipmi/ipmi_panic.c linux-2.5.62p/drivers/char/ipmi/ipmi_panic.c
+--- linux-2.5.62/drivers/char/ipmi/ipmi_panic.c 1970-01-01 08:00:00.000000000 +0800
++++ linux-2.5.62p/drivers/char/ipmi/ipmi_panic.c 2003-03-06 22:27:16.000000000 +0800
+@@ -0,0 +1,515 @@
++/*
++ * ipmi_panic.c
++ *
++ * This code is needed to run a streamlined IPMI KCS command when
++ * the rest of the system may be dead (panic time). It must wait
++ * for completion of the receive function also.
++ * There will be zero or one BMC, with KCS as a minimum and perhaps
++ * other interfaces, so doing KCS to a default BMC LUN is valid here.
++ *
++ * Note that CONFIG_IPMI_HANDLER should be =y (rather than =m) to
++ * ensure that this handler is loaded early enough to cover boot
++ * time panic conditions. CONFIG_IPMI_PANIC_ACTION can only be
++ * defined if CONFIG_IPMI_HANDLER=y.
++ *
++ * Author: Andy Cress <arcress at users.sourceforge.net>
++ *
++ * Change History:
++ * 01/31/03 Andy Cress - created for kernel 2.5.44 with OpenIPMI
++ *
++ * Copyright 2003 Intel Corp.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/semaphore.h>
++#include <linux/delay.h>
++
++#define uchar unsigned char
++
++#define KCS_READY_DELAY 5
++#define BMC_RESPONSE_DELAY 5
++#define BMC_RETRY_DELAY 60
++
++#if defined(__ia64__)
++#define KCS_BASE 0x8a2
++#else
++#define KCS_BASE 0xca2
++#endif
++#define KCS_STATUS_REG (KCS_BASE + 1)
++#define KCS_COMMAND_REG (KCS_BASE + 1)
++#define KCS_DATAIN_REG (KCS_BASE + 0)
++#define KCS_DATAOUT_REG (KCS_BASE + 0)
++
++/* State bits based on S1 & S0 below */
++#define KCS_STATE_MASK 0xC0
++#define KCS_IDLE_STATE 0x00
++#define KCS_READ_STATE 0x40
++#define KCS_WRITE_STATE 0x80
++#define KCS_ERROR_STATE 0xC0
++
++#define KCS_IBF 0x02
++#define KCS_OBF 0x01
++#define KCS_SMS_ATN 0x04
++
++#define SEND_INIT 1
++#define SEND_START 2
++#define SEND_NEXT 3
++#define SEND_END 4
++#define RECV_START 5
++#define RECV_INIT 6
++#define RECV_NEXT 7
++#define RECV_INIT2 8
++#define RECV_END 9
++#define END 10
++#define ERROR 0
++
++/* SMS Transfer Stream Control Codes */
++#define GET_STATUS_ABORT 0x60
++#define WRITE_START 0x61
++#define WRITE_END 0x62
++#define KCS_READ 0x68
++
++#define MAX_INVALID_RESPONSE_COUNT 2
++#define MIN_BMC_RESPONSE_SIZE 3
++#define MAX_IMB_PACKET_SIZE 33
++#define MAX_BMC_RESPONSE_SIZE (MIN_BMC_RESPONSE_SIZE + MAX_IMB_PACKET_SIZE)
++#define MAX_XFER_LENGTH (MAX_IMB_PACKET_SIZE * 2)
++
++#define MAX_BUFFER_SIZE 64
++
++typedef struct bmc_response
++ {
++ unsigned char lun :2;
++ unsigned char netfn :6;
++ unsigned char cmd;
++ unsigned char cc;
++ unsigned char data[1];
++ }BMC_RESPONSE;
++
++typedef struct bmc_request
++ {
++ unsigned char lun :2;
++ unsigned char netfn :6;
++ unsigned char cmd;
++ unsigned char data[1];
++ }BMC_REQUEST;
++
++/* GET_DEVICE_ID RESPONSE (11 bytes) */
++typedef struct device_id_response
++ {
++ unsigned char device_id;
++
++ unsigned char device_revision :4;
++ unsigned char reserved :3;
++ unsigned char provides_sdr :1;
++
++ unsigned char major_firmware_revision :7;
++ #define NORMAL_OPERATION 0
++ #define DEVICE_BUSY 1
++ unsigned char device_available :1;
++
++ unsigned char minor_firmware_revision;
++ unsigned char ipmi_version_major :4;
++ unsigned char ipmi_version_minor :4;
++
++ unsigned char supports_sensor_device :1;
++ unsigned char supports_sdr_device :1;
++ unsigned char supports_sel_device :1;
++ unsigned char supports_fru_device :1;
++ unsigned char supports_ipmb_receiver :1;
++ unsigned char supports_ipmb_generator :1;
++ unsigned char supports_bridge :1;
++ unsigned char supports_chassis_device :1;
++
++ unsigned char manufacturer_id1;
++ unsigned char manufacturer_id2;
++ unsigned char manufacturer_id3;
++ unsigned short product_id;
++ } DEVICE_ID_RESPONSE;
++
++/*************************************/
++
++#if defined(__ia64__)
++static char kcs_new = 1;
++#else
++static char kcs_new = 0;
++#endif
++DECLARE_MUTEX(kcs_sem);
++
++/*************************************/
++
++/*
++ * kcs chip mashing stuff
++ */
++static int wait_while_ibf(void)
++{
++ unsigned char status_byte;
++
++ status_byte = inb_p(KCS_STATUS_REG);
++ if ((status_byte & KCS_IBF) == 0) return (0);
++ mdelay(KCS_READY_DELAY);
++ status_byte = inb_p(KCS_STATUS_REG);
++ if (status_byte & KCS_IBF) return (-1);
++ return (0);
++}
++
++static int is_obf_set(void)
++{
++ unsigned char cs;
++ cs = inb_p(KCS_STATUS_REG);
++ return ((cs & KCS_OBF) == KCS_OBF);
++}
++
++static int wait_until_obf(void)
++{
++ int retries = 0;
++
++ while (retries < 2) {
++ if (is_obf_set()) return (0);
++ mdelay(KCS_READY_DELAY);
++ retries++;
++ }
++ return (-ETIMEDOUT);
++}
++
++static unsigned char get_kcs_state(void)
++{
++ unsigned char cs;
++
++ cs = inb_p(KCS_STATUS_REG);
++ return (cs & KCS_STATE_MASK);
++}
++
++static unsigned char read_kcs_data(void)
++{
++ unsigned char data;
++
++ data = inb_p(KCS_DATAOUT_REG);
++ return (data);
++}
++
++static void write_kcs_data(unsigned char data)
++{
++ outb_p(data, KCS_DATAIN_REG);
++}
++
++static void write_kcs_cmd(unsigned char cmd)
++{
++ outb_p(cmd, KCS_COMMAND_REG);
++}
++
++static int clear_obf(void)
++{
++ read_kcs_data();
++ return (0);
++}
++
++static int kcs_xfer(BMC_REQUEST * request, int request_len,
++ BMC_RESPONSE * response, int *response_len)
++{
++ unsigned char *xmit_buffer, *recv_buffer;
++ int i = 0, rc = 0, state = SEND_INIT, bad = 0;
++
++ xmit_buffer = (unsigned char *) request;
++ recv_buffer = (unsigned char *) response;
++
++ while (1) {
++ if (state == END)
++ break;
++ else if (bad > 2) {
++ printk("[ipmi_panic] Maximum retries exceeded.\n");
++ rc = -EIO;
++ break;
++ }
++ switch (state) {
++ case SEND_INIT:
++ {
++ i = 0;
++ state = SEND_START;
++ wait_while_ibf();
++ if (kcs_new) clear_obf();
++ }
++ case SEND_START:
++ {
++ state = SEND_NEXT;
++ write_kcs_cmd(WRITE_START);
++ wait_while_ibf();
++ }
++ case SEND_NEXT:
++ {
++ if (i == (request_len - 1)) {
++ state = SEND_END;
++ break;
++ }
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ write_kcs_data(xmit_buffer[i++]);
++ wait_while_ibf();
++ if (kcs_new) clear_obf();
++ break;
++ }
++ case SEND_END:
++ {
++ if (!kcs_new) wait_while_ibf();
++ write_kcs_cmd(WRITE_END);
++ wait_while_ibf();
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ if (kcs_new) clear_obf();
++ write_kcs_data(xmit_buffer[i++]);
++ wait_while_ibf();
++ state = RECV_START;
++ }
++ case RECV_START:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_WRITE_STATE:
++ case KCS_IDLE_STATE:
++ {
++ mdelay(BMC_RESPONSE_DELAY);
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ i = 0;
++ memset(recv_buffer, 0,
++ *response_len);
++ state = RECV_INIT;
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_INIT:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ case KCS_WRITE_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_IDLE_STATE:
++ {
++ state = RECV_END;
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ if (is_obf_set())
++ state = RECV_NEXT;
++ else mdelay(1);
++ break;
++ }
++ default:
++ {
++ mdelay(1);
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_NEXT:
++ {
++ if (i >= *response_len) {
++ rc = -EOVERFLOW;
++ state = ERROR;
++ break;
++ }
++ recv_buffer[i++] = read_kcs_data();
++ if (!kcs_new) wait_while_ibf();
++ write_kcs_data(KCS_READ);
++ if (kcs_new) wait_while_ibf();
++ state = RECV_INIT2;
++ break;
++ }
++ case RECV_INIT2:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ case KCS_WRITE_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_IDLE_STATE:
++ {
++ if (kcs_new) {
++ if (wait_until_obf() == 0) {
++ clear_obf();
++ state = RECV_END;
++ } else {
++ state = ERROR;
++ }
++ } else {
++ state = RECV_END;
++ }
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ if (kcs_new) {
++ if (wait_until_obf() == 0)
++ state = RECV_NEXT;
++ else state = ERROR;
++ } else {
++ if (is_obf_set())
++ state = RECV_NEXT;
++ }
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_END:
++ {
++ if ((i < MIN_BMC_RESPONSE_SIZE) ||
++ (response->netfn != (request->netfn | 0x01))
++ || (response->cmd != request->cmd)) {
++ if (request->cmd == 0x01 &&
++ request->netfn == 0x06 &&
++ response->netfn == 0x2b) /*ok*/;
++ else { /* flag the error */
++ printk("[ipmi_panic] Request/Response CMD/NETFN mismatch error\n");
++
++ printk(" i=%d, RQcmd/RQnetfn=0x%x/0x%x,RScmd/RSnetfn=0x%x/0x%x\n",
++ i, request->cmd, request->netfn,
++ response->cmd, response->netfn);
++ mdelay(BMC_RETRY_DELAY);
++ bad++;
++ state = SEND_INIT;
++ break;
++ }
++ }
++
++ *response_len = i;
++ rc = 0;
++ state = END;
++ break;
++ }
++ case ERROR:
++ default:
++ {
++ printk("[ipmi_panic] BMC in bad state. Retrying transfer\n");
++ mdelay(BMC_RETRY_DELAY);
++ bad++;
++ state = SEND_INIT;
++ break;
++ }
++ }
++ }
++ return (rc);
++}
++
++int ipmi_send_recv(uchar cmd, uchar netfn, uchar lun, uchar *sbuf, int slen,
++ uchar *rbuf, int rlen, int *nret, uchar *cc)
++{
++ uchar bmc_outbuf[MAX_BUFFER_SIZE];
++ uchar bmc_inbuf[MAX_BUFFER_SIZE];
++ BMC_REQUEST *bmc_req;
++ BMC_RESPONSE *bmc_resp;
++ int bmc_outlen;
++ int bmc_inlen;
++ int rc = 0;
++
++ if (kcs_new == 2) return (-ENXIO);
++
++ memset(bmc_outbuf,0, sizeof(bmc_outbuf));
++ memset(bmc_inbuf,0, sizeof(bmc_inbuf));
++ bmc_req = (BMC_REQUEST *)bmc_outbuf;
++ bmc_resp = (BMC_RESPONSE *)bmc_inbuf;
++ bmc_req->cmd = cmd;
++ bmc_req->netfn = netfn;
++ bmc_req->lun = lun;
++ bmc_outlen = slen + 2;
++ bmc_inlen = sizeof(bmc_inbuf);
++ if (slen > 0) memcpy(bmc_req->data,sbuf,slen);
++
++ rc = kcs_xfer(bmc_req, bmc_outlen, bmc_resp, &bmc_inlen);
++ if (bmc_resp->cc == 0xcc) /* flaky NMI fixup */
++ rc = kcs_xfer(bmc_req, bmc_outlen, bmc_resp, &bmc_inlen); /*retry*/
++
++ /* copy the response */
++ *cc = bmc_resp->cc;
++ if (bmc_inlen > rlen) bmc_inlen = rlen;
++ *nret = bmc_inlen;
++ if (bmc_inlen > 0) memcpy(rbuf,bmc_resp->data,bmc_inlen);
++
++ return(rc);
++}
++
++int ipmi_panic_init(void)
++{
++ int i, rc;
++ uchar cc;
++ uchar bdev[16];
++ DEVICE_ID_RESPONSE *dev_id;
++
++ printk("ipmi_panic driver at io 0x%x\n", KCS_BASE);
++ if ((inb_p(KCS_STATUS_REG) == 0xFF) &&
++ (inb_p(KCS_DATAIN_REG) == 0xFF)) {
++ printk("--KCS ISA window not present, exiting.\n");
++ return (-ENXIO);
++ }
++
++ /* Get Device ID */
++ rc = ipmi_send_recv(0x01,0x06,0,NULL,0,bdev,sizeof(bdev),&i,&cc);
++ if (rc != 0) kcs_new = 2; /* bad */
++ else if (cc != 0) kcs_new = 2; /* bad */
++ else
++ {
++ dev_id = (DEVICE_ID_RESPONSE *)&bdev[0];
++ printk("--BMC version %x.%x, IPMI version %d.%d\n",
++ dev_id->major_firmware_revision,
++ dev_id->minor_firmware_revision,
++ dev_id->ipmi_version_major, dev_id->ipmi_version_minor);
++ if ((dev_id->ipmi_version_major == 0) &&
++ (dev_id->ipmi_version_minor == 9)) {
++ printk("--Using legacy KCS state machine\n");
++ kcs_new = 0;
++ } else {
++ printk("--Using new KCS state machine\n");
++ kcs_new = 1;
++ }
++ }
++ /* dont care about chipset vendor, but test Lancewood & IPF to be sure*/
++
++ return(rc);
++}
++
++/* end ipmi_panic.c */
+diff -Naru linux-2.5.62/drivers/char/ipmi/Kconfig linux-2.5.62p/drivers/char/ipmi/Kconfig
+--- linux-2.5.62/drivers/char/ipmi/Kconfig 2003-03-07 16:34:23.000000000 +0800
++++ linux-2.5.62p/drivers/char/ipmi/Kconfig 2003-03-06 22:46:58.000000000 +0800
+@@ -7,8 +7,14 @@
+ tristate 'IPMI top-level message handler'
+ help
+ This enables the central IPMI message handler, required for IPMI
+- to work. Note that you must have this enabled to do any other IPMI
+- things. See IPMI.txt for more details.
++ to work.
++
++ IPMI is a standard for managing sensors (temperature,
++ voltage, etc.) in a system.
++
++ See Documentation/IPMI.txt for more details on the driver.
++
++ If unsure, say N.
+
+ config IPMI_PANIC_EVENT
+ bool 'Generate a panic event to all BMCs on a panic'
+@@ -36,5 +42,11 @@
+ depends on IPMI_HANDLER
+ help
+ This enables the IPMI watchdog timer.
++config IPMI_PANIC_ACTION
++ int 'Action after Panic (0=reset,1=power down,2=power cycle)'
++ requires IPMI_HANDLER=y
++ default "0"
++ help
++ Set the Action after Panic
+
+ endmenu
+diff -Naru linux-2.5.62/drivers/char/ipmi/Makefile linux-2.5.62p/drivers/char/ipmi/Makefile
+--- linux-2.5.62/drivers/char/ipmi/Makefile 2003-03-07 16:34:54.000000000 +0800
++++ linux-2.5.62p/drivers/char/ipmi/Makefile 2003-03-06 22:27:16.000000000 +0800
+@@ -4,7 +4,7 @@
+
+ ipmi_kcs_drv-objs := ipmi_kcs_sm.o ipmi_kcs_intf.o
+
+-obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o
++obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o ipmi_panic.o
+ obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
+ obj-$(CONFIG_IPMI_KCS) += ipmi_kcs_drv.o
+ obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
+diff -Naru linux-2.5.62/drivers/char/Kconfig linux-2.5.62p/drivers/char/Kconfig
+--- linux-2.5.62/drivers/char/Kconfig 2003-03-07 16:33:38.000000000 +0800
++++ linux-2.5.62p/drivers/char/Kconfig 2003-03-07 16:22:02.000000000 +0800
+@@ -999,5 +999,6 @@
+ out to lunch past a certain margin. It can reboot the system
+ or merely print a warning.
+
++
+ endmenu
+
+diff -Naru linux-2.5.62/kernel/panic.c linux-2.5.62p/kernel/panic.c
+--- linux-2.5.62/kernel/panic.c 2003-03-07 16:34:58.000000000 +0800
++++ linux-2.5.62p/kernel/panic.c 2003-03-06 22:27:07.000000000 +0800
+@@ -20,6 +20,10 @@
+ asmlinkage void sys_sync(void); /* it's really int */
+
+ int panic_timeout;
++char *panic_string;
++#ifdef CONFIG_IPMI_PANIC_ACTION
++ extern void ipmi_reset(int mode);
++#endif
+
+ struct notifier_block *panic_notifier_list;
+
+@@ -53,6 +57,7 @@
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
++ panic_string = buf;
+ printk(KERN_EMERG "Kernel panic: %s\n",buf);
+ if (in_interrupt())
+ printk(KERN_EMERG "In interrupt handler - not syncing\n");
+@@ -81,7 +86,11 @@
+ * choosing not too. It might crash, be corrupt or do
+ * more harm than good for other reasons.
+ */
++#ifdef CONFIG_IPMI_PANIC_ACTION
++ ipmi_reset(CONFIG_IPMI_PANIC_ACTION);
++#else
+ machine_restart(NULL);
++#endif
+ }
+ #ifdef __sparc__
+ {
diff --git a/kern/bmcpanic-2.6.0.patch b/kern/bmcpanic-2.6.0.patch
new file mode 100644
index 0000000..da24915
--- /dev/null
+++ b/kern/bmcpanic-2.6.0.patch
@@ -0,0 +1,162 @@
+--- linux-2.6.0-test3orig/drivers/char/ipmi/ipmi_msghandler.c 2003-08-09 00:37:25.000000000 -0400
++++ linux-2.6.0-test3/drivers/char/ipmi/ipmi_msghandler.c 2003-08-14 09:40:49.000000000 -0400
+@@ -1813,7 +1813,9 @@
+ {
+ }
+
+-static void send_panic_events(void)
++#define EVENT_VALID 0x80
++
++static void send_panic_events(int evt, char *str)
+ {
+ struct ipmi_msg msg;
+ ipmi_smi_t intf;
+@@ -1837,12 +1839,17 @@
+ data[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
+ data[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
+
+- /* These used to have the first three bytes of the panic string,
+- but not only is that not terribly useful, it's not available
+- any more. */
+- data[3] = 0;
+- data[6] = 0;
+- data[7] = 0;
++ /*
++ * Add whatever breadcrumbs we can to indicate the type of panic.
++ * In kernel 2.6.0 an event code and panic string are passed in.
++ */
++ if (evt != 0)
++ data[7] = EVENT_VALID | (evt & 0x7f);
++ if (str != NULL) {
++ data[3] = str[0];
++ data[6] = str[1];
++ if (evt == 0) data[7] = str[2];
++ }
+
+ smi_msg.done = dummy_smi_done_handler;
+ recv_msg.done = dummy_recv_done_handler;
+@@ -1891,7 +1898,7 @@
+ }
+
+ #ifdef CONFIG_IPMI_PANIC_EVENT
+- send_panic_events();
++ send_panic_events(event,(char *)ptr);
+ #endif
+
+ return NOTIFY_DONE;
+--- linux-2.6.0-test3orig/arch/i386/kernel/traps.c 2003-08-09 00:33:15.000000000 -0400
++++ linux-2.6.0-test3/arch/i386/kernel/traps.c 2003-08-13 17:37:50.789828552 -0400
+@@ -288,6 +288,8 @@
+ return address;
+ }
+
++extern int last_trapnr;
++
+ static inline void do_trap(int trapnr, int signr, char *str, int vm86,
+ struct pt_regs * regs, long error_code, siginfo_t *info)
+ {
+@@ -312,8 +314,10 @@
+ }
+
+ kernel_trap: {
+- if (!fixup_exception(regs))
++ if (!fixup_exception(regs)) {
++ last_trapnr = trapnr;
+ die(str, regs, error_code);
++ }
+ return;
+ }
+
+@@ -387,8 +391,10 @@
+ return;
+
+ gp_in_kernel:
+- if (!fixup_exception(regs))
++ if (!fixup_exception(regs)) {
++ last_trapnr = 13;
+ die("general protection fault", regs, error_code);
++ }
+ }
+
+ static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
+@@ -721,6 +727,7 @@
+ error_code);
+ return;
+ }
++ last_trapnr = 19;
+ die_if_kernel("cache flush denied", regs, error_code);
+ current->thread.trap_no = 19;
+ current->thread.error_code = error_code;
+--- linux-2.6.0-test3orig/kernel/ksyms.c 2003-08-09 00:31:15.000000000 -0400
++++ linux-2.6.0-test3/kernel/ksyms.c 2003-08-13 17:39:00.000000000 -0400
+@@ -71,6 +71,7 @@
+ extern struct timezone sys_tz;
+
+ extern int panic_timeout;
++extern int last_trapnr;
+
+ /* process memory management */
+ EXPORT_SYMBOL(do_mmap_pgoff);
+@@ -504,6 +505,7 @@
+ EXPORT_SYMBOL(panic);
+ EXPORT_SYMBOL(panic_notifier_list);
+ EXPORT_SYMBOL(panic_timeout);
++EXPORT_SYMBOL(last_trapnr);
+ EXPORT_SYMBOL(sprintf);
+ EXPORT_SYMBOL(snprintf);
+ EXPORT_SYMBOL(sscanf);
+--- linux-2.6.0-test3orig/kernel/panic.c 2003-08-09 00:41:41.000000000 -0400
++++ linux-2.6.0-test3/kernel/panic.c 2003-08-13 17:38:49.000000000 -0400
+@@ -20,9 +20,15 @@
+
+ asmlinkage void sys_sync(void); /* it's really int */
+
++/* values for panic event */
++#define EVENT_VALID 0x80
++#define PANIC_IN_INTERRUPT 0x40
++#define TRAP_INIT 0x80
++
+ int panic_timeout;
+ int panic_on_oops;
+ int tainted;
++int last_trapnr = TRAP_INIT;
+
+ struct notifier_block *panic_notifier_list;
+
+@@ -47,6 +53,7 @@
+ {
+ static char buf[1024];
+ va_list args;
++ int event = 0;
+ #if defined(CONFIG_ARCH_S390)
+ unsigned long caller = (unsigned long) __builtin_return_address(0);
+ #endif
+@@ -56,11 +63,16 @@
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ printk(KERN_EMERG "Kernel panic: %s\n",buf);
+- if (in_interrupt())
++ if (last_trapnr != TRAP_INIT) {
++ /* should be <= 30 trapnr values, so packing in 0x3f is ok */
++ event = EVENT_VALID + (last_trapnr & 0x3f);
++ }
++ if (in_interrupt()) {
++ event |= PANIC_IN_INTERRUPT; /*0x40*/
+ printk(KERN_EMERG "In interrupt handler - not syncing\n");
+- else if (!current->pid)
++ } else if (!current->pid)
+ printk(KERN_EMERG "In idle task - not syncing\n");
+- else
++ else
+ sys_sync();
+ bust_spinlocks(0);
+
+@@ -68,7 +80,7 @@
+ smp_send_stop();
+ #endif
+
+- notifier_call_chain(&panic_notifier_list, 0, buf);
++ notifier_call_chain(&panic_notifier_list, event, buf);
+
+ if (panic_timeout > 0)
+ {
diff --git a/kern/ipmi_kcs.patch b/kern/ipmi_kcs.patch
new file mode 100644
index 0000000..15f9a10
--- /dev/null
+++ b/kern/ipmi_kcs.patch
@@ -0,0 +1,1592 @@
+--- linux-2.4.2-virgin/drivers/char/misc.c Sun Apr 8 18:22:17 2001
++++ linux-bmc/drivers/char/misc.c Tue Oct 30 17:18:07 2001
+@@ -273,6 +273,9 @@
+ #ifdef CONFIG_TOSHIBA
+ tosh_init();
+ #endif
++#ifdef CONFIG_IPMI_KCS
++ ipmi_kcs_init();
++#endif
+ if (devfs_register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
+ printk("unable to get major %d for misc devices\n",
+ MISC_MAJOR);
+--- linux-2.4.2-virgin/drivers/char/Config.in Sun Apr 8 18:22:22 2001
++++ linux-bmc/drivers/char/Config.in Tue Oct 30 17:18:07 2001
+@@ -81,6 +81,11 @@
+ dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT
+ fi
+
++tristate 'IPMI KCS Interface' CONFIG_IPMI_KCS
++if [ "$CONFIG_IPMI_KCS" != "n" ]; then
++ bool ' BMC watchdog timer support' CONFIG_BMC_WDT
++fi
++
+ source drivers/i2c/Config.in
+
+ source drivers/sensors/Config.in
+--- linux-2.4.2-virgin/drivers/char/Makefile Sun Apr 8 18:22:17 2001
++++ linux-bmc/drivers/char/Makefile Tue Oct 30 17:18:08 2001
+@@ -191,6 +191,8 @@
+ obj-$(CONFIG_NWBUTTON) += nwbutton.o
+ obj-$(CONFIG_NWFLASH) += nwflash.o
+
++obj-$(CONFIG_IPMI_KCS) += ipmi_kcs.o
++
+ # Only one watchdog can succeed. We probe the hardware watchdog
+ # drivers first, then the softdog driver. This means if your hardware
+ # watchdog dies or is 'borrowed' for some reason the software watchdog
+--- linux-2.4.2-virgin/include/linux/miscdevice.h Sun Apr 8 18:47:26 2001
++++ linux-bmc/include/linux/miscdevice.h Tue Oct 30 17:32:42 2001
+@@ -31,6 +31,9 @@
+ #define SGI_STREAMS_KEYBOARD 150
+ /* drivers/sgi/char/usema.c */
+ #define SGI_USEMACLONE 151
++#define IPMI_KCS_MINOR 173
++#define IPMI_BT_MINOR 210
++#define IPMI_SMIC_MINOR 211
+
+ #define TUN_MINOR 200
+
+--- /dev/null Fri Mar 23 23:37:44 2001
++++ linux-bmc/drivers/char/ipmi_kcs.c Tue Oct 30 17:18:07 2001
+@@ -0,0 +1,1211 @@
++/*
++ * Intelligent Platform Management Interface driver for Linux 2.2.x
++ *
++ * (c) Copyright 2000 San Mehat <nettwerk@valinux.com>, All Rights Reserved.
++ * http://www.valinux.com
++ *
++ * 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.
++ *
++ * Neither San Mehat nor VA Linux Systems admit liability nor provide
++ * warranty for any of this software. This material is provided
++ * "AS-IS" and at no charge.
++ *
++ * (c) Copyright 1999 San Mehat <nettwerk@valinux.com>
++ *
++ * Release 0.04. - Initial Release
++ *
++ * Release 0.05. - Fixed ring buffer bugs... better buffer handling
++ *
++ * Release 0.06. - Changed polling freq to 1/10 sec
++ *
++ * Release 0.07. - Integrated watchdog commands into IOCTL's and added
++ * support for blinking front panel LED
++ *
++ * Release 0.08. - Sensor read commands added as ioctl
++ *
++ * Release 0.09. - Changed polling freq back to 1 second
++ * - Fixed possible bug where a chip status variable was
++ * not declared volatile.
++ * - Fixed buffer memory leak
++ * - Fixed ioctl return value problem
++ * - Changed architecture so that applications calling
++ * driver ioctl()'s are put to sleep after request
++ * is sent. The reply is handled by the normal
++ * driver polling timer queue and ring buffer
++ *
++ * Release 0.10. - Modified kcs_write routine so once a write is complete
++ * if the interface isn't in a 'READ STATE' it's okay.
++ *
++ * Release 0.12. - Added Intel Nightshade MB fixups since NS boards don't
++ * support pre-timeout NMI support
++ * - FRU download support added
++ * - /proc/ipmi created with fru data and driver status
++ * Release 0.13. - Added ioctl for setting asset tag
++ * - Fixed bug in /proc
++ * - Added asset tag max length field
++ * Release 1.00 - Added intelligent proc reading so that asset tag is
++ * refreshed whenever /proc/ipmi is read
++ * - Code cleanup
++ * - When asset tag is set with data whoes size is < maximum,
++ * pad the rest out with NULLs
++ * Release 1.10 - Fixed SMP bug which was causing command failures when
++ * /proc/ipmi was being read while a command was being
++ * executed (added semaphore)
++ * - Fixed /proc/ipmi so commands only get issued once
++ * Release 1.20 - Removed a bunch of useless warning msgs
++ * Release 1.30 - Added more stringent error checking when ISA state
++ * enters ERROR_STATE
++ * - Added better unexpected OBF handling on transactions
++ * - Explicitly set power sensor state to NO BLINKY on
++ * startup
++ * Release 2.0 - Re-wrote kcs state machine
++ * - Removed high level functions from driver
++ * - removed driver read() and write() capabilities
++ * - /proc/ipmi renamed to /proc/ipmi_kcs
++ * - /proc/ipmi_kcs now contains only BMC info
++ *
++ * Release 2.1 - Added support of watchdog timer through /dev/watchdog
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/smp_lock.h>
++#include <linux/miscdevice.h>
++#include "ipmi_kcs.h"
++#include <linux/malloc.h>
++#include <linux/ioport.h>
++#include <linux/fcntl.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/semaphore.h>
++#include <linux/notifier.h>
++#include <linux/reboot.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/timer.h>
++#include <linux/ipmi_ioctls.h>
++#include <linux/pci.h>
++
++#ifdef CONFIG_PROC_FS
++#include <linux/proc_fs.h>
++#endif
++
++#ifdef CONFIG_BMC_WDT
++#include <linux/watchdog.h>
++#endif
++
++/* function prototypes */
++
++int ipmi_kcs_init(void);
++
++static int kcs_open(struct inode *inode, struct file *file);
++static int kcs_release(struct inode *inode, struct file *file);
++static ssize_t kcs_read(struct file *file, char *buf, size_t count,
++ loff_t * ptr);
++static ssize_t kcs_write(struct file *file, const char *buf, size_t count,
++ loff_t * ppos);
++static long long kcs_llseek(struct file *file, long long offset,
++ int origin);
++static int kcs_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg);
++
++#ifdef CONFIG_BMC_WDT
++static int wdt_is_open;
++static int watchdog_set(int cmd);
++static int watchdog_reset(void);
++static int wdt_open(struct inode *inode, struct file *file);
++static int wdt_release(struct inode *inode, struct file *file);
++static ssize_t wdt_write(struct file *file, const char *buf, size_t count,
++ loff_t * ppos);
++static int wdt_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg);
++
++static struct file_operations wdt_fops = {
++ owner:THIS_MODULE,
++ write:wdt_write,
++ ioctl:wdt_ioctl,
++ open:wdt_open,
++ release:wdt_release,
++};
++
++static struct miscdevice wdt_miscdev = {
++ WATCHDOG_MINOR,
++ "bmc_wdt",
++ &wdt_fops
++};
++
++/* module parameters */
++static int wdt_margin = 60; /* watchdog timer interval in seconds */
++static int wdt_pre = 1; /* watchdog pre-timeout interval in seconds */
++static int wdt_action = 0x03; /* Default is no pre-timeout interrupt and power cycle upon timeout */
++
++MODULE_PARM(wdt_margin, "i");
++MODULE_PARM(wdt_pre, "i");
++MODULE_PARM(wdt_action, "i");
++
++#define WATCHDOG_ENABLE 0x01
++#define WATCHDOG_DISABLE 0x02
++#endif
++
++static unsigned char get_kcs_state(void);
++static unsigned char read_kcs_data(void);
++static void write_kcs_data(unsigned char data);
++static void write_kcs_cmd(unsigned char cmd);
++static int is_obf_set(void);
++static int clear_obf(void);
++static int wait_while_ibf(void);
++static int get_deviceid(void);
++static int kcs_do_xfer(BMC_REQUEST * request, int request_len,
++ BMC_RESPONSE * response, int *response_len);
++static int old_kcs_do_xfer(BMC_REQUEST * request, int request_len,
++ BMC_RESPONSE * response, int *response_len);
++static int new_kcs_do_xfer(BMC_REQUEST * request, int request_len,
++ BMC_RESPONSE * response, int *response_len);
++
++#ifdef CONFIG_PROC_FS
++int ipmi_get_info(char *buf, char **start, off_t fpos, int length,
++ int *eof, void *unused);
++#endif
++
++/* static globals */
++static int kcs_refcnt = 0;
++static int driver_major = 2;
++static int driver_minor = 1;
++static int kcs_machine = 0;
++
++static struct {
++ unsigned int tx_good;
++ unsigned int tx_bad;
++} kcs_stat;
++
++static DEVICE_ID_RESPONSE dev_id;
++DECLARE_MUTEX(kcs_sem);
++
++#ifdef CONFIG_PROC_FS
++static struct proc_dir_entry *ipmi_proc_entry;
++#endif
++
++static struct file_operations kcs_fops = {
++ owner:THIS_MODULE,
++ write:kcs_write,
++ ioctl:kcs_ioctl,
++ open:kcs_open,
++ release:kcs_release,
++ read:kcs_read,
++};
++
++static struct miscdevice kcs_miscdev = {
++ IPMI_KCS_MINOR,
++ "ipmi_kcs",
++ &kcs_fops
++};
++
++static struct ipmi_driver_info drv_inf;
++
++/***************/
++
++static long long kcs_llseek(struct file *file, long long offset,
++ int origin)
++{
++ return -ESPIPE;
++}
++
++static ssize_t kcs_write(struct file *file, const char *buf, size_t count,
++ loff_t * ppos)
++{
++ return (-ENOSYS);
++}
++
++static ssize_t kcs_read(struct file *file, char *buf, size_t count,
++ loff_t * ptr)
++{
++ return (-ENOSYS);
++}
++
++static int kcs_ioctl(struct inode *inode,
++ struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ switch (cmd) {
++ case IOCTL_IPMI_XFER:
++ {
++ IPMI_XFER user_buffer;
++ int rc;
++ int response_len = sizeof(user_buffer.response);
++
++ if (!arg)
++ return (-EFAULT);
++ if (copy_from_user
++ ((void *) &user_buffer, (void *) arg,
++ sizeof(IPMI_XFER)))
++ return (-EFAULT);
++ if ((user_buffer.request_len < 2)
++ || (user_buffer.response_len < 3))
++ return (-EINVAL);
++
++ rc = kcs_do_xfer((BMC_REQUEST *) & user_buffer.
++ request, user_buffer.request_len,
++ (BMC_RESPONSE *) & user_buffer.
++ response, &response_len);
++ user_buffer.response_len = response_len;
++ copy_to_user((void *) arg, (void *) &user_buffer,
++ sizeof(IPMI_XFER));
++ return (rc);
++ }
++ case IOCTL_DRIVER_INFO:
++ {
++ struct ipmi_driver_info user_buffer;
++
++ if (!arg)
++ return (-EFAULT);
++ if (copy_from_user
++ ((void *) &user_buffer, (void *) arg,
++ sizeof(user_buffer)))
++ return (-EFAULT);
++ copy_to_user((void *) arg, (void *) &drv_inf,
++ sizeof(drv_inf));
++ return (0);
++ }
++ default:
++ return -EINVAL;
++ }
++ return (0);
++}
++
++static int get_deviceid()
++{
++ unsigned char request_buffer[MAX_BUFFER_SIZE];
++ unsigned char response_buffer[MAX_BUFFER_SIZE];
++ BMC_REQUEST *bmc_req;
++ BMC_RESPONSE *bmc_resp;
++ int rc, response_len;
++
++ memset(&dev_id, 0, sizeof(DEVICE_ID_RESPONSE));
++ memset(request_buffer, 0, sizeof(request_buffer));
++ memset(response_buffer, 0, sizeof(response_buffer));
++ bmc_req = (BMC_REQUEST *) request_buffer;
++ bmc_resp = (BMC_RESPONSE *) response_buffer;
++ response_len = sizeof(response_buffer);
++
++ bmc_req->lun = 0;
++ bmc_req->netfn = APP_REQUEST;
++ bmc_req->cmd = 0x01; /* GET_DEVICE_ID */
++
++#if defined(__ia64__)
++ rc = new_kcs_do_xfer(bmc_req, 2, bmc_resp, &response_len);
++#else
++ rc = old_kcs_do_xfer(bmc_req, 2, bmc_resp, &response_len);
++#endif
++ if (bmc_resp->cc != 0x00) {
++ printk("[IPMI_KCS] get_deviceid() failed (0x%.2x)\n",
++ bmc_resp->cc);
++ return (-EIO);
++ }
++ memcpy(&dev_id, bmc_resp->data, sizeof(DEVICE_ID_RESPONSE));
++ return (0);
++}
++
++static int kcs_open(struct inode *inode, struct file *file)
++{
++ switch (MINOR(inode->i_rdev)) {
++ case IPMI_KCS_MINOR:
++ {
++ MOD_INC_USE_COUNT;
++ kcs_refcnt++;
++ return 0;
++ }
++ default:
++ return -ENODEV;
++ }
++}
++
++static int kcs_release(struct inode *inode, struct file *file)
++{
++ if (MINOR(inode->i_rdev) == IPMI_KCS_MINOR) {
++ kcs_refcnt--;
++ }
++ MOD_DEC_USE_COUNT;
++ return 0;
++}
++
++#ifdef CONFIG_BMC_WDT
++static ssize_t wdt_write(struct file *file, const char *buf, size_t count,
++ loff_t * ppos)
++{
++ /* Can't seek (pwrite) on this device */
++ if (ppos != &file->f_pos)
++ return -ESPIPE;
++
++ /*
++ * Stop and then restart the watchdog timer.
++ */
++ if (count) {
++ if (watchdog_set(WATCHDOG_DISABLE))
++ return -EIO;
++ if (watchdog_set(WATCHDOG_ENABLE))
++ return -EIO;
++ if (watchdog_reset())
++ return -EIO;
++ return 1;
++ }
++ return 0;
++}
++
++static int wdt_ioctl(struct inode *inode,
++ struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ static struct watchdog_info ident = {
++ WDIOF_KEEPALIVEPING, 1, "BMC WDT"
++ };
++
++ switch (cmd) {
++ case WDIOC_GETSUPPORT:
++ if (copy_to_user
++ ((struct watchdog_info *) arg, &ident, sizeof(ident)))
++ return -EFAULT;
++ break;
++
++ case WDIOC_GETSTATUS:
++ if (copy_to_user((int *) arg, &wdt_is_open, sizeof(int)))
++ return -EFAULT;
++ break;
++
++ case WDIOC_KEEPALIVE:
++ if (watchdog_set(WATCHDOG_DISABLE))
++ return -EIO;
++ if (watchdog_set(WATCHDOG_ENABLE))
++ return -EIO;
++ if (watchdog_reset())
++ return -EIO;
++ break;
++
++ default:
++ return -ENOIOCTLCMD;
++ }
++ return 0;
++}
++
++static int watchdog_set(int cmd)
++{
++ unsigned char request_buffer[MAX_BUFFER_SIZE];
++ unsigned char response_buffer[MAX_BUFFER_SIZE];
++ BMC_REQUEST *bmc_req;
++ BMC_RESPONSE *bmc_resp;
++ int rc, response_len;
++ SET_WATCHDOG *set;
++ int fixup = 0;
++
++ memset(request_buffer, 0, sizeof(request_buffer));
++ memset(response_buffer, 0, sizeof(response_buffer));
++ bmc_req = (BMC_REQUEST *) request_buffer;
++ bmc_resp = (BMC_RESPONSE *) response_buffer;
++ response_len = sizeof(response_buffer);
++
++ bmc_req->lun = 0;
++ bmc_req->netfn = APP_REQUEST;
++ bmc_req->cmd = 0x24; /* Set Watchdog Timer */
++
++ set = (SET_WATCHDOG *) bmc_req->data;
++
++ while (1) {
++ set->timer_use = 0x04;
++
++ set->timeout_action = wdt_action & 0x0F;
++ set->pre_irq = (wdt_action >> 4) & 0x0F;
++
++ if (cmd == WATCHDOG_DISABLE) {
++ set->timeout_action = 0x00;
++ set->pre_irq = 0x00;
++ }
++ set->pretimeout_interval = wdt_pre;
++
++ if (fixup) {
++ set->pre_irq = 0x00;
++ set->pretimeout_interval = 0;
++ }
++
++ set->tuefc_biosfrb2 = 0x00;
++ set->tuefc_biospost = 0x0;
++ set->tuefc_osload = 0x00;
++ set->tuefc_smsos = 0x01;
++ set->initial_count = wdt_margin * 10;
++
++ rc = kcs_do_xfer(bmc_req, 2 + sizeof(SET_WATCHDOG),
++ bmc_resp, &response_len);
++
++ if (bmc_resp->cc == 0xcc) {
++ fixup++;
++ if (fixup == 2) {
++ printk
++ ("[IPMI_KCS] Flakey NMI fixup failed\n");
++ return (-EIO);
++ }
++ printk("[IPMI_KCS] Flakey NMI fixup enabled\n");
++ continue;
++ } else if (bmc_resp->cc != 0x00) {
++ printk
++ ("[IPMI_KCS] Set watchdog timer failed (rc = 0x%.2x)\n",
++ bmc_resp->cc);
++ return (-EIO);
++ }
++ break;
++ }
++ return (0);
++}
++
++static int watchdog_reset()
++{
++ unsigned char request_buffer[MAX_BUFFER_SIZE];
++ unsigned char response_buffer[MAX_BUFFER_SIZE];
++ BMC_REQUEST *bmc_req;
++ BMC_RESPONSE *bmc_resp;
++ int rc, response_len;
++
++ memset(request_buffer, 0, sizeof(request_buffer));
++ memset(response_buffer, 0, sizeof(response_buffer));
++ bmc_req = (BMC_REQUEST *) request_buffer;
++ bmc_resp = (BMC_RESPONSE *) response_buffer;
++ response_len = sizeof(response_buffer);
++
++ bmc_req->lun = 0;
++ bmc_req->netfn = APP_REQUEST;
++ bmc_req->cmd = 0x22; /* Reset Watchdog Timer */
++
++ rc = kcs_do_xfer(bmc_req, 2, bmc_resp, &response_len);
++ if (bmc_resp->cc != 0x00) {
++ printk("[IPMI_KCS] Reset Watchdog Timer failed (0x%.2x)\n",
++ bmc_resp->cc);
++ return (-EIO);
++ }
++ return (0);
++}
++
++static int wdt_open(struct inode *inode, struct file *file)
++{
++ switch (MINOR(inode->i_rdev)) {
++ case WATCHDOG_MINOR:
++ if (wdt_is_open)
++ return -EBUSY;
++
++ MOD_INC_USE_COUNT;
++ /*
++ * Activate
++ */
++ wdt_is_open = 1;
++ if (watchdog_reset())
++ return -EIO;
++ return 0;
++ default:
++ return -ENODEV;
++ }
++}
++
++static int wdt_release(struct inode *inode, struct file *file)
++{
++ lock_kernel();
++ if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
++#ifndef CONFIG_WATCHDOG_NOWAYOUT
++ if (watchdog_set(WATCHDOG_DISABLE))
++ return -EIO;
++#endif
++ wdt_is_open = 0;
++ MOD_DEC_USE_COUNT;
++ }
++ unlock_kernel();
++ return 0;
++}
++
++/*
++ * Notifier for system down
++ */
++
++static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
++ void *unused)
++{
++ if (code == SYS_DOWN || code == SYS_HALT) {
++ /* Turn the timer off */
++ watchdog_set(WATCHDOG_DISABLE);
++ }
++ return NOTIFY_DONE;
++}
++
++/*
++ * The BMC needs to learn about soft shutdowns in order to
++ * turn the watchdog timer off.
++ */
++
++static struct notifier_block wdt_notifier = {
++ wdt_notify_sys,
++ NULL,
++ 0
++};
++#endif
++
++#ifdef MODULE
++int init_module(void)
++{
++ return (ipmi_kcs_init());
++}
++
++void cleanup_module(void)
++{
++ printk("[IPMI_KCS] Driver shutting down.\n");
++#ifdef CONFIG_PROC_FS
++ remove_proc_entry("ipmi_kcs", 0);
++#endif
++ misc_deregister(&kcs_miscdev);
++#ifdef CONFIG_BMC_WDT
++ misc_deregister(&wdt_miscdev);
++ unregister_reboot_notifier(&wdt_notifier);
++#endif
++ release_region(KCS_BASE, 16);
++}
++#endif
++
++int ipmi_kcs_init()
++{
++ printk
++ ("IPMI KCS driver (San Mehat nettwerk@valinux.com) v%d.%d at io 0x%x\n",
++ driver_major, driver_minor, KCS_BASE);
++ request_region(KCS_BASE, 16, "ipmi_kcs");
++ if ((inb_p(KCS_STATUS_REG) == 0xFF) &&
++ (inb_p(KCS_DATAIN_REG) == 0xFF)) {
++ printk("--KCS ISA window not present. Driver exiting\n");
++ release_region(KCS_BASE, 16);
++ return (-ENXIO);
++ }
++
++ kcs_stat.tx_good = 0;
++ kcs_stat.tx_bad = 0;
++ memset(&drv_inf, 0, sizeof(drv_inf));
++ strcpy(drv_inf.driver_name, "ipmi_kcs");
++ drv_inf.major_ver = driver_major;
++ drv_inf.minor_ver = driver_minor;
++
++ misc_register(&kcs_miscdev);
++#ifdef CONFIG_BMC_WDT
++ misc_register(&wdt_miscdev);
++ register_reboot_notifier(&wdt_notifier);
++#endif
++ get_deviceid();
++ printk("--BMC version %x.%x, IPMI version %d.%d\n",
++ dev_id.major_firmware_revision,
++ dev_id.minor_firmware_revision,
++ dev_id.ipmi_version_major, dev_id.ipmi_version_minor);
++ if ((dev_id.ipmi_version_major == 0) &&
++ (dev_id.ipmi_version_minor == 9)) {
++ printk("--Using legacy KCS state machine\n");
++ kcs_machine = KCS_LEGACY;
++ drv_inf.flags |= KCS_FLAG_LEGACY;
++ } else {
++ printk("--Using new KCS state machine\n");
++ kcs_machine = KCS_NEW;
++ }
++ if (!pci_present()) {
++ printk
++ ("--PCIBIOS not present. Unable to determine chipset vendor\n");
++ drv_inf.flags |= KCS_FLAG_BLINKY;
++ } else {
++ int pci_index = 0;
++ unsigned char pci_bus, pci_device_fn;
++ unsigned short vendor, device;
++
++ for (; pci_index < 0xff; pci_index++) {
++ if (pcibios_find_class(PCI_CLASS_BRIDGE_HOST << 8,
++ pci_index,
++ &pci_bus,
++ &pci_device_fn) !=
++ PCIBIOS_SUCCESSFUL) {
++ break;
++ }
++ pcibios_read_config_word(pci_bus, pci_device_fn,
++ PCI_VENDOR_ID, &vendor);
++ pcibios_read_config_word(pci_bus, pci_device_fn,
++ PCI_DEVICE_ID, &device);
++ drv_inf.mb_chipset_vendor = vendor;
++ drv_inf.mb_chipset_device = device;
++ printk
++ ("--Motherboard Chipset vendor 0x%.4x, device 0x%.4x\n",
++ vendor, device);
++ if ((vendor == 0x8086) && (device == 0x71a0)) {
++ drv_inf.flags |= KCS_FLAG_BLINKY;
++ }
++ }
++ }
++ if (drv_inf.flags & KCS_FLAG_BLINKY) {
++ printk("--Intel Lancewood features enabled\n");
++ } else
++ printk("--No vendor specific features enabled\n");
++#ifdef CONFIG_PROC_FS
++ if (!(ipmi_proc_entry = create_proc_entry("ipmi_kcs", 0, 0)))
++ printk(KERN_ERR,
++ "--ERROR: Unable to register /proc/ipmi_kcs\n");
++ else
++ ipmi_proc_entry->read_proc = ipmi_get_info;
++
++#endif
++ return (0);
++}
++
++static int kcs_do_xfer(BMC_REQUEST * request,
++ int request_len,
++ BMC_RESPONSE * response, int *response_len)
++{
++ int rc = 0;
++
++ down(&kcs_sem);
++ switch (kcs_machine) {
++ case KCS_LEGACY:
++ {
++ rc = old_kcs_do_xfer(request, request_len,
++ response, response_len);
++ break;
++ }
++ case KCS_NEW:
++ {
++ rc = new_kcs_do_xfer(request, request_len,
++ response, response_len);
++ break;
++ }
++ default:
++ {
++ printk
++ ("[IPMI_KCS] Undefined or bad KCS state machine selected (%d)\n",
++ kcs_machine);
++ get_deviceid();
++ if ((dev_id.ipmi_version_major == 0) &&
++ (dev_id.ipmi_version_minor == 9)) {
++ printk
++ ("Recalibrated to use legacy KCS state machine\n");
++ kcs_machine = KCS_LEGACY;
++ } else {
++ printk
++ ("Recalibrated to use new KCS state machine\n");
++ kcs_machine = KCS_NEW;
++ }
++ rc = -EAGAIN;
++ break;
++ }
++ }
++ if (rc == 0)
++ kcs_stat.tx_good++;
++ else
++ kcs_stat.tx_bad++;
++ up(&kcs_sem);
++ return (rc);
++}
++
++static int new_kcs_do_xfer(BMC_REQUEST * request,
++ int request_len,
++ BMC_RESPONSE * response, int *response_len)
++{
++ unsigned char *xmit_buffer, *recv_buffer;
++ int i = 0, rc = 0, state = SEND_INIT, bad = 0;
++
++ xmit_buffer = (unsigned char *) request;
++ recv_buffer = (unsigned char *) response;
++
++ while (1) {
++ if (state == END)
++ break;
++ else if (bad > 2) {
++ printk
++ ("[IPMI_KCS] Maximum retries exceeded. Aborting transfer\n");
++ rc = -EIO;
++ break;
++ }
++ switch (state) {
++ case SEND_INIT:
++ {
++ i = 0;
++ state = SEND_START;
++ wait_while_ibf();
++ if (clear_obf() != 0) {
++ state = ERROR;
++ break;
++ }
++ }
++ case SEND_START:
++ {
++ state = SEND_NEXT;
++ write_kcs_cmd(WRITE_START);
++ wait_while_ibf();
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ }
++ case SEND_NEXT:
++ {
++ if (i == (request_len - 1)) {
++ state = SEND_END;
++ break;
++ }
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ write_kcs_data(xmit_buffer[i++]);
++ wait_while_ibf();
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ if (clear_obf() != 0) {
++ state = ERROR;
++ break;
++ }
++ break;
++ }
++ case SEND_END:
++ {
++ write_kcs_cmd(WRITE_END);
++ wait_while_ibf();
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ if (clear_obf() != 0) {
++ state = ERROR;
++ break;
++ }
++ write_kcs_data(xmit_buffer[i++]);
++ wait_while_ibf();
++ state = RECV_START;
++ }
++ case RECV_START:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_WRITE_STATE:
++ case KCS_IDLE_STATE:
++ {
++ mdelay(BMC_RESPONSE_DELAY);
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ i = 0;
++ memset(recv_buffer, 0,
++ *response_len);
++ state = RECV_INIT;
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_INIT:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ case KCS_WRITE_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_IDLE_STATE:
++ {
++ state = RECV_END;
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ if (is_obf_set())
++ state = RECV_NEXT;
++ else
++ mdelay(1);
++ break;
++ }
++ default:
++ {
++ mdelay(1);
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_NEXT:
++ {
++ if (i >= *response_len) {
++ rc = -EOVERFLOW;
++ state = ERROR;
++ break;
++ }
++ recv_buffer[i++] = read_kcs_data();
++ write_kcs_data(KCS_READ);
++ wait_while_ibf();
++ state = RECV_INIT2;
++ break;
++ }
++ case RECV_INIT2:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ case KCS_WRITE_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_IDLE_STATE:
++ {
++ if (wait_until_obf() == 0) {
++ clear_obf();
++ state = RECV_END;
++ break;
++ } else {
++ state = ERROR;
++ break;
++ }
++ }
++ case KCS_READ_STATE:
++ {
++ if (wait_until_obf() == 0)
++ state = RECV_NEXT;
++ else
++ state = ERROR;
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_END:
++ {
++ if ((i < MIN_BMC_RESPONSE_SIZE) ||
++ (response->netfn !=
++ (request->netfn | 0x01))
++ || (response->cmd != request->cmd)) {
++ mdelay(BMC_RETRY_DELAY);
++ bad++;
++ state = SEND_INIT;
++ printk
++ ("[IPMI_KCS] Request/Response CMD/NETFN mismatch error\n");
++
++ printk
++ (" RQcmd/RQnetfn=0x%x/0x%x,RScmd/RSnetfn=0x%x/0x%x\n",
++ request->cmd, request->netfn,
++ response->cmd,
++ response->netfn);
++ break;
++ }
++
++ *response_len = i;
++ rc = 0;
++ state = END;
++ break;
++ }
++ case ERROR:
++ default:
++ {
++ printk
++ ("[IPMI_KCS] BMC in bad state. Retrying transfer\n");
++ mdelay(BMC_RETRY_DELAY);
++ bad++;
++ state = SEND_INIT;
++ break;
++ }
++ }
++ }
++ return (rc);
++}
++
++static int old_kcs_do_xfer(BMC_REQUEST * request,
++ int request_len,
++ BMC_RESPONSE * response, int *response_len)
++{
++ unsigned char *xmit_buffer, *recv_buffer;
++ int i = 0, rc = 0, state = SEND_INIT, bad = 0;
++
++ xmit_buffer = (unsigned char *) request;
++ recv_buffer = (unsigned char *) response;
++
++ while (1) {
++ if (state == END)
++ break;
++ else if (bad > 2) {
++ printk
++ ("[IPMI_KCS] Maximum retries exceeded. Aborting transfer\n");
++ rc = -EIO;
++ break;
++ }
++ switch (state) {
++ case SEND_INIT:
++ {
++ i = 0;
++ state = SEND_START;
++ wait_while_ibf();
++ }
++ case SEND_START:
++ {
++ state = SEND_NEXT;
++ write_kcs_cmd(WRITE_START);
++ wait_while_ibf();
++ }
++ case SEND_NEXT:
++ {
++ if (i == (request_len - 1)) {
++ state = SEND_END;
++ break;
++ }
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ write_kcs_data(xmit_buffer[i++]);
++ wait_while_ibf();
++ break;
++ }
++ case SEND_END:
++ {
++ wait_while_ibf();
++ write_kcs_cmd(WRITE_END);
++ wait_while_ibf();
++ if (get_kcs_state() != KCS_WRITE_STATE) {
++ state = ERROR;
++ break;
++ }
++ write_kcs_data(xmit_buffer[i++]);
++ wait_while_ibf();
++ state = RECV_START;
++ }
++ case RECV_START:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_WRITE_STATE:
++ case KCS_IDLE_STATE:
++ {
++ mdelay(BMC_RESPONSE_DELAY);
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ i = 0;
++ memset(recv_buffer, 0,
++ *response_len);
++ state = RECV_INIT;
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_INIT:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ case KCS_WRITE_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_IDLE_STATE:
++ {
++ state = RECV_END;
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ if (is_obf_set())
++ state = RECV_NEXT;
++ else
++ mdelay(1);
++ break;
++ }
++ default:
++ {
++ mdelay(1);
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_NEXT:
++ {
++ if (i >= *response_len) {
++ rc = -EOVERFLOW;
++ state = ERROR;
++ break;
++ }
++ recv_buffer[i++] = read_kcs_data();
++ wait_while_ibf();
++ write_kcs_data(KCS_READ);
++ state = RECV_INIT2;
++ break;
++ }
++ case RECV_INIT2:
++ {
++ switch (get_kcs_state()) {
++ case KCS_ERROR_STATE:
++ case KCS_WRITE_STATE:
++ {
++ state = ERROR;
++ break;
++ }
++ case KCS_IDLE_STATE:
++ {
++ state = RECV_END;
++ break;
++ }
++ case KCS_READ_STATE:
++ {
++ if (is_obf_set())
++ state = RECV_NEXT;
++ break;
++ }
++ }
++ break;
++ }
++ case RECV_END:
++ {
++ if ((i < MIN_BMC_RESPONSE_SIZE) ||
++ (response->netfn !=
++ (request->netfn | 0x01))
++ || (response->cmd != request->cmd)) {
++ mdelay(BMC_RETRY_DELAY);
++ bad++;
++ state = SEND_INIT;
++ printk
++ ("[IPMI_KCS] Request/Response CMD/NETFN mismatch error\n");
++
++ printk
++ (" RQcmd/RQnetfn=0x%x/0x%x,RScmd/RSnetfn=0x%x/0x%x\n",
++ request->cmd, request->netfn,
++ response->cmd,
++ response->netfn);
++ break;
++ }
++
++ *response_len = i;
++ rc = 0;
++ state = END;
++ break;
++ }
++ case ERROR:
++ default:
++ {
++ printk
++ ("[IPMI_KCS] BMC in bad state. Retrying transfer\n");
++ mdelay(BMC_RETRY_DELAY);
++ bad++;
++ state = SEND_INIT;
++ break;
++ }
++ }
++ }
++ return (rc);
++}
++
++#ifdef CONFIG_PROC_FS
++int ipmi_get_info(char *buf, char **start, off_t fpos, int length,
++ int *eof, void *unused)
++{
++ char *p;
++
++ if (get_deviceid() != 0) {
++ printk("[IPMI_KCS] Unable to get device ID\n");
++ memset(&dev_id, 0, sizeof(dev_id));
++ }
++
++ p = buf;
++ p += sprintf(p, "Driver Version\t: %d.%d\n",
++ driver_major, driver_minor);
++ p += sprintf(p, "BMC Version\t: %x.%x\n",
++ dev_id.major_firmware_revision,
++ dev_id.minor_firmware_revision);
++ p += sprintf(p, "IPMI Version\t: %d.%d\n",
++ dev_id.ipmi_version_major, dev_id.ipmi_version_minor);
++ p += sprintf(p, "\nTotal Good Transactions\t: %d\n",
++ kcs_stat.tx_good);
++ p += sprintf(p, "Total Bad Transactions\t: %d\n", kcs_stat.tx_bad);
++
++ return p - buf;
++}
++#endif
++
++/*
++ * kcs chip mashing stuff
++ */
++static int wait_while_ibf()
++{
++ unsigned char status_byte;
++
++ status_byte = inb_p(KCS_STATUS_REG);
++ if ((status_byte & KCS_IBF) == 0)
++ return (0);
++ mdelay(KCS_READY_DELAY);
++ status_byte = inb_p(KCS_STATUS_REG);
++ if (status_byte & KCS_IBF)
++ return (-1);
++ return (0);
++}
++
++static int wait_until_obf()
++{
++ int retries = 0;
++
++ while (retries < 2) {
++ if (is_obf_set())
++ return (0);
++ mdelay(KCS_READY_DELAY);
++ retries++;
++ }
++ return (-ETIMEDOUT);
++}
++
++static unsigned char get_kcs_state()
++{
++ unsigned char cs;
++
++ cs = inb_p(KCS_STATUS_REG);
++ return (cs & KCS_STATE_MASK);
++}
++
++static unsigned char read_kcs_data()
++{
++ unsigned char data;
++
++ data = inb_p(KCS_DATAOUT_REG);
++ return (data);
++}
++
++static void write_kcs_data(unsigned char data)
++{
++ outb_p(data, KCS_DATAIN_REG);
++}
++
++static void write_kcs_cmd(unsigned char cmd)
++{
++ outb_p(cmd, KCS_COMMAND_REG);
++}
++
++static int is_obf_set()
++{
++ unsigned char cs;
++
++ cs = inb_p(KCS_STATUS_REG);
++ return ((cs & KCS_OBF) == KCS_OBF);
++}
++
++static int clear_obf()
++{
++ read_kcs_data();
++ return (0);
++}
+--- /dev/null Fri Mar 23 23:37:44 2001
++++ linux-bmc/drivers/char/ipmi_kcs.h Tue Oct 30 17:18:07 2001
+@@ -0,0 +1,171 @@
++/*
++ * Intelligent Platform Management Interface driver for Linux 2.x
++ *
++ * (c) Copyright 1999 San Mehat & VA Linux Systems
++ * 1382 Bordeaux Dr.
++ * Sunnyvale, California
++ * 94089
++ *
++ * http://www.valinux.com
++ *
++ * This driver is provided under the GNU public license, incorporated
++ * herein by reference. The driver is provided without warranty or
++ * support.
++ *
++ *
++ */
++
++#include <linux/config.h>
++
++#define KCS_LEGACY 1
++#define KCS_NEW 2
++
++#define KCS_READY_DELAY 5
++#define BMC_RESPONSE_DELAY 5
++#define BMC_RETRY_DELAY 60
++
++#if defined(__ia64__)
++#define KCS_BASE 0x8a2
++#else
++#define KCS_BASE 0xca2
++#endif
++#define KCS_STATUS_REG (KCS_BASE + 1)
++#define KCS_COMMAND_REG (KCS_BASE + 1)
++#define KCS_DATAIN_REG (KCS_BASE + 0)
++#define KCS_DATAOUT_REG (KCS_BASE + 0)
++
++/* State bits based on S1 & S0 below */
++#define KCS_STATE_MASK 0xC0
++#define KCS_IDLE_STATE 0x00
++#define KCS_READ_STATE 0x40
++#define KCS_WRITE_STATE 0x80
++#define KCS_ERROR_STATE 0xC0
++
++#define KCS_IBF 0x02
++#define KCS_OBF 0x01
++#define KCS_SMS_ATN 0x04
++
++#define SEND_INIT 1
++#define SEND_START 2
++#define SEND_NEXT 3
++#define SEND_END 4
++#define RECV_START 5
++#define RECV_INIT 6
++#define RECV_NEXT 7
++#define RECV_INIT2 8
++#define RECV_END 9
++#define END 10
++#define ERROR 0
++
++/* SMS Transfer Stream Control Codes */
++#define GET_STATUS_ABORT 0x60
++#define WRITE_START 0x61
++#define WRITE_END 0x62
++#define KCS_READ 0x68
++
++#define MAX_INVALID_RESPONSE_COUNT 2
++#define MIN_BMC_RESPONSE_SIZE 3
++#define MAX_IMB_PACKET_SIZE 33
++#define MAX_BMC_RESPONSE_SIZE (MIN_BMC_RESPONSE_SIZE + MAX_IMB_PACKET_SIZE)
++#define MAX_XFER_LENGTH (MAX_IMB_PACKET_SIZE * 2)
++
++#define MAX_BUFFER_SIZE 64
++
++typedef struct bmc_response
++ {
++ unsigned char lun :2;
++ unsigned char netfn :6;
++
++ unsigned char cmd;
++ unsigned char cc;
++ unsigned char data[1];
++ }BMC_RESPONSE;
++
++typedef struct bmc_request
++ {
++ unsigned char lun :2;
++ unsigned char netfn :6;
++
++ unsigned char cmd;
++ unsigned char data[1];
++ }BMC_REQUEST;
++
++/* GET_DEVICE_ID RESPONSE */
++typedef struct device_id_response
++ {
++ unsigned char device_id;
++
++ unsigned char device_revision :4;
++ unsigned char reserved :3;
++ unsigned char provides_sdr :1;
++
++ unsigned char major_firmware_revision :7;
++ #define NORMAL_OPERATION 0
++ #define DEVICE_BUSY 1
++ unsigned char device_available :1;
++
++ unsigned char minor_firmware_revision;
++
++ unsigned char ipmi_version_major :4;
++ unsigned char ipmi_version_minor :4;
++
++ unsigned char supports_sensor_device :1;
++ unsigned char supports_sdr_device :1;
++ unsigned char supports_sel_device :1;
++ unsigned char supports_fru_device :1;
++ unsigned char supports_ipmb_receiver :1;
++ unsigned char supports_ipmb_generator :1;
++ unsigned char supports_bridge :1;
++ unsigned char supports_chassis_device :1;
++
++ unsigned char manufacturer_id1;
++ unsigned char manufacturer_id2;
++ unsigned char manufacturer_id3;
++
++ unsigned short product_id;
++ } DEVICE_ID_RESPONSE;
++
++typedef struct set_watchdog
++ {
++ unsigned char timer_use :3;
++ unsigned char res1 :4;
++ unsigned char dontlog :1;
++
++ unsigned char timeout_action :3;
++ unsigned char res2 :1;
++ unsigned char pre_irq :3;
++ unsigned char res3 :1;
++
++ unsigned char pretimeout_interval;
++
++ unsigned char tuefc_res1 :1;
++ unsigned char tuefc_biosfrb2 :1;
++ unsigned char tuefc_biospost :1;
++ unsigned char tuefc_osload :1;
++ unsigned char tuefc_smsos :1;
++ unsigned char tuefc_oem :1;
++ unsigned char tuefc_res2 :1;
++ unsigned char tuefc_res3 :1;
++
++ unsigned short initial_count;
++ } SET_WATCHDOG;
++
++typedef struct get_watchdog_response
++ {
++ unsigned char timer_use :3;
++ unsigned char res1 :3;
++ unsigned char timer_status :1;
++ unsigned char sel_log :1;
++
++ unsigned char timeout_act :3;
++ unsigned char res2 :1;
++ unsigned char pre_irq_act :3;
++ unsigned char res3 :1;
++
++ unsigned char pre_timeout __attribute__ ((packed));
++
++ unsigned char timer_use_xp __attribute__ ((packed));
++
++ unsigned short init_count __attribute__ ((packed));
++ unsigned short current_count __attribute__ ((packed));
++ } GET_WATCHDOG_RESPONSE;
+--- /dev/null Fri Mar 23 23:37:44 2001
++++ linux-bmc/include/linux/ipmi_ioctls.h Tue Oct 30 17:18:07 2001
+@@ -0,0 +1,152 @@
++/*
++ * Intelligent Platform Management Interface driver for Linux 2.x
++ *
++ * (c) Copyright 1999 San Mehat & VA Linux Systems
++ * 1382 Bordeaux Dr.
++ * Sunnyvale, California
++ * 94089
++ *
++ * http://www.valinux.com
++ *
++ * This driver is provided under the GNU public license, incorporated
++ * herein by reference. The driver is provided without warranty or
++ * support.
++ *
++ * IOCTL definitions for IPMI drivers
++ */
++
++/*
++ * Note: The following macros should be used on the IPMI_XFER structure.
++ * DO NOT try to muck with this structure directly.. use the macros
++ * to ensure future compatibility:
++ *
++ * INIT_XFER(IPMI_XFER *);
++ * -- Zero out a IPMI_XFER structure and initialize it for use
++ *
++ * SET_REQUEST_LUN(IPMI_XFER *, unsigned char lun);
++ * -- Set the request packet logical unit
++ *
++ * SET_REQUEST_NETFN(IPMI_XFER *, unsigned char netfn);
++ * -- Set the request packet network function code
++ *
++ * SET_REQUEST_CMD(IPMI_XFER *, unsigned char cmd);
++ * -- Set the request packet IPMI command code
++ *
++ * SET_REQUEST_DATA(IPMI_XFER *, unsigned char *data, int length);
++ * -- Set the request packet optional argument data field
++ *
++ * GET_RESPONSE_LUN(IPMI_XFER *, unsigned char lun);
++ * -- Get the response packet logical unit
++ *
++ * GET_RESPONSE_NETFN(IPMI_XFER *, unsigned char netfn);
++ * -- Get the response packet network function code
++ *
++ * GET_RESPONSE_CMD(IPMI_XFER *, unsigned char cmd);
++ * -- Get the response packet command
++ *
++ * GET_RESPONSE_CC(IPMI_XFER *, unsigned char cc);
++ * -- Get the response packet completion code
++ *
++ * GET_RESPONSE_DATA_LENGTH(IPMI_XFER *, int len);
++ * -- Get the response packet data length
++ *
++ * GET_RESPONSE_DATA(IPMI_XFER *, unsigned char *buffer);
++ * -- Copy the response packet data into local buffer
++ */
++
++#ifndef _IPMI_IOCTLS_H
++#define _IPMI_IOCTLS_H
++
++#define IOCTL_IPMI_XFER 0x01
++#define IOCTL_DRIVER_INFO 0x02
++
++typedef struct ipmi_xfer
++ {
++ unsigned char request[64];
++ unsigned char response[64];
++ int request_len;
++ int response_len;
++ } IPMI_XFER;
++
++struct ipmi_driver_info
++ {
++ char driver_name[64]; /* Name of the driver */
++ int major_ver;
++ int minor_ver;
++ unsigned short mb_chipset_vendor; /* PCI host bridge vendor tag */
++ unsigned short mb_chipset_device; /* PCI host bridge vendor device id */
++ unsigned int flags; /* driver specific flags */
++ unsigned int reserved;
++ };
++
++/* flags definitions for the 'ipmi_kcs' driver */
++#define KCS_FLAG_BLINKY 0x01 /* Set if blinky works (only on Intel L440GX) */
++#define KCS_FLAG_LEGACY 0x02 /* Set if using legacy KCS interface ( < IPMI 1.0) */
++
++#define INIT_XFER(_xferp) \
++ memset(_xferp, 0, sizeof(IPMI_XFER)); \
++ _xferp->request_len = 2; \
++ _xferp->response_len = sizeof(_xferp->response);
++
++#define SET_REQUEST_LUN(_xferp, _lun) \
++ { \
++ unsigned char _netfn_copy; \
++ \
++ _netfn_copy = (_xferp->request[0] & 0xFC); \
++ _xferp->request[0] = _lun; \
++ _xferp->request[0]|= _netfn_copy; \
++ }
++
++#define SET_REQUEST_NETFN(_xferp, netfn) \
++ { \
++ unsigned char __lun_copy; \
++ \
++ __lun_copy = (_xferp->request[0] & 0x3); \
++ _xferp->request[0] = (netfn << 2); \
++ _xferp->request[0]|= __lun_copy; \
++ }
++
++#define SET_REQUEST_CMD(_xferp, _cmd) \
++ _xferp->request[1] = _cmd;
++
++#define SET_REQUEST_DATA(_xferp, datap, _len) \
++ { \
++ memcpy(&_xferp->request[2], datap, _len); \
++ _xferp->request_len = (_len + 2); \
++ }
++
++#define GET_RESPONSE_LUN(_xferp, _lun) \
++ _lun = (_xferp->response[0] & 0x3);
++
++#define GET_RESPONSE_NETFN(_xferp, netfn) \
++ netfn = ((_xferp->response[0] & 0xFC) >> 2);
++
++#define GET_RESPONSE_CMD(_xferp, _cmd) \
++ _cmd = _xferp->response[1];
++
++#define GET_RESPONSE_CC(_xferp, cc) \
++ cc = _xferp->response[2];
++
++#define GET_RESPONSE_DATA_LENGTH(_xferp, _len) \
++ _len = (_xferp->response_len - 3);
++
++#define GET_RESPONSE_DATA(_xferp, datap) \
++ memcpy(datap, &_xferp->response[3], (_xferp->response_len -3));
++
++/*
++ * The Netfn codes
++ */
++#define CHASSIS_REQUEST 0x00
++#define CHASSIS_RESPONSE 0x01
++#define BRIDGE_REQUEST 0x02
++#define BRIDGE_RESPONSE 0x03
++#define SENSOR_REQUEST 0x04
++#define SENSOR_RESPONSE 0x05
++#define APP_REQUEST 0x06
++#define APP_RESPONSE 0x07
++#define FIRMWARE_REQUEST 0x08
++#define FIRMWARE_RESPONSE 0x09
++#define STORAGE_REQUEST 0x0A
++#define STORAGE_RESPONSE 0x0B
++
++#endif
diff --git a/kern/linux-ipmi-2.4.20-v17.diff b/kern/linux-ipmi-2.4.20-v17.diff
new file mode 100644
index 0000000..a919310
--- /dev/null
+++ b/kern/linux-ipmi-2.4.20-v17.diff
@@ -0,0 +1,6647 @@
+diff -urN linux.orig/Documentation/Configure.help linux/Documentation/Configure.help
+--- linux.orig/Documentation/Configure.help Fri Dec 6 09:11:24 2002
++++ linux/Documentation/Configure.help Fri Dec 6 09:12:27 2002
+@@ -26242,6 +26242,31 @@
+
+ If unsure, say N.
+
++IPMI top-level message handler
++CONFIG_IPMI_HANDLER
++ This enables the central IPMI message handler, required for IPMI
++ to work. Note that you must have this enabled to do any other IPMI
++ things. See IPMI.txt for more details.
++
++Generate a panic event to all BMCs on a panic
++CONFIG_IPMI_PANIC_EVENT
++ When a panic occurs, this will cause the IPMI message handler to
++ generate an IPMI event describing the panic to each interface
++ registered with the message handler.
++
++Device interface for IPMI
++CONFIG_IPMI_DEVICE_INTERFACE
++ This provides an IOCTL interface to the IPMI message handler so
++ userland processes may use IPMI. It supports poll() and select().
++
++IPMI KCS handler
++CONFIG_IPMI_KCS
++ Provides a driver for a KCS-style interface to a BMC.
++
++IPMI Watchdog Timer
++CONFIG_IPMI_WATCHDOG
++ This enables the IPMI watchdog timer.
++
+ #
+ # A couple of things I keep forgetting:
+ # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
+diff -urN linux.orig/Documentation/IPMI.txt linux/Documentation/IPMI.txt
+--- linux.orig/Documentation/IPMI.txt Wed Dec 31 18:00:00 1969
++++ linux/Documentation/IPMI.txt Tue Dec 31 13:00:01 2002
+@@ -0,0 +1,352 @@
++
++ The Linux IPMI Driver
++ ---------------------
++ Corey Minyard
++ <minyard@mvista.com>
++ <minyard@acm.org>
++
++This document describes how to use the IPMI driver for Linux. If you
++are not familiar with IPMI itself, see the web site at
++http://www.intel.com/design/servers/ipmi/index.htm. IPMI is a big
++subject and I can't cover it all here!
++
++Basic Design
++------------
++
++The Linux IPMI driver is designed to be very modular and flexible, you
++only need to take the pieces you need and you can use it in many
++different ways. Because of that, it's broken into many chunks of
++code. These chunks are:
++
++ipmi_msghandler - This is the central piece of software for the IPMI
++system. It handles all messages, message timing, and responses. The
++IPMI users tie into this, and the IPMI physical interfaces (called
++System Management Interfaces, or SMIs) also tie in here. This
++provides the kernelland interface for IPMI, but does not provide an
++interface for use by application processes.
++
++ipmi_devintf - This provides a userland IOCTL interface for the IPMI
++driver, each open file for this device ties in to the message handler
++as an IPMI user.
++
++ipmi_kcs_drv - A driver for the KCS SMI. Most system have a KCS
++interface for IPMI.
++
++
++Much documentation for the interface is in the include files. The
++IPMI include files are:
++
++ipmi.h - Contains the user interface and IOCTL interface for IPMI.
++
++ipmi_smi.h - Contains the interface for SMI drivers to use.
++
++ipmi_msgdefs.h - General definitions for base IPMI messaging.
++
++
++Addressing
++----------
++
++The IPMI addressing works much like IP addresses, you have an overlay
++to handle the different address types. The overlay is:
++
++ struct ipmi_addr
++ {
++ int addr_type;
++ short channel;
++ char data[IPMI_MAX_ADDR_SIZE];
++ };
++
++The addr_type determines what the address really is. The driver
++currently understands two different types of addresses.
++
++"System Interface" addresses are defined as:
++
++ struct ipmi_system_interface_addr
++ {
++ int addr_type;
++ short channel;
++ };
++
++and the type is IPMI_SYSTEM_INTERFACE_ADDR_TYPE. This is used for talking
++straight to the BMC on the current card. The channel must be
++IPMI_BMC_CHANNEL.
++
++Messages that are destined to go out on the IPMB bus use the
++IPMI_IPMB_ADDR_TYPE address type. The format is
++
++ struct ipmi_ipmb_addr
++ {
++ int addr_type;
++ short channel;
++ unsigned char slave_addr;
++ unsigned char lun;
++ };
++
++The "channel" here is generally zero, but some devices support more
++than one channel, it corresponds to the channel as defined in the IPMI
++spec.
++
++
++Messages
++--------
++
++Messages are defined as:
++
++struct ipmi_msg
++{
++ unsigned char netfn;
++ unsigned char lun;
++ unsigned char cmd;
++ unsigned char *data;
++ int data_len;
++};
++
++The driver takes care of adding/stripping the header information. The
++data portion is just the data to be send (do NOT put addressing info
++here) or the response. Note that the completion code of a response is
++the first item in "data", it is not stripped out because that is how
++all the messages are defined in the spec (and thus makes counting the
++offsets a little easier :-).
++
++When using the IOCTL interface from userland, you must provide a block
++of data for "data", fill it, and set data_len to the length of the
++block of data, even when receiving messages. Otherwise the driver
++will have no place to put the message.
++
++Messages coming up from the message handler in kernelland will come in
++as:
++
++ struct ipmi_recv_msg
++ {
++ struct list_head link;
++
++ /* The type of message as defined in the "Receive Types"
++ defines above. */
++ int recv_type;
++
++ ipmi_user_t *user;
++ struct ipmi_addr addr;
++ long msgid;
++ struct ipmi_msg msg;
++
++ /* Call this when done with the message. It will presumably free
++ the message and do any other necessary cleanup. */
++ void (*done)(struct ipmi_recv_msg *msg);
++
++ /* Place-holder for the data, don't make any assumptions about
++ the size or existence of this, since it may change. */
++ unsigned char msg_data[IPMI_MAX_MSG_LENGTH];
++ };
++
++You should look at the receive type and handle the message
++appropriately.
++
++
++The Upper Layer Interface (Message Handler)
++-------------------------------------------
++
++The upper layer of the interface provides the users with a consistent
++view of the IPMI interfaces. It allows multiple SMI interfaces to be
++addressed (because some boards actually have multiple BMCs on them)
++and the user should not have to care what type of SMI is below them.
++
++
++Creating the User
++
++To user the message handler, you must first create a user using
++ipmi_create_user. The interface number specifies which SMI you want
++to connect to, and you must supply callback functions to be called
++when data comes in. The callback function can run at interrupt level,
++so be careful using the callbacks. This also allows to you pass in a
++piece of data, the handler_data, that will be passed back to you on
++all calls.
++
++Once you are done, call ipmi_destroy_user() to get rid of the user.
++
++From userland, opening the device automatically creates a user, and
++closing the device automatically destroys the user.
++
++
++Messaging
++
++To send a message from kernel-land, the ipmi_request() call does
++pretty much all message handling. Most of the parameter are
++self-explanatory. However, it takes a "msgid" parameter. This is NOT
++the sequence number of messages. It is simply a long value that is
++passed back when the response for the message is returned. You may
++use it for anything you like.
++
++Responses come back in the function pointed to by the ipmi_recv_hndl
++field of the "handler" that you passed in to ipmi_create_user().
++Remember again, these may be running at interrupt level. Remember to
++look at the receive type, too.
++
++From userland, you fill out an ipmi_req_t structure and use the
++IPMICTL_SEND_COMMAND ioctl. For incoming stuff, you can use select()
++or poll() to wait for messages to come in. However, you cannot use
++read() to get them, you must call the IPMICTL_RECEIVE_MSG with the
++ipmi_recv_t structure to actually get the message. Remember that you
++must supply a pointer to a block of data in the msg.data field, and
++you must fill in the msg.data_len field with the size of the data.
++This gives the receiver a place to actually put the message.
++
++If the message cannot fit into the data you provide, you will get an
++EMSGSIZE error and the driver will leave the data in the receive
++queue. If you want to get it and have it truncate the message, us
++the IPMICTL_RECEIVE_MSG_TRUNC ioctl.
++
++When you send a command (which is defined by the lowest-order bit of
++the netfn per the IPMI spec) on the IPMB bus, the driver will
++automatically assign the sequence number to the command and save the
++command. If the response is not receive in the IPMI-specified 5
++seconds, it will generate a response automatically saying the command
++timed out. If an unsolicited response comes in (if it was after 5
++seconds, for instance), that response will be ignored.
++
++In kernelland, after you receive a message and are done with it, you
++MUST call ipmi_free_recv_msg() on it, or you will leak messages. Note
++that you should NEVER mess with the "done" field of a message, that is
++required to properly clean up the message.
++
++Note that when sending, there is an ipmi_request_supply_msgs() call
++that lets you supply the smi and receive message. This is useful for
++pieces of code that need to work even if the system is out of buffers
++(the watchdog timer uses this, for instance). You supply your own
++buffer and own free routines. This is not recommended for normal use,
++though, since it is tricky to manage your own buffers.
++
++
++Events and Incoming Commands
++
++The driver takes care of polling for IPMI events and receiving
++commands (commands are messages that are not responses, they are
++commands that other things on the IPMB bus have sent you). To receive
++these, you must register for them, they will not automatically be sent
++to you.
++
++To receive events, you must call ipmi_set_gets_events() and set the
++"val" to non-zero. Any events that have been received by the driver
++since startup will immediately be delivered to the first user that
++registers for events. After that, if multiple users are registered
++for events, they will all receive all events that come in.
++
++For receiving commands, you have to individually register commands you
++want to receive. Call ipmi_register_for_cmd() and supply the netfn
++and command name for each command you want to receive. Only one user
++may be registered for each netfn/cmd, but different users may register
++for different commands.
++
++From userland, equivalent IOCTLs are provided to do these functions.
++
++
++The Lower Layer (SMI) Interface
++-------------------------------
++
++As mentioned before, multiple SMI interfaces may be registered to the
++message handler, each of these is assigned an interface number when
++they register with the message handler. They are generally assigned
++in the order they register, although if an SMI unregisters and then
++another one registers, all bets are off.
++
++The ipmi_smi.h defines the interface for SMIs, see that for more
++details.
++
++
++The KCS Driver
++--------------
++
++The KCS driver allows up to 4 KCS interfaces to be configured in the
++system. By default, the driver will register one KCS interface at the
++spec-specified I/O port 0xca2 without interrupts. You can change this
++at module load time (for a module) with:
++
++ insmod ipmi_kcs_drv.o kcs_ports=<port1>,<port2>... kcs_addrs=<addr1>,<addr2>
++ kcs_irqs=<irq1>,<irq2>... kcs_trydefaults=[0|1]
++
++The KCS driver supports two types of interfaces, ports (for I/O port
++based KCS interfaces) and memory addresses (for KCS interfaces in
++memory). The driver will support both of them simultaneously, setting
++the port to zero (or just not specifying it) will allow the memory
++address to be used. The port will override the memory address if it
++is specified and non-zero. kcs_trydefaults sets whether the standard
++IPMI interface at 0xca2 and any interfaces specified by ACPE are
++tried. By default, the driver tries it, set this value to zero to
++turn this off.
++
++When compiled into the kernel, the addresses can be specified on the
++kernel command line as:
++
++ ipmi_kcs=<bmc1>:<irq1>,<bmc2>:<irq2>....,[nodefault]
++
++The <bmcx> values is either "p<port>" or "m<addr>" for port or memory
++addresses. So for instance, a KCS interface at port 0xca2 using
++interrupt 9 and a memory interface at address 0xf9827341 with no
++interrupt would be specified "ipmi_kcs=p0xca2:9,m0xf9827341".
++If you specify zero for in irq or don't specify it, the driver will
++run polled unless the software can detect the interrupt to use in the
++ACPI tables.
++
++By default, the driver will attempt to detect a KCS device at the
++spec-specified 0xca2 address and any address specified by ACPI. If
++you want to turn this off, use the "nodefault" option.
++
++If you have high-res timers compiled into the kernel, the driver will
++use them to provide much better performance. Note that if you do not
++have high-res timers enabled in the kernel and you don't have
++interrupts enabled, the driver will run VERY slowly. Don't blame me,
++the KCS interface sucks.
++
++
++Other Pieces
++------------
++
++Watchdog
++
++A watchdog timer is provided that implements the Linux-standard
++watchdog timer interface. It has three module parameters that can be
++used to control it:
++
++ insmod ipmi_watchdog timeout=<t> pretimeout=<t> action=<action type>
++ preaction=<preaction type> preop=<preop type>
++
++The timeout is the number of seconds to the action, and the pretimeout
++is the amount of seconds before the reset that the pre-timeout panic will
++occur (if pretimeout is zero, then pretimeout will not be enabled).
++
++The action may be "reset", "power_cycle", or "power_off", and
++specifies what to do when the timer times out, and defaults to
++"reset".
++
++The preaction may be "pre_smi" for an indication through the SMI
++interface, "pre_int" for an indication through the SMI with an
++interrupts, and "pre_nmi" for a NMI on a preaction. This is how
++the driver is informed of the pretimeout.
++
++The preop may be set to "preop_none" for no operation on a pretimeout,
++"preop_panic" to set the preoperation to panic, or "preop_give_data"
++to provide data to read from the watchdog device when the pretimeout
++occurs. A "pre_nmi" setting CANNOT be used with "preop_give_data"
++because you can't do data operations from an NMI.
++
++When preop is set to "preop_give_data", one byte comes ready to read
++on the device when the pretimeout occurs. Select and fasync work on
++the device, as well.
++
++When compiled into the kernel, the kernel command line is available
++for configuring the watchdog:
++
++ ipmi_wdog=<timeout>[,<pretimeout>[,<option>[,<options>....]]]
++
++The options are the actions and preaction above (if an option
++controlling the same thing is specified twice, the last is taken). An
++options "start_now" is also there, if included, the watchdog will
++start running immediately when all the drivers are ready, it doesn't
++have to have a user hooked up to start it.
++
++The watchdog will panic and start a 120 second reset timeout if it
++gets a pre-action. During a panic or a reboot, the watchdog will
++start a 120 timer if it is running to make sure the reboot occurs.
++
++Note that if you use the NMI preaction for the watchdog, you MUST
++NOT use nmi watchdog mode 1. If you use the NMI watchdog, you
++must use mode 2.
+diff -urN linux.orig/drivers/char/Config.in linux/drivers/char/Config.in
+--- linux.orig/drivers/char/Config.in Fri Dec 6 09:11:37 2002
++++ linux/drivers/char/Config.in Fri Dec 6 09:12:38 2002
+@@ -190,6 +190,12 @@
+ fi
+ fi
+
++tristate 'IPMI top-level message handler' CONFIG_IPMI_HANDLER
++dep_mbool ' Generate a panic event to all BMCs on a panic' CONFIG_IPMI_PANIC_EVENT $CONFIG_IPMI_HANDLER
++dep_tristate ' Device interface for IPMI' CONFIG_IPMI_DEVICE_INTERFACE $CONFIG_IPMI_HANDLER
++dep_tristate ' IPMI KCS handler' CONFIG_IPMI_KCS $CONFIG_IPMI_HANDLER
++dep_tristate ' IPMI Watchdog Timer' CONFIG_IPMI_WATCHDOG $CONFIG_IPMI_HANDLER
++
+ mainmenu_option next_comment
+ comment 'Watchdog Cards'
+ bool 'Watchdog Timer Support' CONFIG_WATCHDOG
+diff -urN linux.orig/drivers/char/Makefile linux/drivers/char/Makefile
+--- linux.orig/drivers/char/Makefile Fri Dec 6 09:11:37 2002
++++ linux/drivers/char/Makefile Fri Dec 6 09:12:38 2002
+@@ -289,6 +289,11 @@
+ obj-y += mwave/mwave.o
+ endif
+
++subdir-$(CONFIG_IPMI_HANDLER) += ipmi
++ifeq ($(CONFIG_IPMI_HANDLER),y)
++ obj-y += ipmi/ipmi.o
++endif
++
+ include $(TOPDIR)/Rules.make
+
+ fastdep:
+diff -urN linux.orig/drivers/char/ipmi/Makefile linux/drivers/char/ipmi/Makefile
+--- linux.orig/drivers/char/ipmi/Makefile Wed Dec 31 18:00:00 1969
++++ linux/drivers/char/ipmi/Makefile Thu Aug 22 16:58:48 2002
+@@ -0,0 +1,20 @@
++#
++# Makefile for the ipmi drivers.
++#
++
++O_TARGET := ipmi.o
++
++export-objs := ipmi_msghandler.o ipmi_watchdog.o
++
++list-multi := ipmi_kcs_drv.o
++ipmi_kcs_drv-objs := ipmi_kcs_sm.o ipmi_kcs_intf.o
++
++obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o
++obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
++obj-$(CONFIG_IPMI_KCS) += ipmi_kcs_drv.o
++obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
++
++include $(TOPDIR)/Rules.make
++
++ipmi_kcs_drv.o: $(ipmi_kcs_drv-objs)
++ $(LD) -r -o $@ $(ipmi_kcs_drv-objs)
+diff -urN linux.orig/drivers/char/ipmi/ipmi_devintf.c linux/drivers/char/ipmi/ipmi_devintf.c
+--- linux.orig/drivers/char/ipmi/ipmi_devintf.c Wed Dec 31 18:00:00 1969
++++ linux/drivers/char/ipmi/ipmi_devintf.c Mon Nov 18 20:43:45 2002
+@@ -0,0 +1,532 @@
++/*
++ * ipmi_devintf.c
++ *
++ * Linux device interface for the IPMI message handler.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <asm/system.h>
++#include <linux/sched.h>
++#include <linux/poll.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/devfs_fs_kernel.h>
++#include <linux/ipmi.h>
++#include <asm/semaphore.h>
++#include <linux/init.h>
++
++struct ipmi_file_private
++{
++ ipmi_user_t user;
++ spinlock_t recv_msg_lock;
++ struct list_head recv_msgs;
++ struct file *file;
++ struct fasync_struct *fasync_queue;
++ wait_queue_head_t wait;
++ struct semaphore recv_sem;
++};
++
++static void file_receive_handler(struct ipmi_recv_msg *msg,
++ void *handler_data)
++{
++ struct ipmi_file_private *priv = handler_data;
++ int was_empty;
++ unsigned long flags;
++
++ spin_lock_irqsave(&(priv->recv_msg_lock), flags);
++
++ was_empty = list_empty(&(priv->recv_msgs));
++ list_add_tail(&(msg->link), &(priv->recv_msgs));
++
++ if (was_empty) {
++ wake_up_interruptible(&priv->wait);
++ kill_fasync(&priv->fasync_queue, SIGIO, POLL_IN);
++ }
++
++ spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
++}
++
++static unsigned int ipmi_poll(struct file *file, poll_table *wait)
++{
++ struct ipmi_file_private *priv = file->private_data;
++ unsigned int mask = 0;
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->recv_msg_lock, flags);
++
++ poll_wait(file, &priv->wait, wait);
++
++ if (! list_empty(&(priv->recv_msgs)))
++ mask |= (POLLIN | POLLRDNORM);
++
++ spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
++
++ return mask;
++}
++
++static int ipmi_fasync(int fd, struct file *file, int on)
++{
++ struct ipmi_file_private *priv = file->private_data;
++ int result;
++
++ result = fasync_helper(fd, file, on, &priv->fasync_queue);
++
++ return (result);
++}
++
++static struct ipmi_user_hndl ipmi_hndlrs =
++{
++ ipmi_recv_hndl : file_receive_handler
++};
++
++static int ipmi_open(struct inode *inode, struct file *file)
++{
++ int if_num = minor(inode->i_rdev);
++ int rv;
++ struct ipmi_file_private *priv;
++
++
++ priv = kmalloc(sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->file = file;
++
++ rv = ipmi_create_user(if_num,
++ &ipmi_hndlrs,
++ priv,
++ &(priv->user));
++ if (rv) {
++ kfree(priv);
++ return rv;
++ }
++
++ file->private_data = priv;
++
++ spin_lock_init(&(priv->recv_msg_lock));
++ INIT_LIST_HEAD(&(priv->recv_msgs));
++ init_waitqueue_head(&priv->wait);
++ priv->fasync_queue = NULL;
++ sema_init(&(priv->recv_sem), 1);
++
++ return 0;
++}
++
++static int ipmi_release(struct inode *inode, struct file *file)
++{
++ struct ipmi_file_private *priv = file->private_data;
++ int rv;
++
++ rv = ipmi_destroy_user(priv->user);
++ if (rv)
++ return rv;
++
++ ipmi_fasync (-1, file, 0);
++
++ /* FIXME - free the messages in the list. */
++ kfree(priv);
++
++ return 0;
++}
++
++static int ipmi_ioctl(struct inode *inode,
++ struct file *file,
++ unsigned int cmd,
++ unsigned long data)
++{
++ int rv = -EINVAL;
++ struct ipmi_file_private *priv = file->private_data;
++
++ switch (cmd)
++ {
++ case IPMICTL_SEND_COMMAND:
++ {
++ struct ipmi_req req;
++ struct ipmi_addr addr;
++ unsigned char msgdata[IPMI_MAX_MSG_LENGTH];
++
++ if (copy_from_user(&req, (void *) data, sizeof(req))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ if (req.addr_len > sizeof(struct ipmi_addr))
++ {
++ rv = -EINVAL;
++ break;
++ }
++
++ if (copy_from_user(&addr, req.addr, req.addr_len)) {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = ipmi_validate_addr(&addr, req.addr_len);
++ if (rv)
++ break;
++
++ if (req.msg.data != NULL) {
++ if (req.msg.data_len > IPMI_MAX_MSG_LENGTH) {
++ rv = -EMSGSIZE;
++ break;
++ }
++
++ if (copy_from_user(&msgdata,
++ req.msg.data,
++ req.msg.data_len))
++ {
++ rv = -EFAULT;
++ break;
++ }
++ } else {
++ req.msg.data_len = 0;
++ }
++
++ req.msg.data = msgdata;
++
++ rv = ipmi_request(priv->user,
++ &addr,
++ req.msgid,
++ &(req.msg),
++ 0);
++ break;
++ }
++
++ case IPMICTL_RECEIVE_MSG:
++ case IPMICTL_RECEIVE_MSG_TRUNC:
++ {
++ struct ipmi_recv rsp;
++ int addr_len;
++ struct list_head *entry;
++ struct ipmi_recv_msg *msg;
++ unsigned long flags;
++
++
++ rv = 0;
++ if (copy_from_user(&rsp, (void *) data, sizeof(rsp))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ /* We claim a semaphore because we don't want two
++ users getting something from the queue at a time.
++ Since we have to release the spinlock before we can
++ copy the data to the user, it's possible another
++ user will grab something from the queue, too. Then
++ the messages might get out of order if something
++ fails and the message gets put back onto the
++ queue. This semaphore prevents that problem. */
++ down(&(priv->recv_sem));
++
++ /* Grab the message off the list. */
++ spin_lock_irqsave(&(priv->recv_msg_lock), flags);
++ if (list_empty(&(priv->recv_msgs))) {
++ spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
++ rv = -EAGAIN;
++ goto recv_err;
++ }
++ entry = priv->recv_msgs.next;
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ list_del(entry);
++ spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
++
++ addr_len = ipmi_addr_length(msg->addr.addr_type);
++ if (rsp.addr_len < addr_len)
++ {
++ rv = -EINVAL;
++ goto recv_putback_on_err;
++ }
++
++ if (copy_to_user(rsp.addr, &(msg->addr), addr_len)) {
++ rv = -EFAULT;
++ goto recv_putback_on_err;
++ }
++ rsp.addr_len = addr_len;
++
++ rsp.recv_type = msg->recv_type;
++ rsp.msgid = msg->msgid;
++ rsp.msg.netfn = msg->msg.netfn;
++ rsp.msg.cmd = msg->msg.cmd;
++
++ if (msg->msg.data_len > 0) {
++ if (rsp.msg.data_len < msg->msg.data_len) {
++ rv = -EMSGSIZE;
++ if (cmd == IPMICTL_RECEIVE_MSG_TRUNC) {
++ msg->msg.data_len = rsp.msg.data_len;
++ } else {
++ goto recv_putback_on_err;
++ }
++ }
++
++ if (copy_to_user(rsp.msg.data,
++ msg->msg.data,
++ msg->msg.data_len))
++ {
++ rv = -EFAULT;
++ goto recv_putback_on_err;
++ }
++ rsp.msg.data_len = msg->msg.data_len;
++ } else {
++ rsp.msg.data_len = 0;
++ }
++
++ if (copy_to_user((void *) data, &rsp, sizeof(rsp))) {
++ rv = -EFAULT;
++ goto recv_putback_on_err;
++ }
++
++ up(&(priv->recv_sem));
++ ipmi_free_recv_msg(msg);
++ break;
++
++ recv_putback_on_err:
++ /* If we got an error, put the message back onto
++ the head of the queue. */
++ spin_lock_irqsave(&(priv->recv_msg_lock), flags);
++ list_add(entry, &(priv->recv_msgs));
++ spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
++ up(&(priv->recv_sem));
++ break;
++
++ recv_err:
++ up(&(priv->recv_sem));
++ break;
++ }
++
++ case IPMICTL_REGISTER_FOR_CMD:
++ {
++ struct ipmi_cmdspec val;
++
++ if (copy_from_user(&val, (void *) data, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd);
++ break;
++ }
++
++ case IPMICTL_UNREGISTER_FOR_CMD:
++ {
++ struct ipmi_cmdspec val;
++
++ if (copy_from_user(&val, (void *) data, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd);
++ break;
++ }
++
++ case IPMICTL_SET_GETS_EVENTS_CMD:
++ {
++ int val;
++
++ if (copy_from_user(&val, (void *) data, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = ipmi_set_gets_events(priv->user, val);
++ break;
++ }
++
++ case IPMICTL_SET_MY_ADDRESS_CMD:
++ {
++ unsigned int val;
++
++ if (copy_from_user(&val, (void *) data, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ ipmi_set_my_address(priv->user, val);
++ rv = 0;
++ break;
++ }
++
++ case IPMICTL_GET_MY_ADDRESS_CMD:
++ {
++ unsigned int val;
++
++ val = ipmi_get_my_address(priv->user);
++
++ if (copy_to_user((void *) data, &val, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++ rv = 0;
++ break;
++ }
++
++ case IPMICTL_SET_MY_LUN_CMD:
++ {
++ unsigned int val;
++
++ if (copy_from_user(&val, (void *) data, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ ipmi_set_my_LUN(priv->user, val);
++ rv = 0;
++ break;
++ }
++
++ case IPMICTL_GET_MY_LUN_CMD:
++ {
++ unsigned int val;
++
++ val = ipmi_get_my_LUN(priv->user);
++
++ if (copy_to_user((void *) data, &val, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++ rv = 0;
++ break;
++ }
++
++ }
++
++ return rv;
++}
++
++
++static struct file_operations ipmi_fops = {
++ owner: THIS_MODULE,
++ ioctl: ipmi_ioctl,
++ open: ipmi_open,
++ release: ipmi_release,
++ fasync: ipmi_fasync,
++ poll: ipmi_poll
++};
++
++#define DEVICE_NAME "ipmidev"
++
++static int ipmi_major = 0;
++MODULE_PARM(ipmi_major, "i");
++
++static devfs_handle_t devfs_handle;
++
++#define MAX_DEVICES 10
++static devfs_handle_t handles[MAX_DEVICES];
++
++static void ipmi_new_smi(int if_num)
++{
++ char name[2];
++
++ if (if_num > MAX_DEVICES)
++ return;
++
++ name[0] = if_num + '0';
++ name[1] = '\0';
++
++ handles[if_num] = devfs_register(devfs_handle, name, DEVFS_FL_NONE,
++ ipmi_major, if_num,
++ S_IFCHR | S_IRUSR | S_IWUSR,
++ &ipmi_fops, NULL);
++}
++
++static void ipmi_smi_gone(int if_num)
++{
++ if (if_num > MAX_DEVICES)
++ return;
++
++ devfs_unregister(handles[if_num]);
++}
++
++static struct ipmi_smi_watcher smi_watcher =
++{
++ new_smi : ipmi_new_smi,
++ smi_gone : ipmi_smi_gone
++};
++
++static __init int init_ipmi_devintf(void)
++{
++ int rv;
++
++ if (ipmi_major < 0)
++ return -EINVAL;
++
++ rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
++ if (rv < 0) {
++ printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major);
++ return rv;
++ }
++
++ if (ipmi_major == 0) {
++ ipmi_major = rv;
++ }
++
++ devfs_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL);
++
++ rv = ipmi_smi_watcher_register(&smi_watcher);
++ if (rv) {
++ unregister_chrdev(ipmi_major, DEVICE_NAME);
++ printk(KERN_WARNING "ipmi: can't register smi watcher");
++ return rv;
++ }
++
++ printk(KERN_INFO "ipmi: device interface at char major %d\n",
++ ipmi_major);
++
++ return 0;
++}
++module_init(init_ipmi_devintf);
++
++static __exit void cleanup_ipmi(void)
++{
++ ipmi_smi_watcher_unregister(&smi_watcher);
++ devfs_unregister(devfs_handle);
++ unregister_chrdev(ipmi_major, DEVICE_NAME);
++}
++module_exit(cleanup_ipmi);
++#ifndef MODULE
++static __init int ipmi_setup (char *str)
++{
++ int x;
++
++ if (get_option (&str, &x)) {
++ /* ipmi=x sets the major number to x. */
++ ipmi_major = x;
++ } else if (!strcmp(str, "off")) {
++ ipmi_major = -1;
++ }
++
++ return 1;
++}
++#endif
++
++__setup("ipmi=", ipmi_setup);
++MODULE_LICENSE("GPL");
+diff -urN linux.orig/drivers/char/ipmi/ipmi_kcs_intf.c linux/drivers/char/ipmi/ipmi_kcs_intf.c
+--- linux.orig/drivers/char/ipmi/ipmi_kcs_intf.c Wed Dec 31 18:00:00 1969
++++ linux/drivers/char/ipmi/ipmi_kcs_intf.c Mon Jan 6 10:20:27 2003
+@@ -0,0 +1,1243 @@
++/*
++ * ipmi_kcs_intf.c
++ *
++ * The interface to the IPMI driver for the KCS.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++/*
++ * This file holds the "policy" for the interface to the KCS state
++ * machine. It does the configuration, handles timers and interrupts,
++ * and drives the real KCS state machine.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <asm/system.h>
++#include <linux/sched.h>
++#include <linux/timer.h>
++#include <linux/errno.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/list.h>
++#include <linux/ioport.h>
++#ifdef CONFIG_HIGH_RES_TIMERS
++#include <linux/hrtime.h>
++#endif
++#include <linux/interrupt.h>
++#include <linux/ipmi_smi.h>
++#include <asm/io.h>
++#include "ipmi_kcs_sm.h"
++#include <linux/init.h>
++
++/* Measure times between events in the driver. */
++#undef DEBUG_TIMING
++
++#ifdef CONFIG_IPMI_KCS
++/* This forces a dependency to the config file for this option. */
++#endif
++
++enum kcs_intf_state {
++ KCS_NORMAL,
++ KCS_GETTING_FLAGS,
++ KCS_GETTING_EVENTS,
++ KCS_CLEARING_FLAGS,
++ KCS_CLEARING_FLAGS_THEN_SET_IRQ,
++ KCS_GETTING_MESSAGES,
++ KCS_ENABLE_INTERRUPTS1,
++ KCS_ENABLE_INTERRUPTS2
++ /* FIXME - add watchdog stuff. */
++};
++
++struct kcs_info
++{
++ ipmi_smi_t intf;
++ struct kcs_data *kcs_sm;
++ spinlock_t kcs_lock;
++ spinlock_t msg_lock;
++ struct list_head xmit_msgs;
++ struct list_head hp_xmit_msgs;
++ struct ipmi_smi_msg *curr_msg;
++ enum kcs_intf_state kcs_state;
++
++ /* Flags from the last GET_MSG_FLAGS command, used when an ATTN
++ is set to hold the flags until we are done handling everything
++ from the flags. */
++#define RECEIVE_MSG_AVAIL 0x01
++#define EVENT_MSG_BUFFER_FULL 0x02
++#define WDT_PRE_TIMEOUT_INT 0x08
++ unsigned char msg_flags;
++
++ /* If set to true, this will request events the next time the
++ state machine is idle. */
++ atomic_t req_events;
++
++ /* If true, run the state machine to completion on every send
++ call. Generally used after a panic to make sure stuff goes
++ out. */
++ int run_to_completion;
++
++ /* The I/O port of a KCS interface. */
++ int port;
++
++ /* zero if no irq; */
++ int irq;
++
++ /* The physical and remapped memory addresses of a KCS interface. */
++ unsigned long physaddr;
++ unsigned char *addr;
++
++ /* The timer for this kcs. */
++ struct timer_list kcs_timer;
++
++ /* The time (in jiffies) the last timeout occurred at. */
++ unsigned long last_timeout_jiffies;
++
++ /* Used to gracefully stop the timer without race conditions. */
++ volatile int stop_operation;
++ volatile int timer_stopped;
++
++ /* The driver will disable interrupts when it gets into a
++ situation where it cannot handle messages due to lack of
++ memory. Once that situation clears up, it will re-enable
++ interupts. */
++ int interrupt_disabled;
++};
++
++static void deliver_recv_msg(struct kcs_info *kcs_info, struct ipmi_smi_msg *msg)
++{
++ /* Deliver the message to the upper layer with the lock
++ released. */
++ spin_unlock(&(kcs_info->kcs_lock));
++ ipmi_smi_msg_received(kcs_info->intf, msg);
++ spin_lock(&(kcs_info->kcs_lock));
++}
++
++static void return_hosed_msg(struct kcs_info *kcs_info)
++{
++ struct ipmi_smi_msg *msg = kcs_info->curr_msg;
++
++ /* Make it a reponse */
++ msg->rsp[0] = msg->data[0] | 4;
++ msg->rsp[1] = msg->data[1];
++ msg->rsp[2] = 0xFF; /* Unknown error. */
++ msg->rsp_size = 3;
++
++ kcs_info->curr_msg = NULL;
++ deliver_recv_msg(kcs_info, msg);
++}
++
++static enum kcs_result start_next_msg(struct kcs_info *kcs_info)
++{
++ int rv;
++ struct list_head *entry = NULL;
++#ifdef DEBUG_TIMING
++ struct timeval t;
++#endif
++
++ /* No need to save flags, we aleady have interrupts off and we
++ already hold the KCS lock. */
++ spin_lock(&(kcs_info->msg_lock));
++
++ /* Pick the high priority queue first. */
++ if (! list_empty(&(kcs_info->hp_xmit_msgs))) {
++ entry = kcs_info->hp_xmit_msgs.next;
++ } else if (! list_empty(&(kcs_info->xmit_msgs))) {
++ entry = kcs_info->xmit_msgs.next;
++ }
++
++ if (!entry) {
++ kcs_info->curr_msg = NULL;
++ rv = KCS_SM_IDLE;
++ } else {
++ int err;
++
++ list_del(entry);
++ kcs_info->curr_msg = list_entry(entry,
++ struct ipmi_smi_msg,
++ link);
++#ifdef DEBUG_TIMING
++ do_gettimeofday(&t);
++ printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++ err = start_kcs_transaction(kcs_info->kcs_sm,
++ kcs_info->curr_msg->data,
++ kcs_info->curr_msg->data_size);
++ if (err) {
++ return_hosed_msg(kcs_info);
++ }
++
++ rv = KCS_CALL_WITHOUT_DELAY;
++ }
++ spin_unlock(&(kcs_info->msg_lock));
++
++ return rv;
++}
++
++static void start_enable_irq(struct kcs_info *kcs_info)
++{
++ unsigned char msg[2];
++
++ /* If we are enabling interrupts, we have to tell the
++ BMC to use them. */
++ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
++
++ start_kcs_transaction(kcs_info->kcs_sm, msg, 2);
++ kcs_info->kcs_state = KCS_ENABLE_INTERRUPTS1;
++}
++
++static void start_clear_flags(struct kcs_info *kcs_info)
++{
++ unsigned char msg[3];
++
++ /* Make sure the watchdog pre-timeout flag is not set at startup. */
++ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
++ msg[2] = WDT_PRE_TIMEOUT_INT;
++
++ start_kcs_transaction(kcs_info->kcs_sm, msg, 3);
++ kcs_info->kcs_state = KCS_CLEARING_FLAGS;
++}
++
++/* When we have a situtaion where we run out of memory and cannot
++ allocate messages, we just leave them in the BMC and run the system
++ polled until we can allocate some memory. Once we have some
++ memory, we will re-enable the interrupt. */
++static inline void disable_kcs_irq(struct kcs_info *kcs_info)
++{
++ if ((kcs_info->irq) && (!kcs_info->interrupt_disabled)) {
++ disable_irq_nosync(kcs_info->irq);
++ kcs_info->interrupt_disabled = 1;
++ }
++}
++
++static inline void enable_kcs_irq(struct kcs_info *kcs_info)
++{
++ if ((kcs_info->irq) && (kcs_info->interrupt_disabled)) {
++ enable_irq(kcs_info->irq);
++ kcs_info->interrupt_disabled = 0;
++ }
++}
++
++static void handle_flags(struct kcs_info *kcs_info)
++{
++ if (kcs_info->msg_flags & WDT_PRE_TIMEOUT_INT) {
++ /* Watchdog pre-timeout */
++ start_clear_flags(kcs_info);
++ kcs_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
++ spin_unlock(&(kcs_info->kcs_lock));
++ ipmi_smi_watchdog_pretimeout(kcs_info->intf);
++ spin_lock(&(kcs_info->kcs_lock));
++ } else if (kcs_info->msg_flags & RECEIVE_MSG_AVAIL) {
++ /* Messages available. */
++ kcs_info->curr_msg = ipmi_alloc_smi_msg();
++ if (!kcs_info->curr_msg) {
++ disable_kcs_irq(kcs_info);
++ kcs_info->kcs_state = KCS_NORMAL;
++ return;
++ }
++ enable_kcs_irq(kcs_info);
++
++ kcs_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ kcs_info->curr_msg->data[1] = IPMI_GET_MSG_CMD;
++ kcs_info->curr_msg->data_size = 2;
++
++ start_kcs_transaction(kcs_info->kcs_sm,
++ kcs_info->curr_msg->data,
++ kcs_info->curr_msg->data_size);
++ kcs_info->kcs_state = KCS_GETTING_MESSAGES;
++ } else if (kcs_info->msg_flags & EVENT_MSG_BUFFER_FULL) {
++ /* Events available. */
++ kcs_info->curr_msg = ipmi_alloc_smi_msg();
++ if (!kcs_info->curr_msg) {
++ disable_kcs_irq(kcs_info);
++ kcs_info->kcs_state = KCS_NORMAL;
++ return;
++ }
++ enable_kcs_irq(kcs_info);
++
++ kcs_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ kcs_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD;
++ kcs_info->curr_msg->data_size = 2;
++
++ start_kcs_transaction(kcs_info->kcs_sm,
++ kcs_info->curr_msg->data,
++ kcs_info->curr_msg->data_size);
++ kcs_info->kcs_state = KCS_GETTING_EVENTS;
++ } else {
++ kcs_info->kcs_state = KCS_NORMAL;
++ }
++}
++
++static void handle_transaction_done(struct kcs_info *kcs_info)
++{
++ struct ipmi_smi_msg *msg;
++#ifdef DEBUG_TIMING
++ struct timeval t;
++
++ do_gettimeofday(&t);
++ printk("**Done: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++ switch (kcs_info->kcs_state) {
++ case KCS_NORMAL:
++ kcs_info->curr_msg->rsp_size
++ = kcs_get_result(kcs_info->kcs_sm,
++ kcs_info->curr_msg->rsp,
++ IPMI_MAX_MSG_LENGTH);
++
++ /* Do this here becase deliver_recv_msg() releases the
++ lock, and a new message can be put in during the
++ time the lock is released. */
++ msg = kcs_info->curr_msg;
++ kcs_info->curr_msg = NULL;
++ deliver_recv_msg(kcs_info, msg);
++ break;
++
++ case KCS_GETTING_FLAGS:
++ {
++ unsigned char msg[4];
++ unsigned int len;
++
++ /* We got the flags from the KCS, now handle them. */
++ len = kcs_get_result(kcs_info->kcs_sm, msg, 4);
++ if (msg[2] != 0) {
++ /* Error fetching flags, just give up for
++ now. */
++ kcs_info->kcs_state = KCS_NORMAL;
++ } else if (len < 3) {
++ /* Hmm, no flags. That's technically illegal, but
++ don't use uninitialized data. */
++ kcs_info->kcs_state = KCS_NORMAL;
++ } else {
++ kcs_info->msg_flags = msg[3];
++ handle_flags(kcs_info);
++ }
++ break;
++ }
++
++ case KCS_CLEARING_FLAGS:
++ case KCS_CLEARING_FLAGS_THEN_SET_IRQ:
++ {
++ unsigned char msg[3];
++
++ /* We cleared the flags. */
++ kcs_get_result(kcs_info->kcs_sm, msg, 3);
++ if (msg[2] != 0) {
++ /* Error clearing flags */
++ printk(KERN_WARNING
++ "ipmi_kcs: Error clearing flags: %2.2x\n",
++ msg[2]);
++ }
++ if (kcs_info->kcs_state == KCS_CLEARING_FLAGS_THEN_SET_IRQ)
++ start_enable_irq(kcs_info);
++ else
++ kcs_info->kcs_state = KCS_NORMAL;
++ break;
++ }
++
++ case KCS_GETTING_EVENTS:
++ {
++ kcs_info->curr_msg->rsp_size
++ = kcs_get_result(kcs_info->kcs_sm,
++ kcs_info->curr_msg->rsp,
++ IPMI_MAX_MSG_LENGTH);
++
++ /* Do this here becase deliver_recv_msg() releases the
++ lock, and a new message can be put in during the
++ time the lock is released. */
++ msg = kcs_info->curr_msg;
++ kcs_info->curr_msg = NULL;
++ if (msg->rsp[2] != 0) {
++ /* Error getting event, probably done. */
++ msg->done(msg);
++
++ /* Take off the event flag. */
++ kcs_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
++ } else {
++ deliver_recv_msg(kcs_info, msg);
++ }
++ handle_flags(kcs_info);
++ break;
++ }
++
++ case KCS_GETTING_MESSAGES:
++ {
++ kcs_info->curr_msg->rsp_size
++ = kcs_get_result(kcs_info->kcs_sm,
++ kcs_info->curr_msg->rsp,
++ IPMI_MAX_MSG_LENGTH);
++
++ /* Do this here becase deliver_recv_msg() releases the
++ lock, and a new message can be put in during the
++ time the lock is released. */
++ msg = kcs_info->curr_msg;
++ kcs_info->curr_msg = NULL;
++ if (msg->rsp[2] != 0) {
++ /* Error getting event, probably done. */
++ msg->done(msg);
++
++ /* Take off the msg flag. */
++ kcs_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
++ } else {
++ deliver_recv_msg(kcs_info, msg);
++ }
++ handle_flags(kcs_info);
++ break;
++ }
++
++ case KCS_ENABLE_INTERRUPTS1:
++ {
++ unsigned char msg[4];
++
++ /* We got the flags from the KCS, now handle them. */
++ kcs_get_result(kcs_info->kcs_sm, msg, 4);
++ if (msg[2] != 0) {
++ printk(KERN_WARNING
++ "ipmi_kcs: Could not enable interrupts"
++ ", failed get, using polled mode.\n");
++ kcs_info->kcs_state = KCS_NORMAL;
++ } else {
++ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
++ msg[2] = msg[3] | 1; /* enable msg queue int */
++ start_kcs_transaction(kcs_info->kcs_sm, msg,3);
++ kcs_info->kcs_state = KCS_ENABLE_INTERRUPTS2;
++ }
++ break;
++ }
++
++ case KCS_ENABLE_INTERRUPTS2:
++ {
++ unsigned char msg[4];
++
++ /* We got the flags from the KCS, now handle them. */
++ kcs_get_result(kcs_info->kcs_sm, msg, 4);
++ if (msg[2] != 0) {
++ printk(KERN_WARNING
++ "ipmi_kcs: Could not enable interrupts"
++ ", failed set, using polled mode.\n");
++ }
++ kcs_info->kcs_state = KCS_NORMAL;
++ break;
++ }
++ }
++}
++
++/* Called on timeouts and events. Timeouts should pass the elapsed
++ time, interrupts should pass in zero. */
++static enum kcs_result kcs_event_handler(struct kcs_info *kcs_info, int time)
++{
++ enum kcs_result kcs_result;
++
++ restart:
++ /* There used to be a loop here that waited a little while
++ (around 25us) before giving up. That turned out to be
++ pointless, the minimum delays I was seeing were in the 300us
++ range, which is far too long to wait in an interrupt. So
++ we just run until the state machine tells us something
++ happened or it needs a delay. */
++ kcs_result = kcs_event(kcs_info->kcs_sm, time);
++ time = 0;
++ while (kcs_result == KCS_CALL_WITHOUT_DELAY)
++ {
++ kcs_result = kcs_event(kcs_info->kcs_sm, 0);
++ }
++
++ if (kcs_result == KCS_TRANSACTION_COMPLETE)
++ {
++ handle_transaction_done(kcs_info);
++ kcs_result = kcs_event(kcs_info->kcs_sm, 0);
++ }
++ else if (kcs_result == KCS_SM_HOSED)
++ {
++ if (kcs_info->curr_msg != NULL) {
++ /* If we were handling a user message, format
++ a response to send to the upper layer to
++ tell it about the error. */
++ return_hosed_msg(kcs_info);
++ }
++ kcs_result = kcs_event(kcs_info->kcs_sm, 0);
++ kcs_info->kcs_state = KCS_NORMAL;
++ }
++
++ /* We prefer handling attn over new messages. */
++ if (kcs_result == KCS_ATTN)
++ {
++ unsigned char msg[2];
++
++ /* Got a attn, send down a get message flags to see
++ what's causing it. It would be better to handle
++ this in the upper layer, but due to the way
++ interrupts work with the KCS, that's not really
++ possible. */
++ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg[1] = IPMI_GET_MSG_FLAGS_CMD;
++
++ start_kcs_transaction(kcs_info->kcs_sm, msg, 2);
++ kcs_info->kcs_state = KCS_GETTING_FLAGS;
++ goto restart;
++ }
++
++ /* If we are currently idle, try to start the next message. */
++ if (kcs_result == KCS_SM_IDLE) {
++ kcs_result = start_next_msg(kcs_info);
++ if (kcs_result != KCS_SM_IDLE)
++ goto restart;
++ }
++
++ if ((kcs_result == KCS_SM_IDLE)
++ && (atomic_read(&kcs_info->req_events)))
++ {
++ /* We are idle and the upper layer requested that I fetch
++ events, so do so. */
++ unsigned char msg[2];
++
++ atomic_set(&kcs_info->req_events, 0);
++ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg[1] = IPMI_GET_MSG_FLAGS_CMD;
++
++ start_kcs_transaction(kcs_info->kcs_sm, msg, 2);
++ kcs_info->kcs_state = KCS_GETTING_FLAGS;
++ goto restart;
++ }
++
++ return kcs_result;
++}
++
++static void sender(void *send_info,
++ struct ipmi_smi_msg *msg,
++ int priority)
++{
++ struct kcs_info *kcs_info = (struct kcs_info *) send_info;
++ enum kcs_result result;
++ unsigned long flags;
++#ifdef DEBUG_TIMING
++ struct timeval t;
++#endif
++
++ spin_lock_irqsave(&(kcs_info->msg_lock), flags);
++#ifdef DEBUG_TIMING
++ do_gettimeofday(&t);
++ printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++
++ if (kcs_info->run_to_completion) {
++ /* If we are running to completion, then throw it in
++ the list and run transactions until everything is
++ clear. Priority doesn't matter here. */
++ list_add_tail(&(msg->link), &(kcs_info->xmit_msgs));
++
++ /* We have to release the msg lock and claim the kcs
++ lock in this case, because of race conditions. */
++ spin_unlock_irqrestore(&(kcs_info->msg_lock), flags);
++
++ spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
++ result = kcs_event_handler(kcs_info, 0);
++ while (result != KCS_SM_IDLE) {
++ udelay(500);
++ result = kcs_event_handler(kcs_info, 500);
++ }
++ spin_unlock_irqrestore(&(kcs_info->kcs_lock), flags);
++ return;
++ } else {
++ if (priority > 0) {
++ list_add_tail(&(msg->link), &(kcs_info->hp_xmit_msgs));
++ } else {
++ list_add_tail(&(msg->link), &(kcs_info->xmit_msgs));
++ }
++ }
++ spin_unlock_irqrestore(&(kcs_info->msg_lock), flags);
++
++ spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
++ if ((kcs_info->kcs_state == KCS_NORMAL)
++ && (kcs_info->curr_msg == NULL))
++ {
++ start_next_msg(kcs_info);
++ }
++ spin_unlock_irqrestore(&(kcs_info->kcs_lock), flags);
++}
++
++static void set_run_to_completion(void *send_info, int i_run_to_completion)
++{
++ struct kcs_info *kcs_info = (struct kcs_info *) send_info;
++ enum kcs_result result;
++ unsigned long flags;
++
++ spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
++
++ kcs_info->run_to_completion = i_run_to_completion;
++ if (i_run_to_completion) {
++ result = kcs_event_handler(kcs_info, 0);
++ while (result != KCS_SM_IDLE) {
++ udelay(500);
++ result = kcs_event_handler(kcs_info, 500);
++ }
++ }
++
++ spin_unlock_irqrestore(&(kcs_info->kcs_lock), flags);
++}
++
++static void request_events(void *send_info)
++{
++ struct kcs_info *kcs_info = (struct kcs_info *) send_info;
++
++ atomic_set(&kcs_info->req_events, 1);
++}
++
++static int new_user(void *send_info)
++{
++ if (!try_inc_mod_count(THIS_MODULE))
++ return -EBUSY;
++ return 0;
++}
++
++static void user_left(void *send_info)
++{
++ MOD_DEC_USE_COUNT;
++}
++
++/* Call every 10 ms. */
++#define KCS_TIMEOUT_TIME_USEC 10000
++#define KCS_USEC_PER_JIFFY (1000000/HZ)
++#define KCS_TIMEOUT_JIFFIES (KCS_TIMEOUT_TIME_USEC/KCS_USEC_PER_JIFFY)
++#define KCS_SHORT_TIMEOUT_USEC 500 /* .5ms when the SM request a
++ short timeout */
++static int initialized = 0;
++
++static void kcs_timeout(unsigned long data)
++{
++ struct kcs_info *kcs_info = (struct kcs_info *) data;
++ enum kcs_result kcs_result;
++ unsigned long flags;
++ unsigned long jiffies_now;
++ unsigned long time_diff;
++#ifdef DEBUG_TIMING
++ struct timeval t;
++#endif
++
++ if (kcs_info->stop_operation) {
++ kcs_info->timer_stopped = 1;
++ return;
++ }
++
++ spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
++#ifdef DEBUG_TIMING
++ do_gettimeofday(&t);
++ printk("**Timer: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++ jiffies_now = jiffies;
++ time_diff = ((jiffies_now - kcs_info->last_timeout_jiffies)
++ * KCS_USEC_PER_JIFFY);
++ kcs_result = kcs_event_handler(kcs_info, time_diff);
++
++ spin_unlock_irqrestore(&(kcs_info->kcs_lock), flags);
++
++ kcs_info->last_timeout_jiffies = jiffies_now;
++
++ if ((kcs_info->irq) && (! kcs_info->interrupt_disabled)) {
++ /* Running with interrupts, only do long timeouts. */
++ kcs_info->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES;
++ goto do_add_timer;
++ }
++
++ /* If the state machine asks for a short delay, then shorten
++ the timer timeout. */
++#ifdef CONFIG_HIGH_RES_TIMERS
++ if (kcs_result == KCS_CALL_WITH_DELAY) {
++ kcs_info->kcs_timer.sub_expires
++ += usec_to_arch_cycles(KCS_SHORT_TIMEOUT_USEC);
++ while (kcs_info->kcs_timer.sub_expires >= cycles_per_jiffies) {
++ kcs_info->kcs_timer.expires++;
++ kcs_info->kcs_timer.sub_expires -= cycles_per_jiffies;
++ }
++ } else {
++ kcs_info->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES;
++ }
++#else
++ /* If requested, take the shortest delay possible */
++ if (kcs_result == KCS_CALL_WITH_DELAY) {
++ kcs_info->kcs_timer.expires = jiffies + 1;
++ } else {
++ kcs_info->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES;
++ }
++#endif
++
++ do_add_timer:
++ add_timer(&(kcs_info->kcs_timer));
++}
++
++static void kcs_irq_handler(int irq, void *data, struct pt_regs *regs)
++{
++ struct kcs_info *kcs_info = (struct kcs_info *) data;
++ unsigned long flags;
++#ifdef DEBUG_TIMING
++ struct timeval t;
++#endif
++
++ spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
++ if (kcs_info->stop_operation)
++ goto out;
++
++#ifdef DEBUG_TIMING
++ do_gettimeofday(&t);
++ printk("**Interrupt: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++ kcs_event_handler(kcs_info, 0);
++ out:
++ spin_unlock_irqrestore(&(kcs_info->kcs_lock), flags);
++}
++
++static struct ipmi_smi_handlers handlers =
++{
++ sender: sender,
++ request_events: request_events,
++ new_user: new_user,
++ user_left: user_left,
++ set_run_to_completion: set_run_to_completion
++};
++
++static unsigned char ipmi_kcs_dev_rev;
++static unsigned char ipmi_kcs_fw_rev_major;
++static unsigned char ipmi_kcs_fw_rev_minor;
++static unsigned char ipmi_version_major;
++static unsigned char ipmi_version_minor;
++
++extern int kcs_dbg;
++static int ipmi_kcs_detect_hardware(unsigned int port,
++ unsigned char *addr,
++ struct kcs_data *data)
++{
++ unsigned char msg[2];
++ unsigned char resp[IPMI_MAX_MSG_LENGTH];
++ unsigned long resp_len;
++ enum kcs_result kcs_result;
++
++ /* It's impossible for the KCS status register to be all 1's,
++ (assuming a properly functioning, self-initialized BMC)
++ but that's what you get from reading a bogus address, so we
++ test that first. */
++
++ if (port) {
++ if (inb(port+1) == 0xff) return -ENODEV;
++ } else {
++ if (readb(addr+1) == 0xff) return -ENODEV;
++ }
++
++ /* Do a Get Device ID command, since it comes back with some
++ useful info. */
++ msg[0] = IPMI_NETFN_APP_REQUEST << 2;
++ msg[1] = IPMI_GET_DEVICE_ID_CMD;
++ start_kcs_transaction(data, msg, 2);
++
++ kcs_result = kcs_event(data, 0);
++ for (;;)
++ {
++ if (kcs_result == KCS_CALL_WITH_DELAY) {
++ udelay(100);
++ kcs_result = kcs_event(data, 100);
++ }
++ else if (kcs_result == KCS_CALL_WITHOUT_DELAY)
++ {
++ kcs_result = kcs_event(data, 0);
++ }
++ else
++ break;
++ }
++ if (kcs_result == KCS_SM_HOSED) {
++ /* We couldn't get the state machine to run, so whatever's at
++ the port is probably not an IPMI KCS interface. */
++ return -ENODEV;
++ }
++ /* Otherwise, we got some data. */
++ resp_len = kcs_get_result(data, resp, IPMI_MAX_MSG_LENGTH);
++ if (resp_len < 6)
++ /* That's odd, it should be longer. */
++ return -EINVAL;
++
++ if ((resp[1] != IPMI_GET_DEVICE_ID_CMD) || (resp[2] != 0))
++ /* That's odd, it shouldn't be able to fail. */
++ return -EINVAL;
++
++ ipmi_kcs_dev_rev = resp[4] & 0xf;
++ ipmi_kcs_fw_rev_major = resp[5] & 0x7f;
++ ipmi_kcs_fw_rev_minor = resp[6];
++ ipmi_version_major = resp[7] & 0xf;
++ ipmi_version_minor = resp[7] >> 4;
++
++ return 0;
++}
++
++/* There can be 4 IO ports passed in (with or without IRQs), 4 addresses,
++ a default IO port, and 1 ACPI/SPMI address. That sets KCS_MAX_DRIVERS */
++
++#define KCS_MAX_PARMS 4
++#define KCS_MAX_DRIVERS ((KCS_MAX_PARMS * 2) + 2)
++static struct kcs_info *kcs_infos[KCS_MAX_DRIVERS] =
++{ NULL, NULL, NULL, NULL };
++
++#define DEVICE_NAME "ipmi_kcs"
++
++#define DEFAULT_IO_PORT 0xca2
++
++static int kcs_trydefaults = 1;
++static unsigned long kcs_addrs[KCS_MAX_PARMS] = { 0, 0, 0, 0 };
++static int kcs_ports[KCS_MAX_PARMS] = { 0, 0, 0, 0 };
++static int kcs_irqs[KCS_MAX_PARMS] = { 0, 0, 0, 0 };
++
++MODULE_PARM(kcs_trydefaults, "i");
++MODULE_PARM(kcs_addrs, "1-4l");
++MODULE_PARM(kcs_irqs, "1-4i");
++MODULE_PARM(kcs_ports, "1-4i");
++
++/* Returns 0 if initialized, or negative on an error. */
++static int init_one_kcs(int kcs_port,
++ int irq,
++ unsigned long kcs_physaddr,
++ struct kcs_info **kcs)
++{
++ int rv;
++ struct kcs_info *new_kcs;
++
++ /* Did anything get passed in at all? Both == zero disables the
++ driver. */
++
++ if (!(kcs_port || kcs_physaddr))
++ return -ENODEV;
++
++ /* Only initialize a port OR a physical address on this call.
++ Also, IRQs can go with either ports or addresses. */
++
++ if (kcs_port && kcs_physaddr)
++ return -EINVAL;
++
++ new_kcs = kmalloc(kcs_size(), GFP_KERNEL);
++ if (!new_kcs) {
++ printk(KERN_ERR "ipmi_kcs: out of memory\n");
++ return -ENOMEM;
++ }
++
++ /* So we know not to free it unless we have allocated one. */
++ new_kcs->kcs_sm = NULL;
++
++ new_kcs->addr = NULL;
++ new_kcs->physaddr = kcs_physaddr;
++ new_kcs->port = kcs_port;
++
++ if (kcs_port) {
++ if (request_region(kcs_port, 2, DEVICE_NAME) == NULL) {
++ kfree(new_kcs);
++ printk(KERN_ERR
++ "ipmi_kcs: can't reserve port @ 0x%4.4x\n",
++ kcs_port);
++ return -EIO;
++ }
++ } else {
++ if (request_mem_region(kcs_physaddr, 2, DEVICE_NAME) == NULL) {
++ kfree(new_kcs);
++ printk(KERN_ERR
++ "ipmi_kcs: can't reserve memory @ 0x%lx\n",
++ kcs_physaddr);
++ return -EIO;
++ }
++ if ((new_kcs->addr = ioremap(kcs_physaddr, 2)) == NULL) {
++ kfree(new_kcs);
++ printk(KERN_ERR
++ "ipmi_kcs: can't remap memory at 0x%lx\n",
++ kcs_physaddr);
++ return -EIO;
++ }
++ }
++
++ new_kcs->kcs_sm = kmalloc(kcs_size(), GFP_KERNEL);
++ if (!new_kcs->kcs_sm) {
++ printk(KERN_ERR "ipmi_kcs: out of memory\n");
++ rv = -ENOMEM;
++ goto out_err;
++ }
++ init_kcs_data(new_kcs->kcs_sm, kcs_port, new_kcs->addr);
++ spin_lock_init(&(new_kcs->kcs_lock));
++ spin_lock_init(&(new_kcs->msg_lock));
++
++ rv = ipmi_kcs_detect_hardware(kcs_port, new_kcs->addr, new_kcs->kcs_sm);
++ if (rv) {
++ if (kcs_port)
++ printk(KERN_ERR
++ "ipmi_kcs: No KCS @ port 0x%4.4x\n",
++ kcs_port);
++ else
++ printk(KERN_ERR
++ "ipmi_kcs: No KCS @ addr 0x%lx\n",
++ kcs_physaddr);
++ goto out_err;
++ }
++
++ if (irq != 0) {
++ rv = request_irq(irq,
++ kcs_irq_handler,
++ SA_INTERRUPT,
++ DEVICE_NAME,
++ new_kcs);
++ if (rv) {
++ printk(KERN_WARNING
++ "ipmi_kcs: %s unable to claim interrupt %d,"
++ " running polled\n",
++ DEVICE_NAME, irq);
++ irq = 0;
++ }
++ }
++ new_kcs->irq = irq;
++
++ INIT_LIST_HEAD(&(new_kcs->xmit_msgs));
++ INIT_LIST_HEAD(&(new_kcs->hp_xmit_msgs));
++ new_kcs->curr_msg = NULL;
++ atomic_set(&new_kcs->req_events, 0);
++ new_kcs->run_to_completion = 0;
++
++ start_clear_flags(new_kcs);
++
++ if (irq) {
++ new_kcs->kcs_state = KCS_CLEARING_FLAGS_THEN_SET_IRQ;
++
++ printk(KERN_INFO
++ "ipmi_kcs: Acquiring BMC @ port=0x%x irq=%d\n",
++ kcs_port, irq);
++
++ } else {
++ if (kcs_port)
++ printk(KERN_INFO
++ "ipmi_kcs: Acquiring BMC @ port=0x%x\n",
++ kcs_port);
++ else
++ printk(KERN_INFO
++ "ipmi_kcs: Acquiring BMC @ addr=0x%lx\n",
++ kcs_physaddr);
++ }
++
++ rv = ipmi_register_smi(&handlers,
++ new_kcs,
++ ipmi_version_major,
++ ipmi_version_minor,
++ &(new_kcs->intf));
++ if (rv) {
++ free_irq(irq, new_kcs);
++ printk(KERN_ERR
++ "ipmi_kcs: Unable to register device: error %d\n",
++ rv);
++ goto out_err;
++ }
++
++ new_kcs->interrupt_disabled = 0;
++ new_kcs->timer_stopped = 0;
++ new_kcs->stop_operation = 0;
++
++ init_timer(&(new_kcs->kcs_timer));
++ new_kcs->kcs_timer.data = (long) new_kcs;
++ new_kcs->kcs_timer.function = kcs_timeout;
++ new_kcs->last_timeout_jiffies = jiffies;
++ new_kcs->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES;
++ add_timer(&(new_kcs->kcs_timer));
++
++ *kcs = new_kcs;
++
++ return 0;
++
++ out_err:
++ if (kcs_port)
++ release_region (kcs_port, 2);
++ if (new_kcs->addr)
++ iounmap(new_kcs->addr);
++ if (kcs_physaddr)
++ release_mem_region(kcs_physaddr, 2);
++ if (new_kcs->kcs_sm)
++ kfree(new_kcs->kcs_sm);
++ kfree(new_kcs);
++ return rv;
++}
++
++#ifdef CONFIG_ACPI
++
++/* Retrieve the base physical address from ACPI tables. Originally
++ from Hewlett-Packard simple bmc.c, a GPL KCS driver. */
++
++#include <linux/acpi.h>
++/* A real hack, but everything's not there yet in 2.4. */
++#define COMPILER_DEPENDENT_UINT64 unsigned long
++#include <../drivers/acpi/include/acpi.h>
++#include <../drivers/acpi/include/actypes.h>
++
++struct SPMITable {
++ s8 Signature[4];
++ u32 Length;
++ u8 Revision;
++ u8 Checksum;
++ s8 OEMID[6];
++ s8 OEMTableID[8];
++ s8 OEMRevision[4];
++ s8 CreatorID[4];
++ s8 CreatorRevision[4];
++ s16 InterfaceType;
++ s16 SpecificationRevision;
++ u8 InterruptType;
++ u8 GPE;
++ s16 Reserved;
++ u64 GlobalSystemInterrupt;
++ u8 BaseAddress[12];
++ u8 UID[4];
++} __attribute__ ((packed));
++
++static unsigned long acpi_find_bmc(void)
++{
++ acpi_status status;
++ acpi_table_header *spmi;
++ static unsigned long io_base = 0;
++
++ if (io_base != 0)
++ return io_base;
++
++ status = acpi_get_firmware_table("SPMI", 1,
++ ACPI_LOGICAL_ADDRESSING, &spmi);
++
++ if (status != AE_OK) {
++ printk(KERN_ERR "ipmi_kcs: SPMI table not found.\n");
++ return 0;
++ }
++
++ memcpy(&io_base, ((struct SPMITable *)spmi)->BaseAddress,
++ sizeof(io_base));
++
++ return io_base;
++}
++#endif
++
++static __init int init_ipmi_kcs(void)
++{
++ int rv = 0;
++ int pos = 0;
++ int i = 0;
++#ifdef CONFIG_ACPI
++ unsigned long physaddr = 0;
++#endif
++
++ if (initialized)
++ return 0;
++ initialized = 1;
++
++ /* First do the "command-line" parameters */
++
++ for (i=0; i < KCS_MAX_PARMS; i++) {
++ rv = init_one_kcs(kcs_ports[i],
++ kcs_irqs[i],
++ 0,
++ &(kcs_infos[pos]));
++ if (rv == 0)
++ pos++;
++
++ rv = init_one_kcs(0,
++ kcs_irqs[i],
++ kcs_addrs[i],
++ &(kcs_infos[pos]));
++ if (rv == 0)
++ pos++;
++ }
++
++ /* Only try the defaults if enabled and resources are available
++ (because they weren't already specified above). */
++
++ if (kcs_trydefaults) {
++#ifdef CONFIG_ACPI
++ if ((physaddr = acpi_find_bmc())) {
++ if (!check_mem_region(physaddr, 2)) {
++ rv = init_one_kcs(0,
++ 0,
++ physaddr,
++ &(kcs_infos[pos]));
++ if (rv == 0)
++ pos++;
++ }
++ }
++#endif
++ if (!check_region(DEFAULT_IO_PORT, 2)) {
++ rv = init_one_kcs(DEFAULT_IO_PORT,
++ 0,
++ 0,
++ &(kcs_infos[pos]));
++ if (rv == 0)
++ pos++;
++ }
++ }
++
++ if (kcs_infos[0] == NULL) {
++ printk("ipmi_kcs: Unable to find any KCS interfaces\n");
++ return -ENODEV;
++ }
++
++ return 0;
++}
++module_init(init_ipmi_kcs);
++
++#ifdef MODULE
++void __exit cleanup_one_kcs(struct kcs_info *to_clean)
++{
++ int rv;
++ unsigned long flags;
++
++ if (! to_clean)
++ return;
++
++ /* Tell the timer and interrupt handlers that we are shutting
++ down. */
++ spin_lock_irqsave(&(to_clean->kcs_lock), flags);
++ spin_lock(&(to_clean->msg_lock));
++
++ to_clean->stop_operation = 1;
++
++ if (to_clean->irq != 0)
++ free_irq(to_clean->irq, to_clean);
++ if (to_clean->port) {
++ printk(KERN_INFO
++ "ipmi_kcs: Releasing BMC @ port=0x%x\n",
++ to_clean->port);
++ release_region (to_clean->port, 2);
++ }
++ if (to_clean->addr) {
++ printk(KERN_INFO
++ "ipmi_kcs: Releasing BMC @ addr=0x%lx\n",
++ to_clean->physaddr);
++ iounmap(to_clean->addr);
++ release_mem_region(to_clean->physaddr, 2);
++ }
++
++ spin_unlock(&(to_clean->msg_lock));
++ spin_unlock_irqrestore(&(to_clean->kcs_lock), flags);
++
++ /* Wait for the timer to stop. This avoids problems with race
++ conditions removing the timer here. Hopefully this will be
++ long enough to avoid problems with interrupts still
++ running. */
++ schedule_timeout(2);
++ while (!to_clean->timer_stopped) {
++ schedule_timeout(1);
++ }
++
++ rv = ipmi_unregister_smi(to_clean->intf);
++ if (rv) {
++ printk(KERN_ERR
++ "ipmi_kcs: Unable to unregister device: errno=%d\n",
++ rv);
++ }
++
++ initialized = 0;
++
++ kfree(to_clean->kcs_sm);
++ kfree(to_clean);
++}
++
++static __exit void cleanup_ipmi_kcs(void)
++{
++ int i;
++
++ if (!initialized)
++ return;
++
++ for (i=0; i<KCS_MAX_DRIVERS; i++) {
++ cleanup_one_kcs(kcs_infos[i]);
++ }
++}
++module_exit(cleanup_ipmi_kcs);
++#else
++
++/* Unfortunately, cmdline::get_options() only returns integers, not
++ longs. Since we need ulongs (64-bit physical addresses) parse the
++ comma-separated list manually. Arguments can be one of these forms:
++ m0xaabbccddeeff A physical memory address without an IRQ
++ m0xaabbccddeeff:cc A physical memory address with an IRQ
++ p0xaabb An IO port without an IRQ
++ p0xaabb:cc An IO port with an IRQ
++ nodefaults Suppress trying the default IO port or ACPI address
++
++ For example, to pass one IO port with an IRQ, one address, and
++ suppress the use of the default IO port and ACPI address,
++ use this option string: ipmi_kcs=p0xCA2:5,m0xFF5B0022,nodefaults
++
++ Remember, ipmi_kcs_setup() is passed the string after the equal sign. */
++
++static int __init ipmi_kcs_setup(char *str)
++{
++ unsigned long val;
++ char *cur, *colon;
++ int pos;
++
++ pos = 0;
++
++ cur = strsep(&str, ",");
++ while ((cur) && (*cur) && (pos < KCS_MAX_PARMS)) {
++ switch (*cur) {
++ case 'n':
++ if (strcmp(cur, "nodefaults") == 0)
++ kcs_trydefaults = 0;
++ else
++ printk(KERN_INFO
++ "ipmi_kcs: bad parameter value %s\n",
++ cur);
++ break;
++
++ case 'm':
++ case 'p':
++ val = simple_strtoul(cur + 1,
++ &colon,
++ 0);
++ if (*cur == 'p')
++ kcs_ports[pos] = val;
++ else
++ kcs_addrs[pos] = val;
++ if (*colon == ':') {
++ val = simple_strtoul(colon + 1,
++ &colon,
++ 0);
++ kcs_irqs[pos] = val;
++ }
++ pos++;
++ break;
++
++ default:
++ printk(KERN_INFO
++ "ipmi_kcs: bad parameter value %s\n",
++ cur);
++ }
++ cur = strsep(&str, ",");
++ }
++
++ return 1;
++}
++__setup("ipmi_kcs=", ipmi_kcs_setup);
++#endif
++
++MODULE_LICENSE("GPL");
+diff -urN linux.orig/drivers/char/ipmi/ipmi_kcs_sm.c linux/drivers/char/ipmi/ipmi_kcs_sm.c
+--- linux.orig/drivers/char/ipmi/ipmi_kcs_sm.c Wed Dec 31 18:00:00 1969
++++ linux/drivers/char/ipmi/ipmi_kcs_sm.c Fri Jan 10 21:00:19 2003
+@@ -0,0 +1,485 @@
++/*
++ * ipmi_kcs_sm.c
++ *
++ * State machine for handling IPMI KCS interfaces.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++/*
++ * This state machine is taken from the state machine in the IPMI spec,
++ * pretty much verbatim. If you have questions about the states, see
++ * that document.
++ */
++
++#include <asm/io.h>
++#include <asm/string.h> /* Gets rid of memcpy warning */
++
++#include "ipmi_kcs_sm.h"
++
++/* Set this if you want a printout of why the state machine was hosed
++ when it gets hosed. */
++#define DEBUG_HOSED_REASON
++
++/* Print the state machine state on entry every time. */
++#undef DEBUG_STATE
++
++/* The states the KCS driver may be in. */
++enum kcs_states {
++ KCS_IDLE, /* The KCS interface is currently
++ doing nothing. */
++ KCS_START_OP, /* We are starting an operation. The
++ data is in the output buffer, but
++ nothing has been done to the
++ interface yet. This was added to
++ the state machine in the spec to
++ wait for the initial IBF. */
++ KCS_WAIT_WRITE_START, /* We have written a write cmd to the
++ interface. */
++ KCS_WAIT_WRITE, /* We are writing bytes to the
++ interface. */
++ KCS_WAIT_WRITE_END, /* We have written the write end cmd
++ to the interface, and still need to
++ write the last byte. */
++ KCS_WAIT_READ, /* We are waiting to read data from
++ the interface. */
++ KCS_ERROR0, /* State to transition to the error
++ handler, this was added to the
++ state machine in the spec to be
++ sure IBF was there. */
++ KCS_ERROR1, /* First stage error handler, wait for
++ the interface to respond. */
++ KCS_ERROR2, /* The abort cmd has been written,
++ wait for the interface to
++ respond. */
++ KCS_ERROR3, /* We wrote some data to the
++ interface, wait for it to switch to
++ read mode. */
++ KCS_HOSED /* The hardware failed to follow the
++ state machine. */
++};
++
++#define MAX_KCS_READ_SIZE 80
++#define MAX_KCS_WRITE_SIZE 80
++
++/* Timeouts in microseconds. */
++#define IBF_RETRY_TIMEOUT 1000000
++#define OBF_RETRY_TIMEOUT 1000000
++#define MAX_ERROR_RETRIES 10
++
++#define IPMI_ERR_MSG_TRUNCATED 0xc6
++#define IPMI_ERR_UNSPECIFIED 0xff
++
++struct kcs_data
++{
++ enum kcs_states state;
++ unsigned int port;
++ unsigned char *addr;
++ unsigned char write_data[MAX_KCS_WRITE_SIZE];
++ int write_pos;
++ int write_count;
++ int orig_write_count;
++ unsigned char read_data[MAX_KCS_READ_SIZE];
++ int read_pos;
++ int truncated;
++
++ unsigned int error_retries;
++ long ibf_timeout;
++ long obf_timeout;
++};
++
++void init_kcs_data(struct kcs_data *kcs, unsigned int port, unsigned char *addr)
++{
++ kcs->state = KCS_IDLE;
++ kcs->port = port;
++ kcs->addr = addr;
++ kcs->write_pos = 0;
++ kcs->write_count = 0;
++ kcs->orig_write_count = 0;
++ kcs->read_pos = 0;
++ kcs->error_retries = 0;
++ kcs->truncated = 0;
++ kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
++ kcs->obf_timeout = OBF_RETRY_TIMEOUT;
++}
++
++/* Remember, init_one_kcs() insured port and addr can't both be set */
++
++static inline unsigned char read_status(struct kcs_data *kcs)
++{
++ if (kcs->port)
++ return inb(kcs->port + 1);
++ else
++ return readb(kcs->addr + 1);
++}
++
++static inline unsigned char read_data(struct kcs_data *kcs)
++{
++ if (kcs->port)
++ return inb(kcs->port + 0);
++ else
++ return readb(kcs->addr + 0);
++}
++
++static inline void write_cmd(struct kcs_data *kcs, unsigned char data)
++{
++ if (kcs->port)
++ outb(data, kcs->port + 1);
++ else
++ writeb(data, kcs->addr + 1);
++}
++
++static inline void write_data(struct kcs_data *kcs, unsigned char data)
++{
++ if (kcs->port)
++ outb(data, kcs->port + 0);
++ else
++ writeb(data, kcs->addr + 0);
++}
++
++/* Control codes. */
++#define KCS_GET_STATUS_ABORT 0x60
++#define KCS_WRITE_START 0x61
++#define KCS_WRITE_END 0x62
++#define KCS_READ_BYTE 0x68
++
++/* Status bits. */
++#define GET_STATUS_STATE(status) (((status) >> 6) & 0x03)
++#define KCS_IDLE_STATE 0
++#define KCS_READ_STATE 1
++#define KCS_WRITE_STATE 2
++#define KCS_ERROR_STATE 3
++#define GET_STATUS_ATN(status) ((status) & 0x04)
++#define GET_STATUS_IBF(status) ((status) & 0x02)
++#define GET_STATUS_OBF(status) ((status) & 0x01)
++
++
++static inline void write_next_byte(struct kcs_data *kcs)
++{
++ write_data(kcs, kcs->write_data[kcs->write_pos]);
++ (kcs->write_pos)++;
++ (kcs->write_count)--;
++}
++
++static inline void start_error_recovery(struct kcs_data *kcs, char *reason)
++{
++ (kcs->error_retries)++;
++ if (kcs->error_retries > MAX_ERROR_RETRIES) {
++#ifdef DEBUG_HOSED_REASON
++ printk("ipmi_kcs_sm: kcs hosed: %s\n", reason);
++#endif
++ kcs->state = KCS_HOSED;
++ } else {
++ kcs->state = KCS_ERROR0;
++ }
++}
++
++static inline void read_next_byte(struct kcs_data *kcs)
++{
++ if (kcs->read_pos >= MAX_KCS_READ_SIZE) {
++ /* Throw the data away and mark it truncated. */
++ read_data(kcs);
++ kcs->truncated = 1;
++ } else {
++ kcs->read_data[kcs->read_pos] = read_data(kcs);
++ (kcs->read_pos)++;
++ }
++ write_data(kcs, KCS_READ_BYTE);
++}
++
++static inline int check_ibf(struct kcs_data *kcs,
++ unsigned char status,
++ long time)
++{
++ if (GET_STATUS_IBF(status)) {
++ kcs->ibf_timeout -= time;
++ if (kcs->ibf_timeout < 0) {
++ start_error_recovery(kcs, "IBF not ready in time");
++ kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
++ return 1;
++ }
++ return 0;
++ }
++ kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
++ return 1;
++}
++
++static inline int check_obf(struct kcs_data *kcs,
++ unsigned char status,
++ long time)
++{
++ if (! GET_STATUS_OBF(status)) {
++ kcs->obf_timeout -= time;
++ if (kcs->obf_timeout < 0) {
++ start_error_recovery(kcs, "OBF not ready in time");
++ return 1;
++ }
++ return 0;
++ }
++ kcs->obf_timeout = OBF_RETRY_TIMEOUT;
++ return 1;
++}
++
++static void clear_obf(struct kcs_data *kcs, unsigned char status)
++{
++ if (GET_STATUS_OBF(status))
++ read_data(kcs);
++}
++
++static void restart_kcs_transaction(struct kcs_data *kcs)
++{
++ kcs->write_count = kcs->orig_write_count;
++ kcs->write_pos = 0;
++ kcs->read_pos = 0;
++ kcs->state = KCS_WAIT_WRITE_START;
++ kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
++ kcs->obf_timeout = OBF_RETRY_TIMEOUT;
++ write_cmd(kcs, KCS_WRITE_START);
++}
++
++int start_kcs_transaction(struct kcs_data *kcs, char *data, unsigned int size)
++{
++ if ((size < 2) || (size > MAX_KCS_WRITE_SIZE)) {
++ return -1;
++ }
++
++ if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED)) {
++ return -2;
++ }
++
++ kcs->error_retries = 0;
++ memcpy(kcs->write_data, data, size);
++ kcs->write_count = size;
++ kcs->orig_write_count = size;
++ kcs->write_pos = 0;
++ kcs->read_pos = 0;
++ kcs->state = KCS_START_OP;
++ kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
++ kcs->obf_timeout = OBF_RETRY_TIMEOUT;
++ return 0;
++}
++
++int kcs_get_result(struct kcs_data *kcs, unsigned char *data, int length)
++{
++ if (length < kcs->read_pos) {
++ kcs->read_pos = length;
++ kcs->truncated = 1;
++ }
++
++ memcpy(data, kcs->read_data, kcs->read_pos);
++
++ if ((length >= 3) && (kcs->read_pos < 3)) {
++ /* Guarantee that we return at least 3 bytes, with an
++ error in the third byte if it is too short. */
++ data[2] = IPMI_ERR_UNSPECIFIED;
++ kcs->read_pos = 3;
++ }
++ if (kcs->truncated) {
++ /* Report a truncated error. We might overwrite
++ another error, but that's too bad, the user needs
++ to know it was truncated. */
++ data[2] = IPMI_ERR_MSG_TRUNCATED;
++ kcs->truncated = 0;
++ }
++
++ return kcs->read_pos;
++}
++
++/* This implements the state machine defined in the IPMI manual, see
++ that for details on how this works. Divide that flowchart into
++ sections delimited by "Wait for IBF" and this will become clear. */
++enum kcs_result kcs_event(struct kcs_data *kcs, long time)
++{
++ unsigned char status;
++ unsigned char state;
++
++ status = read_status(kcs);
++
++#ifdef DEBUG_STATE
++ printk(" State = %d, %x\n", kcs->state, status);
++#endif
++ /* All states wait for ibf, so just do it here. */
++ if (!check_ibf(kcs, status, time))
++ return KCS_CALL_WITH_DELAY;
++
++ /* Just about everything looks at the KCS state, so grab that, too. */
++ state = GET_STATUS_STATE(status);
++
++ switch (kcs->state) {
++ case KCS_IDLE:
++ /* If there's and interrupt source, turn it off. */
++ clear_obf(kcs, status);
++
++ if (GET_STATUS_ATN(status))
++ return KCS_ATTN;
++ else
++ return KCS_SM_IDLE;
++
++ case KCS_START_OP:
++ if (state != KCS_IDLE) {
++ start_error_recovery(kcs,
++ "State machine not idle at start");
++ break;
++ }
++
++ clear_obf(kcs, status);
++ write_cmd(kcs, KCS_WRITE_START);
++ kcs->state = KCS_WAIT_WRITE_START;
++ break;
++
++ case KCS_WAIT_WRITE_START:
++ if (state != KCS_WRITE_STATE) {
++ start_error_recovery(
++ kcs,
++ "Not in write state at write start");
++ break;
++ }
++ read_data(kcs);
++ if (kcs->write_count == 1) {
++ write_cmd(kcs, KCS_WRITE_END);
++ kcs->state = KCS_WAIT_WRITE_END;
++ } else {
++ write_next_byte(kcs);
++ kcs->state = KCS_WAIT_WRITE;
++ }
++ break;
++
++ case KCS_WAIT_WRITE:
++ if (state != KCS_WRITE_STATE) {
++ start_error_recovery(kcs,
++ "Not in write state for write");
++ break;
++ }
++ clear_obf(kcs, status);
++ if (kcs->write_count == 1) {
++ write_cmd(kcs, KCS_WRITE_END);
++ kcs->state = KCS_WAIT_WRITE_END;
++ } else {
++ write_next_byte(kcs);
++ }
++ break;
++
++ case KCS_WAIT_WRITE_END:
++ if (state != KCS_WRITE_STATE) {
++ start_error_recovery(kcs,
++ "Not in write state for write end");
++ break;
++ }
++ clear_obf(kcs, status);
++ write_next_byte(kcs);
++ kcs->state = KCS_WAIT_READ;
++ break;
++
++ case KCS_WAIT_READ:
++ if ((state != KCS_READ_STATE) && (state != KCS_IDLE_STATE)) {
++ start_error_recovery(
++ kcs,
++ "Not in read or idle in read state");
++ break;
++ }
++
++ if (state == KCS_READ_STATE) {
++ if (! check_obf(kcs, status, time))
++ return KCS_CALL_WITH_DELAY;
++ read_next_byte(kcs);
++ } else {
++ /* We don't implement this exactly like the state
++ machine in the spec. Some broken hardware
++ does not write the final dummy byte to the
++ read register. Thus obf will never go high
++ here. We just go straight to idle, and we
++ handle clearing out obf in idle state if it
++ happens to come in. */
++ clear_obf(kcs, status);
++ kcs->orig_write_count = 0;
++ kcs->state = KCS_IDLE;
++ return KCS_TRANSACTION_COMPLETE;
++ }
++ break;
++
++ case KCS_ERROR0:
++ clear_obf(kcs, status);
++ write_cmd(kcs, KCS_GET_STATUS_ABORT);
++ kcs->state = KCS_ERROR1;
++ break;
++
++ case KCS_ERROR1:
++ clear_obf(kcs, status);
++ write_data(kcs, 0);
++ kcs->state = KCS_ERROR2;
++ break;
++
++ case KCS_ERROR2:
++ if (state != KCS_READ_STATE) {
++ start_error_recovery(kcs,
++ "Not in read state for error2");
++ break;
++ }
++ if (! check_obf(kcs, status, time))
++ return KCS_CALL_WITH_DELAY;
++
++ clear_obf(kcs, status);
++ write_data(kcs, KCS_READ_BYTE);
++ kcs->state = KCS_ERROR3;
++ break;
++
++ case KCS_ERROR3:
++ if (state != KCS_IDLE_STATE) {
++ start_error_recovery(kcs,
++ "Not in idle state for error3");
++ break;
++ }
++
++ if (! check_obf(kcs, status, time))
++ return KCS_CALL_WITH_DELAY;
++
++ clear_obf(kcs, status);
++ if (kcs->orig_write_count) {
++ restart_kcs_transaction(kcs);
++ } else {
++ kcs->state = KCS_IDLE;
++ return KCS_TRANSACTION_COMPLETE;
++ }
++ break;
++
++ case KCS_HOSED:
++ return KCS_SM_HOSED;
++ }
++
++ if (kcs->state == KCS_HOSED) {
++ init_kcs_data(kcs, kcs->port, kcs->addr);
++ return KCS_SM_HOSED;
++ }
++
++ return KCS_CALL_WITHOUT_DELAY;
++}
++
++int kcs_size(void)
++{
++ return sizeof(struct kcs_data);
++}
+diff -urN linux.orig/drivers/char/ipmi/ipmi_kcs_sm.h linux/drivers/char/ipmi/ipmi_kcs_sm.h
+--- linux.orig/drivers/char/ipmi/ipmi_kcs_sm.h Wed Dec 31 18:00:00 1969
++++ linux/drivers/char/ipmi/ipmi_kcs_sm.h Thu Oct 31 17:26:33 2002
+@@ -0,0 +1,70 @@
++/*
++ * ipmi_kcs_sm.h
++ *
++ * State machine for handling IPMI KCS interfaces.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++struct kcs_data;
++
++void init_kcs_data(struct kcs_data *kcs,
++ unsigned int port,
++ unsigned char *addr);
++
++/* Start a new transaction in the state machine. This will return -2
++ if the state machine is not idle, -1 if the size is invalid (to
++ large or too small), or 0 if the transaction is successfully
++ completed. */
++int start_kcs_transaction(struct kcs_data *kcs, char *data, unsigned int size);
++
++/* Return the results after the transaction. This will return -1 if
++ the buffer is too small, zero if no transaction is present, or the
++ actual length of the result data. */
++int kcs_get_result(struct kcs_data *kcs, unsigned char *data, int length);
++
++enum kcs_result
++{
++ KCS_CALL_WITHOUT_DELAY, /* Call the driver again immediately */
++ KCS_CALL_WITH_DELAY, /* Delay some before calling again. */
++ KCS_TRANSACTION_COMPLETE, /* A transaction is finished. */
++ KCS_SM_IDLE, /* The SM is in idle state. */
++ KCS_SM_HOSED, /* The hardware violated the state machine. */
++ KCS_ATTN /* The hardware is asserting attn and the
++ state machine is idle. */
++};
++
++/* Call this periodically (for a polled interface) or upon receiving
++ an interrupt (for a interrupt-driven interface). If interrupt
++ driven, you should probably poll this periodically when not in idle
++ state. This should be called with the time that passed since the
++ last call, if it is significant. Time is in microseconds. */
++enum kcs_result kcs_event(struct kcs_data *kcs, long time);
++
++/* Return the size of the KCS structure in bytes. */
++int kcs_size(void);
+diff -urN linux.orig/drivers/char/ipmi/ipmi_msghandler.c linux/drivers/char/ipmi/ipmi_msghandler.c
+--- linux.orig/drivers/char/ipmi/ipmi_msghandler.c Wed Dec 31 18:00:00 1969
++++ linux/drivers/char/ipmi/ipmi_msghandler.c Mon Jan 13 12:01:34 2003
+@@ -0,0 +1,1984 @@
++/*
++ * ipmi_msghandler.c
++ *
++ * Incoming and outgoing message routing for an IPMI interface.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <asm/system.h>
++#include <linux/sched.h>
++#include <linux/poll.h>
++#include <linux/spinlock.h>
++#include <linux/rwsem.h>
++#include <linux/slab.h>
++#include <linux/ipmi.h>
++#include <linux/ipmi_smi.h>
++#include <linux/notifier.h>
++#include <linux/init.h>
++
++struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
++static int ipmi_init_msghandler(void);
++
++static int initialized = 0;
++
++#define MAX_EVENTS_IN_QUEUE 25
++
++/* Don't let a message sit in a queue forever, always time it with at lest
++ the max message timer. */
++#define MAX_MSG_TIMEOUT 60000
++
++struct ipmi_user
++{
++ struct list_head link;
++
++ /* The upper layer that handles receive messages. */
++ struct ipmi_user_hndl *handler;
++ void *handler_data;
++
++ /* The interface this user is bound to. */
++ ipmi_smi_t intf;
++
++ /* Does this interface receive IPMI events? */
++ int gets_events;
++};
++
++struct cmd_rcvr
++{
++ struct list_head link;
++
++ ipmi_user_t user;
++ unsigned char netfn;
++ unsigned char cmd;
++};
++
++struct seq_table
++{
++ int inuse : 1;
++
++ unsigned long timeout;
++ unsigned long orig_timeout;
++ unsigned int retries_left;
++
++ /* To verify on an incoming send message response that this is
++ the message that the response is for, we keep a sequence id
++ and increment it every time we send a message. */
++ long seqid;
++
++ /* This is held so we can properly respond to the message on a
++ timeout, and it is used to hold the temporary data for
++ retransmission, too. */
++ struct ipmi_recv_msg *recv_msg;
++};
++
++/* Store the information in a msgid (long) to allow us to find a
++ sequence table entry from the msgid. */
++#define STORE_SEQ_IN_MSGID(seq, seqid) (((seq&0xff)<<26) | (seqid&0x3ffffff))
++
++#define GET_SEQ_FROM_MSGID(msgid, seq, seqid) \
++ do { \
++ seq = ((msgid >> 26) & 0x3f); \
++ seqid = (msgid & 0x3fffff); \
++ } while(0)
++
++#define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3fffff)
++
++
++#define IPMI_IPMB_NUM_SEQ 64
++struct ipmi_smi
++{
++ /* The list of upper layers that are using me. We read-lock
++ this when delivering messages to the upper layer to keep
++ the user from going away while we are processing the
++ message. This means that you cannot add or delete a user
++ from the receive callback. */
++ rwlock_t users_lock;
++ struct list_head users;
++
++ /* The IPMI version of the BMC on the other end. */
++ unsigned char version_major;
++ unsigned char version_minor;
++
++ /* This is the lower-layer's sender routine. */
++ struct ipmi_smi_handlers *handlers;
++ void *send_info;
++
++ /* A table of sequence numbers for this interface. We use the
++ sequence numbers for IPMB messages that go out of the
++ interface to match them up with their responses. A routine
++ is called periodically to time the items in this list. */
++ spinlock_t seq_lock;
++ struct seq_table seq_table[IPMI_IPMB_NUM_SEQ];
++ int curr_seq;
++
++ /* Messages that were delayed for some reason (out of memory,
++ for instance), will go in here to be processed later in a
++ periodic timer interrupt. */
++ spinlock_t waiting_msgs_lock;
++ struct list_head waiting_msgs;
++
++ /* The list of command receivers that are registered for commands
++ on this interface. */
++ rwlock_t cmd_rcvr_lock;
++ struct list_head cmd_rcvrs;
++
++ /* Events that were queues because no one was there to receive
++ them. */
++ spinlock_t events_lock; /* For dealing with event stuff. */
++ struct list_head waiting_events;
++ unsigned int waiting_events_count; /* How many events in queue? */
++
++ /* This will be non-null if someone registers to receive all
++ IPMI commands (this is for interface emulation). There
++ may not be any things in the cmd_rcvrs list above when
++ this is registered. */
++ ipmi_user_t all_cmd_rcvr;
++
++ /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR,
++ but may be changed by the user. */
++ unsigned char my_address;
++
++ /* My LUN. This should generally stay the SMS LUN, but just in
++ case... */
++ unsigned char my_lun;
++};
++
++int
++ipmi_register_all_cmd_rcvr(ipmi_user_t user)
++{
++ int flags;
++ int rv = -EBUSY;
++
++ write_lock_irqsave(&(user->intf->users_lock), flags);
++ write_lock(&(user->intf->cmd_rcvr_lock));
++ if ((user->intf->all_cmd_rcvr == NULL)
++ && (list_empty(&(user->intf->cmd_rcvrs))))
++ {
++ user->intf->all_cmd_rcvr = user;
++ rv = 0;
++ }
++ write_unlock(&(user->intf->cmd_rcvr_lock));
++ write_unlock_irqrestore(&(user->intf->users_lock), flags);
++ return rv;
++}
++
++int
++ipmi_unregister_all_cmd_rcvr(ipmi_user_t user)
++{
++ int flags;
++ int rv = -EINVAL;
++
++ write_lock_irqsave(&(user->intf->users_lock), flags);
++ write_lock(&(user->intf->cmd_rcvr_lock));
++ if (user->intf->all_cmd_rcvr == user)
++ {
++ user->intf->all_cmd_rcvr = NULL;
++ rv = 0;
++ }
++ write_unlock(&(user->intf->cmd_rcvr_lock));
++ write_unlock_irqrestore(&(user->intf->users_lock), flags);
++ return rv;
++}
++
++
++#define MAX_IPMI_INTERFACES 4
++static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES];
++
++/* Used to keep interfaces from going away while operations are
++ operating on interfaces. Grab read if you are not modifying the
++ interfaces, write if you are. */
++static DECLARE_RWSEM(interfaces_sem);
++
++/* Directly protects the ipmi_interfaces data structure. This is
++ claimed in the timer interrupt. */
++static spinlock_t interfaces_lock = SPIN_LOCK_UNLOCKED;
++
++/* List of watchers that want to know when smi's are added and
++ deleted. */
++static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers);
++static DECLARE_RWSEM(smi_watchers_sem);
++
++int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
++{
++ int i;
++
++ down_read(&interfaces_sem);
++ down_write(&smi_watchers_sem);
++ list_add(&(watcher->link), &smi_watchers);
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ if (ipmi_interfaces[i] != NULL) {
++ watcher->new_smi(i);
++ }
++ }
++ up_write(&smi_watchers_sem);
++ up_read(&interfaces_sem);
++ return 0;
++}
++
++int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher)
++{
++ down_write(&smi_watchers_sem);
++ list_del(&(watcher->link));
++ up_write(&smi_watchers_sem);
++ return 0;
++}
++
++int
++ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2)
++{
++ if (addr1->addr_type != addr2->addr_type)
++ return 0;
++
++ if (addr1->channel != addr2->channel)
++ return 0;
++
++ if (addr1->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {
++ struct ipmi_system_interface_addr *smi_addr1
++ = (struct ipmi_system_interface_addr *) addr1;
++ struct ipmi_system_interface_addr *smi_addr2
++ = (struct ipmi_system_interface_addr *) addr2;
++ return (smi_addr1->lun == smi_addr2->lun);
++ }
++
++ if ((addr1->addr_type == IPMI_IPMB_ADDR_TYPE)
++ || (addr1->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
++ {
++ struct ipmi_ipmb_addr *ipmb_addr1
++ = (struct ipmi_ipmb_addr *) addr1;
++ struct ipmi_ipmb_addr *ipmb_addr2
++ = (struct ipmi_ipmb_addr *) addr2;
++
++ return ((ipmb_addr1->slave_addr == ipmb_addr2->slave_addr)
++ && (ipmb_addr1->lun == ipmb_addr2->lun));
++ }
++
++ return 1;
++}
++
++int ipmi_validate_addr(struct ipmi_addr *addr, int len)
++{
++ if (len < sizeof(struct ipmi_system_interface_addr)) {
++ return -EINVAL;
++ }
++
++ if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {
++ if (addr->channel != IPMI_BMC_CHANNEL)
++ return -EINVAL;
++ return 0;
++ }
++
++ if ((addr->channel == IPMI_BMC_CHANNEL)
++ || (addr->channel >= IPMI_NUM_CHANNELS)
++ || (addr->channel < 0))
++ return -EINVAL;
++
++ if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)
++ || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
++ {
++ if (len < sizeof(struct ipmi_ipmb_addr)) {
++ return -EINVAL;
++ }
++ return 0;
++ }
++
++ return -EINVAL;
++}
++
++unsigned int ipmi_addr_length(int addr_type)
++{
++ if (addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
++ return sizeof(struct ipmi_system_interface_addr);
++
++ if ((addr_type == IPMI_IPMB_ADDR_TYPE)
++ || (addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
++ {
++ return sizeof(struct ipmi_ipmb_addr);
++ }
++
++ return 0;
++}
++
++static void deliver_response(struct ipmi_recv_msg *msg)
++{
++ msg->user->handler->ipmi_recv_hndl(msg, msg->user->handler_data);
++}
++
++/* Find the next sequence number not being used and add the given
++ message with the given timeout to the sequence table. This must be
++ called with the interface's seq_lock held. */
++static int intf_next_seq(ipmi_smi_t intf,
++ struct ipmi_recv_msg *recv_msg,
++ unsigned long timeout,
++ int retries,
++ unsigned char *seq,
++ long *seqid)
++{
++ int rv = 0;
++ unsigned int i;
++
++ for (i=intf->curr_seq;
++ i!=(intf->curr_seq-1);
++ i=(i+1)%IPMI_IPMB_NUM_SEQ)
++ {
++ if (! intf->seq_table[i].inuse)
++ break;
++ }
++
++ if (! intf->seq_table[i].inuse) {
++ intf->seq_table[i].recv_msg = recv_msg;
++
++ /* Start with the maximum timeout, when the send response
++ comes in we will start the real timer. */
++ intf->seq_table[i].timeout = MAX_MSG_TIMEOUT;
++ intf->seq_table[i].orig_timeout = timeout;
++ intf->seq_table[i].retries_left = retries;
++ intf->seq_table[i].inuse = 1;
++ intf->seq_table[i].seqid = NEXT_SEQID(intf->seq_table[i].seqid);
++ *seq = i;
++ *seqid = intf->seq_table[i].seqid;
++ intf->curr_seq = (i+1)%IPMI_IPMB_NUM_SEQ;
++ } else {
++ rv = -EAGAIN;
++ }
++
++ return rv;
++}
++
++/* Return the receive message for the given sequence number and
++ release the sequence number so it can be reused. Some other data
++ is passed in to be sure the message matches up correctly (to help
++ guard against message coming in after their timeout and the
++ sequence number being reused). */
++static int intf_find_seq(ipmi_smi_t intf,
++ unsigned char seq,
++ short channel,
++ unsigned char cmd,
++ unsigned char netfn,
++ struct ipmi_addr *addr,
++ struct ipmi_recv_msg **recv_msg)
++{
++ int rv = -ENODEV;
++ unsigned long flags;
++
++ if (seq >= IPMI_IPMB_NUM_SEQ)
++ return -EINVAL;
++
++ spin_lock_irqsave(&(intf->seq_lock), flags);
++ if (intf->seq_table[seq].inuse) {
++ struct ipmi_recv_msg *msg = intf->seq_table[seq].recv_msg;
++
++ if ((msg->addr.channel == channel)
++ && (msg->msg.cmd == cmd)
++ && (msg->msg.netfn == netfn)
++ && (ipmi_addr_equal(addr, &(msg->addr))))
++ {
++ *recv_msg = msg;
++ intf->seq_table[seq].inuse = 0;
++ rv = 0;
++ }
++ }
++ spin_unlock_irqrestore(&(intf->seq_lock), flags);
++
++ return rv;
++}
++
++
++/* Start the timer for a specific sequence table entry. */
++static int intf_start_seq_timer(ipmi_smi_t intf,
++ long msgid)
++{
++ int rv = -ENODEV;
++ unsigned long flags;
++ unsigned char seq;
++ unsigned long seqid;
++
++
++ GET_SEQ_FROM_MSGID(msgid, seq, seqid);
++
++ spin_lock_irqsave(&(intf->seq_lock), flags);
++ /* We do this verification because the user can be deleted
++ while a message is outstanding. */
++ if ((intf->seq_table[seq].inuse)
++ && (intf->seq_table[seq].seqid == seqid))
++ {
++ struct seq_table *ent = &(intf->seq_table[seq]);
++ ent->timeout = ent->orig_timeout;
++ }
++ spin_unlock_irqrestore(&(intf->seq_lock), flags);
++
++ return rv;
++}
++
++
++int ipmi_create_user(unsigned int if_num,
++ struct ipmi_user_hndl *handler,
++ void *handler_data,
++ ipmi_user_t *user)
++{
++ unsigned long flags;
++ ipmi_user_t new_user;
++ int rv = 0;
++
++ /* There is no module usecount here, because it's not
++ required. Since this can only be used by and called from
++ other modules, they will implicitly use this module, and
++ thus this can't be removed unless the other modules are
++ removed. */
++
++ if (handler == NULL)
++ return -EINVAL;
++
++ /* Make sure the driver is actually initialized, this handles
++ problems with initialization order. */
++ if (!initialized) {
++ rv = ipmi_init_msghandler();
++ if (rv)
++ return rv;
++
++ /* The init code doesn't return an error if it was turned
++ off, but it won't initialize. Check that. */
++ if (!initialized)
++ return -ENODEV;
++ }
++
++ new_user = kmalloc(sizeof(*new_user), GFP_KERNEL);
++ if (! new_user)
++ return -ENOMEM;
++
++ down_read(&interfaces_sem);
++ if ((if_num > MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)
++ {
++ rv = -EINVAL;
++ goto out_unlock;
++ }
++
++ new_user->handler = handler;
++ new_user->handler_data = handler_data;
++ new_user->intf = ipmi_interfaces[if_num];
++ new_user->gets_events = 0;
++
++ rv = new_user->intf->handlers->new_user(new_user->intf->send_info);
++ if (rv)
++ goto out_unlock;
++
++ write_lock_irqsave(&(new_user->intf->users_lock), flags);
++ list_add_tail(&(new_user->link), &(new_user->intf->users));
++ write_unlock_irqrestore(&(new_user->intf->users_lock), flags);
++
++ out_unlock:
++ if (rv) {
++ kfree(new_user);
++ } else {
++ *user = new_user;
++ }
++
++ up_read(&interfaces_sem);
++ return rv;
++}
++
++static int ipmi_destroy_user_nolock(ipmi_user_t user)
++{
++ int rv = -ENODEV;
++ ipmi_user_t t_user;
++ struct list_head *entry, *entry2;
++ int i;
++ unsigned long flags;
++
++ /* Find the user and delete them from the list. */
++ list_for_each(entry, &(user->intf->users)) {
++ t_user = list_entry(entry, struct ipmi_user, link);
++ if (t_user == user) {
++ list_del(entry);
++ rv = 0;
++ break;
++ }
++ }
++
++ if (rv) {
++ goto out_unlock;
++ }
++
++ /* Remove the user from the interfaces sequence table. */
++ spin_lock_irqsave(&(user->intf->seq_lock), flags);
++ for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) {
++ if (user->intf->seq_table[i].inuse
++ && (user->intf->seq_table[i].recv_msg->user == user))
++ {
++ user->intf->seq_table[i].inuse = 0;
++ }
++ }
++ spin_unlock_irqrestore(&(user->intf->seq_lock), flags);
++
++ /* Remove the user from the command receiver's table. */
++ write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
++ list_for_each_safe(entry, entry2, &(user->intf->cmd_rcvrs)) {
++ struct cmd_rcvr *rcvr;
++ rcvr = list_entry(entry, struct cmd_rcvr, link);
++ if (rcvr->user == user) {
++ list_del(entry);
++ kfree(rcvr);
++ }
++ }
++ write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
++
++ kfree(user);
++
++ out_unlock:
++
++ return rv;
++}
++
++int ipmi_destroy_user(ipmi_user_t user)
++{
++ int rv;
++ ipmi_smi_t intf = user->intf;
++ unsigned long flags;
++
++ down_read(&interfaces_sem);
++ write_lock_irqsave(&(intf->users_lock), flags);
++ rv = ipmi_destroy_user_nolock(user);
++ if (!rv)
++ intf->handlers->user_left(intf->send_info);
++
++ write_unlock_irqrestore(&(intf->users_lock), flags);
++ up_read(&interfaces_sem);
++ return rv;
++}
++
++void ipmi_get_version(ipmi_user_t user,
++ unsigned char *major,
++ unsigned char *minor)
++{
++ *major = user->intf->version_major;
++ *minor = user->intf->version_minor;
++}
++
++void ipmi_set_my_address(ipmi_user_t user,
++ unsigned char address)
++{
++ user->intf->my_address = address;
++}
++
++unsigned char ipmi_get_my_address(ipmi_user_t user)
++{
++ return user->intf->my_address;
++}
++
++void ipmi_set_my_LUN(ipmi_user_t user,
++ unsigned char LUN)
++{
++ user->intf->my_lun = LUN & 0x3;
++}
++
++unsigned char ipmi_get_my_LUN(ipmi_user_t user)
++{
++ return user->intf->my_lun;
++}
++
++int ipmi_set_gets_events(ipmi_user_t user, int val)
++{
++ unsigned long flags;
++ struct list_head *e, *e2;
++ struct ipmi_recv_msg *msg;
++
++ read_lock(&(user->intf->users_lock));
++ spin_lock_irqsave(&(user->intf->events_lock), flags);
++ user->gets_events = val;
++
++ if (val) {
++ /* Deliver any queued events. */
++ list_for_each_safe(e, e2, &(user->intf->waiting_events)) {
++ msg = list_entry(e, struct ipmi_recv_msg, link);
++ list_del(e);
++ msg->user = user;
++ deliver_response(msg);
++ }
++ }
++
++ spin_unlock_irqrestore(&(user->intf->events_lock), flags);
++ read_unlock(&(user->intf->users_lock));
++
++ return 0;
++}
++
++int ipmi_register_for_cmd(ipmi_user_t user,
++ unsigned char netfn,
++ unsigned char cmd)
++{
++ struct list_head *entry;
++ unsigned long flags;
++ struct cmd_rcvr *rcvr;
++ int rv = 0;
++
++
++ rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL);
++ if (! rcvr)
++ return -ENOMEM;
++
++ read_lock(&(user->intf->users_lock));
++ write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
++ if (user->intf->all_cmd_rcvr != NULL) {
++ rv = -EBUSY;
++ goto out_unlock;
++ }
++
++ /* Make sure the command/netfn is not already registered. */
++ list_for_each(entry, &(user->intf->cmd_rcvrs)) {
++ struct cmd_rcvr *cmp;
++ cmp = list_entry(entry, struct cmd_rcvr, link);
++ if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) {
++ rv = -EBUSY;
++ break;
++ }
++ }
++
++ if (! rv) {
++ rcvr->cmd = cmd;
++ rcvr->netfn = netfn;
++ rcvr->user = user;
++ list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs));
++ }
++ out_unlock:
++ write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
++ read_unlock(&(user->intf->users_lock));
++
++ if (rv)
++ kfree(rcvr);
++
++ return rv;
++}
++
++int ipmi_unregister_for_cmd(ipmi_user_t user,
++ unsigned char netfn,
++ unsigned char cmd)
++{
++ struct list_head *entry;
++ unsigned long flags;
++ struct cmd_rcvr *rcvr;
++ int rv = -ENOENT;
++
++ read_lock(&(user->intf->users_lock));
++ write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
++ /* Make sure the command/netfn is not already registered. */
++ list_for_each(entry, &(user->intf->cmd_rcvrs)) {
++ rcvr = list_entry(entry, struct cmd_rcvr, link);
++ if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
++ rv = 0;
++ list_del(entry);
++ kfree(rcvr);
++ break;
++ }
++ }
++ write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
++ read_unlock(&(user->intf->users_lock));
++
++ return rv;
++}
++
++static unsigned char
++ipmb_checksum(unsigned char *data, int size)
++{
++ unsigned char csum = 0;
++
++ for (; size > 0; size--, data++)
++ csum += *data;
++
++ return -csum;
++}
++
++static inline void format_ipmb_msg(struct ipmi_smi_msg *smi_msg,
++ struct ipmi_msg *msg,
++ struct ipmi_ipmb_addr *ipmb_addr,
++ long msgid,
++ unsigned char ipmb_seq,
++ int broadcast,
++ unsigned char source_address,
++ unsigned char source_lun)
++{
++ int i = broadcast;
++
++ /* Format the IPMB header data. */
++ smi_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ smi_msg->data[1] = IPMI_SEND_MSG_CMD;
++ smi_msg->data[2] = ipmb_addr->channel;
++ if (broadcast)
++ smi_msg->data[3] = 0;
++ smi_msg->data[i+3] = ipmb_addr->slave_addr;
++ smi_msg->data[i+4] = (msg->netfn << 2) | (ipmb_addr->lun & 0x3);
++ smi_msg->data[i+5] = ipmb_checksum(&(smi_msg->data[i+3]), 2);
++ smi_msg->data[i+6] = source_address;
++ smi_msg->data[i+7] = (ipmb_seq << 2) | source_lun;
++ smi_msg->data[i+8] = msg->cmd;
++
++ /* Now tack on the data to the message. */
++ if (msg->data_len > 0)
++ memcpy(&(smi_msg->data[i+9]), msg->data,
++ msg->data_len);
++ smi_msg->data_size = msg->data_len + 9;
++
++ /* Now calculate the checksum and tack it on. */
++ smi_msg->data[i+smi_msg->data_size]
++ = ipmb_checksum(&(smi_msg->data[i+6]),
++ smi_msg->data_size-6);
++
++ /* Add on the checksum size and the offset from the
++ broadcast. */
++ smi_msg->data_size += 1 + i;
++
++ smi_msg->msgid = msgid;
++}
++
++/* Separate from ipmi_request so that the user does not have to be
++ supplied in certain circumstances (mainly at panic time). If
++ messages are supplied, they will be freed, even if an error
++ occurs. */
++static inline int i_ipmi_request(ipmi_user_t user,
++ ipmi_smi_t intf,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ void *supplied_smi,
++ struct ipmi_recv_msg *supplied_recv,
++ int priority,
++ unsigned char source_address,
++ unsigned char source_lun)
++{
++ int rv = 0;
++ struct ipmi_smi_msg *smi_msg;
++ struct ipmi_recv_msg *recv_msg;
++ unsigned long flags;
++
++
++ if (supplied_recv) {
++ recv_msg = supplied_recv;
++ } else {
++ recv_msg = ipmi_alloc_recv_msg();
++ if (recv_msg == NULL) {
++ return -ENOMEM;
++ }
++ }
++
++ if (supplied_smi) {
++ smi_msg = (struct ipmi_smi_msg *) supplied_smi;
++ } else {
++ smi_msg = ipmi_alloc_smi_msg();
++ if (smi_msg == NULL) {
++ ipmi_free_recv_msg(recv_msg);
++ return -ENOMEM;
++ }
++ }
++
++ if (addr->channel > IPMI_NUM_CHANNELS) {
++ rv = -EINVAL;
++ goto out_err;
++ }
++
++ recv_msg->user = user;
++ recv_msg->msgid = msgid;
++ /* Store the message to send in the receive message so timeout
++ responses can get the proper response data. */
++ recv_msg->msg = *msg;
++
++ if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {
++ struct ipmi_system_interface_addr *smi_addr;
++
++
++ smi_addr = (struct ipmi_system_interface_addr *) addr;
++ if (smi_addr->lun > 3)
++ return -EINVAL;
++
++ memcpy(&recv_msg->addr, smi_addr, sizeof(*smi_addr));
++
++ if ((msg->netfn == IPMI_NETFN_APP_REQUEST)
++ && ((msg->cmd == IPMI_SEND_MSG_CMD)
++ || (msg->cmd == IPMI_GET_MSG_CMD)
++ || (msg->cmd == IPMI_READ_EVENT_MSG_BUFFER_CMD)))
++ {
++ /* We don't let the user do these, since we manage
++ the sequence numbers. */
++ rv = -EINVAL;
++ goto out_err;
++ }
++
++ if ((msg->data_len + 2) > IPMI_MAX_MSG_LENGTH) {
++ rv = -EMSGSIZE;
++ goto out_err;
++ }
++
++ smi_msg->data[0] = (msg->netfn << 2) | (smi_addr->lun & 0x3);
++ smi_msg->data[1] = msg->cmd;
++ smi_msg->msgid = msgid;
++ smi_msg->user_data = recv_msg;
++ if (msg->data_len > 0)
++ memcpy(&(smi_msg->data[2]), msg->data, msg->data_len);
++ smi_msg->data_size = msg->data_len + 2;
++ } else if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)
++ || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
++ {
++ struct ipmi_ipmb_addr *ipmb_addr;
++ unsigned char ipmb_seq;
++ long seqid;
++ int broadcast;
++ int retries;
++
++ if (addr == NULL) {
++ rv = -EINVAL;
++ goto out_err;
++ }
++
++ if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE) {
++ /* Broadcasts add a zero at the beginning of the
++ message, but otherwise is the same as an IPMB
++ address. */
++ addr->addr_type = IPMI_IPMB_ADDR_TYPE;
++ broadcast = 1;
++ retries = 0; /* Don't retry broadcasts. */
++ } else {
++ broadcast = 0;
++ retries = 4;
++ }
++
++ /* 9 for the header and 1 for the checksum, plus
++ possibly one for the broadcast. */
++ if ((msg->data_len + 10 + broadcast) > IPMI_MAX_MSG_LENGTH) {
++ rv = -EMSGSIZE;
++ goto out_err;
++ }
++
++ ipmb_addr = (struct ipmi_ipmb_addr *) addr;
++ if (ipmb_addr->lun > 3) {
++ rv = -EINVAL;
++ goto out_err;
++ }
++
++ memcpy(&recv_msg->addr, ipmb_addr, sizeof(*ipmb_addr));
++
++ if (recv_msg->msg.netfn & 0x1) {
++ /* It's a response, so use the user's sequence
++ from msgid. */
++ format_ipmb_msg(smi_msg, msg, ipmb_addr, msgid,
++ msgid, broadcast,
++ source_address, source_lun);
++ } else {
++ /* It's a command, so get a sequence for it. */
++
++ spin_lock_irqsave(&(intf->seq_lock), flags);
++
++ /* Create a sequence number with a 1 second
++ timeout and 4 retries. */
++ /* FIXME - magic number for the timeout. */
++ rv = intf_next_seq(intf,
++ recv_msg,
++ 1000,
++ retries,
++ &ipmb_seq,
++ &seqid);
++ if (rv) {
++ /* We have used up all the sequence numbers,
++ probably, so abort. */
++ spin_unlock_irqrestore(&(intf->seq_lock),
++ flags);
++ ipmi_free_recv_msg(recv_msg);
++ ipmi_free_smi_msg(smi_msg);
++ goto out_err;
++ }
++
++ /* Store the sequence number in the message,
++ so that when the send message response
++ comes back we can start the timer. */
++ format_ipmb_msg(smi_msg, msg, ipmb_addr,
++ STORE_SEQ_IN_MSGID(ipmb_seq, seqid),
++ ipmb_seq, broadcast,
++ source_address, source_lun);
++
++ /* Copy the message into the recv message data, so we
++ can retransmit it later if necessary. */
++ memcpy(recv_msg->msg_data, smi_msg->data,
++ smi_msg->data_size);
++ recv_msg->msg.data = recv_msg->msg_data;
++ recv_msg->msg.data_len = smi_msg->data_size;
++
++ /* We don't unlock until here, because we need
++ to copy the completed message into the
++ recv_msg before we release the lock.
++ Otherwise, race conditions may bite us. I
++ know that's pretty paranoid, but I prefer
++ to be correct. */
++ spin_unlock_irqrestore(&(intf->seq_lock), flags);
++ }
++ } else {
++ /* Unknown address type. */
++ rv = -EINVAL;
++ goto out_err;
++ }
++
++#if DEBUG_MSGING
++ {
++ int m;
++ for (m=0; m<smi_msg->data_size; m++)
++ printk(" %2.2x", smi_msg->data[m]);
++ printk("\n");
++ }
++#endif
++ intf->handlers->sender(intf->send_info, smi_msg, priority);
++
++ return 0;
++
++ out_err:
++ ipmi_free_smi_msg(smi_msg);
++ ipmi_free_recv_msg(recv_msg);
++ return rv;
++}
++
++int ipmi_request(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ int priority)
++{
++ return i_ipmi_request(user,
++ user->intf,
++ addr,
++ msgid,
++ msg,
++ NULL, NULL,
++ priority,
++ user->intf->my_address,
++ user->intf->my_lun);
++}
++
++int ipmi_request_supply_msgs(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ void *supplied_smi,
++ struct ipmi_recv_msg *supplied_recv,
++ int priority)
++{
++ return i_ipmi_request(user,
++ user->intf,
++ addr,
++ msgid,
++ msg,
++ supplied_smi,
++ supplied_recv,
++ priority,
++ user->intf->my_address,
++ user->intf->my_lun);
++}
++
++int ipmi_request_with_source(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ int priority,
++ unsigned char source_address,
++ unsigned char source_lun)
++{
++ return i_ipmi_request(user,
++ user->intf,
++ addr,
++ msgid,
++ msg,
++ NULL, NULL,
++ priority,
++ source_address,
++ source_lun);
++}
++
++int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
++ void *send_info,
++ unsigned char version_major,
++ unsigned char version_minor,
++ ipmi_smi_t *intf)
++{
++ int i, j;
++ int rv;
++ ipmi_smi_t new_intf;
++ struct list_head *entry;
++ unsigned int flags;
++
++
++ /* Make sure the driver is actually initialized, this handles
++ problems with initialization order. */
++ if (!initialized) {
++ rv = ipmi_init_msghandler();
++ if (rv)
++ return rv;
++ /* The init code doesn't return an error if it was turned
++ off, but it won't initialize. Check that. */
++ if (!initialized)
++ return -ENODEV;
++ }
++
++ new_intf = kmalloc(sizeof(*new_intf), GFP_KERNEL);
++ if (!new_intf)
++ return -ENOMEM;
++
++ rv = -ENOMEM;
++
++ down_write(&interfaces_sem);
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ if (ipmi_interfaces[i] == NULL) {
++ new_intf->version_major = version_major;
++ new_intf->version_minor = version_minor;
++ new_intf->my_address = IPMI_BMC_SLAVE_ADDR;
++ new_intf->my_lun = 2; /* the SMS LUN. */
++ rwlock_init(&(new_intf->users_lock));
++ INIT_LIST_HEAD(&(new_intf->users));
++ new_intf->handlers = handlers;
++ new_intf->send_info = send_info;
++ spin_lock_init(&(new_intf->seq_lock));
++ for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) {
++ new_intf->seq_table[j].inuse = 0;
++ new_intf->seq_table[j].seqid = 0;
++ }
++ new_intf->curr_seq = 0;
++ spin_lock_init(&(new_intf->waiting_msgs_lock));
++ INIT_LIST_HEAD(&(new_intf->waiting_msgs));
++ spin_lock_init(&(new_intf->events_lock));
++ INIT_LIST_HEAD(&(new_intf->waiting_events));
++ new_intf->waiting_events_count = 0;
++ rwlock_init(&(new_intf->cmd_rcvr_lock));
++ INIT_LIST_HEAD(&(new_intf->cmd_rcvrs));
++ new_intf->all_cmd_rcvr = NULL;
++
++ spin_lock_irqsave(&interfaces_lock, flags);
++ ipmi_interfaces[i] = new_intf;
++ spin_unlock_irqrestore(&interfaces_lock, flags);
++
++ rv = 0;
++ *intf = new_intf;
++ break;
++ }
++ }
++
++ /* We convert to a read semaphore here. It's possible the
++ interface was removed between the calls, we have to recheck
++ afterwards. */
++ up_write(&interfaces_sem);
++ down_read(&interfaces_sem);
++
++ if (ipmi_interfaces[i] != new_intf)
++ /* Well, it went away. Just return. */
++ goto out;
++
++ if (rv == 0) {
++ /* Call all the watcher interfaces to tell them that a
++ new interface is available. */
++ down_read(&smi_watchers_sem);
++ list_for_each(entry, &smi_watchers) {
++ struct ipmi_smi_watcher *w;
++ w = list_entry(entry, struct ipmi_smi_watcher, link);
++ w->new_smi(i);
++ }
++ up_read(&smi_watchers_sem);
++ }
++
++ out:
++ up_read(&interfaces_sem);
++
++ if (rv)
++ kfree(new_intf);
++
++ return rv;
++}
++
++static void free_recv_msg_list(struct list_head *q)
++{
++ struct list_head *entry, *entry2;
++ struct ipmi_recv_msg *msg;
++
++ list_for_each_safe(entry, entry2, q) {
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ list_del(entry);
++ ipmi_free_recv_msg(msg);
++ }
++}
++
++static void free_cmd_rcvr_list(struct list_head *q)
++{
++ struct list_head *entry, *entry2;
++ struct cmd_rcvr *rcvr;
++
++ list_for_each_safe(entry, entry2, q) {
++ rcvr = list_entry(entry, struct cmd_rcvr, link);
++ list_del(entry);
++ kfree(rcvr);
++ }
++}
++
++static void clean_up_interface_data(ipmi_smi_t intf)
++{
++ int i;
++
++ free_recv_msg_list(&(intf->waiting_msgs));
++ free_recv_msg_list(&(intf->waiting_events));
++ free_cmd_rcvr_list(&(intf->cmd_rcvrs));
++
++ for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) {
++ if ((intf->seq_table[i].inuse)
++ && (intf->seq_table[i].recv_msg))
++ {
++ ipmi_free_recv_msg(intf->seq_table[i].recv_msg);
++ }
++ }
++}
++
++int ipmi_unregister_smi(ipmi_smi_t intf)
++{
++ int rv = -ENODEV;
++ int i;
++ struct list_head *entry;
++ unsigned int flags;
++
++ down_write(&interfaces_sem);
++ if (list_empty(&(intf->users)))
++ {
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ if (ipmi_interfaces[i] == intf) {
++ spin_lock_irqsave(&interfaces_lock, flags);
++ ipmi_interfaces[i] = NULL;
++ clean_up_interface_data(intf);
++ spin_unlock_irqrestore(&interfaces_lock,flags);
++ kfree(intf);
++ rv = 0;
++ goto out_call_watcher;
++ }
++ }
++ } else {
++ rv = -EBUSY;
++ }
++ up_write(&interfaces_sem);
++
++ return rv;
++
++ out_call_watcher:
++ /* Convert to a read semaphore so callbacks don't bite us. */
++ up_write(&interfaces_sem);
++ down_read(&interfaces_sem);
++
++ /* Call all the watcher interfaces to tell them that
++ an interface is gone. */
++ down_read(&smi_watchers_sem);
++ list_for_each(entry, &smi_watchers) {
++ struct ipmi_smi_watcher *w;
++ w = list_entry(entry,
++ struct ipmi_smi_watcher,
++ link);
++ w->smi_gone(i);
++ }
++ up_read(&smi_watchers_sem);
++ up_read(&interfaces_sem);
++ return 0;
++}
++
++static int handle_get_msg_rsp(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ struct ipmi_ipmb_addr ipmb_addr;
++ struct ipmi_recv_msg *recv_msg;
++
++
++ if (msg->rsp_size < 11)
++ /* Message not big enough, just ignore it. */
++ return 0;
++
++ if (msg->rsp[2] != 0)
++ /* An error getting the response, just ignore it. */
++ return 0;
++
++ ipmb_addr.addr_type = IPMI_IPMB_ADDR_TYPE;
++ ipmb_addr.slave_addr = msg->rsp[6];
++ ipmb_addr.channel = msg->rsp[3] & 0x0f;
++ ipmb_addr.lun = msg->rsp[7] & 3;
++
++ /* It's a response from a remote entity. Look up the sequence
++ number and handle the response. */
++ if (intf_find_seq(intf,
++ msg->rsp[7] >> 2,
++ msg->rsp[3] & 0x0f,
++ msg->rsp[8],
++ (msg->rsp[4] >> 2) & (~1),
++ (struct ipmi_addr *) &(ipmb_addr),
++ &recv_msg))
++ {
++ /* We were unable to find the sequence number,
++ so just nuke the message. */
++ return 0;
++ }
++
++ memcpy(recv_msg->msg_data,
++ &(msg->rsp[9]),
++ msg->rsp_size - 9);
++ /* THe other fields matched, so no need to set them, except
++ for netfn, which needs to be the response that was
++ returned, not the request value. */
++ recv_msg->msg.netfn = msg->rsp[4] >> 2;
++ recv_msg->msg.data = recv_msg->msg_data;
++ recv_msg->msg.data_len = msg->rsp_size - 10;
++ recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
++ deliver_response(recv_msg);
++
++ return 0;
++}
++
++static int handle_get_msg_cmd(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ struct list_head *entry;
++ struct cmd_rcvr *rcvr;
++ int rv = 0;
++ unsigned char netfn;
++ unsigned char cmd;
++ ipmi_user_t user = NULL;
++ struct ipmi_ipmb_addr *ipmb_addr;
++ struct ipmi_recv_msg *recv_msg;
++
++ if (msg->rsp_size < 10)
++ /* Message not big enough, just ignore it. */
++ return 0;
++
++ if (msg->rsp[2] != 0) {
++ /* An error getting the response, just ignore it. */
++ return 0;
++ }
++
++ netfn = msg->rsp[4] >> 2;
++ cmd = msg->rsp[8];
++
++ read_lock(&(intf->cmd_rcvr_lock));
++
++ if (intf->all_cmd_rcvr) {
++ user = intf->all_cmd_rcvr;
++ } else {
++ /* Find the command/netfn. */
++ list_for_each(entry, &(intf->cmd_rcvrs)) {
++ rcvr = list_entry(entry, struct cmd_rcvr, link);
++ if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
++ user = rcvr->user;
++ break;
++ }
++ }
++ }
++ read_unlock(&(intf->cmd_rcvr_lock));
++
++ if (user == NULL) {
++ /* We didn't find a user, deliver an error response. */
++ msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg->data[1] = IPMI_SEND_MSG_CMD;
++ msg->data[2] = msg->rsp[3];
++ msg->data[3] = msg->rsp[6];
++ msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3);
++ msg->data[5] = ipmb_checksum(&(msg->data[3]), 2);
++ msg->data[6] = intf->my_address;
++ /* rqseq/lun */
++ msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3);
++ msg->data[8] = msg->rsp[8]; /* cmd */
++ msg->data[9] = IPMI_INVALID_CMD_COMPLETION_CODE;
++ msg->data[10] = ipmb_checksum(&(msg->data[6]), 4);
++ msg->data_size = 11;
++
++ intf->handlers->sender(intf->send_info, msg, 0);
++
++ rv = -1; /* We used the message, so return the value that
++ causes it to not be freed or queued. */
++ } else {
++ /* Deliver the message to the user. */
++ recv_msg = ipmi_alloc_recv_msg();
++ if (! recv_msg) {
++ /* We couldn't allocate memory for the
++ message, so requeue it for handling
++ later. */
++ rv = 1;
++ } else {
++ ipmb_addr = (struct ipmi_ipmb_addr *) &recv_msg->addr;
++ ipmb_addr->addr_type = IPMI_IPMB_ADDR_TYPE;
++ ipmb_addr->slave_addr = msg->rsp[6];
++ ipmb_addr->lun = msg->rsp[7] & 3;
++ ipmb_addr->channel = msg->rsp[3];
++
++ recv_msg->user = user;
++ recv_msg->recv_type = IPMI_CMD_RECV_TYPE;
++ recv_msg->msgid = msg->rsp[7] >> 2;
++ recv_msg->msg.netfn = msg->rsp[4] >> 2;
++ recv_msg->msg.cmd = msg->rsp[8];
++ recv_msg->msg.data = recv_msg->msg_data;
++ recv_msg->msg.data_len = msg->rsp_size - 10;
++ memcpy(recv_msg->msg_data,
++ &(msg->rsp[9]),
++ msg->rsp_size - 10);
++ deliver_response(recv_msg);
++ }
++ }
++
++ return rv;
++}
++
++static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg,
++ struct ipmi_smi_msg *msg)
++{
++ struct ipmi_system_interface_addr *smi_addr;
++
++ recv_msg->msgid = 0;
++ smi_addr = (struct ipmi_system_interface_addr *) &(recv_msg->addr);
++ smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr->channel = IPMI_BMC_CHANNEL;
++ smi_addr->lun = msg->rsp[0] & 3;
++ recv_msg->recv_type = IPMI_ASYNC_EVENT_RECV_TYPE;
++ recv_msg->msg.netfn = msg->rsp[0] >> 2;
++ recv_msg->msg.cmd = msg->rsp[1];
++ memcpy(recv_msg->msg_data, &(msg->rsp[3]), msg->rsp_size - 3);
++ recv_msg->msg.data = recv_msg->msg_data;
++ recv_msg->msg.data_len = msg->rsp_size - 3;
++}
++
++/* This will be called with the intf->users_lock read-locked, so no need
++ to do that here. */
++static int handle_read_event_rsp(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ struct ipmi_recv_msg *recv_msg;
++ struct list_head msgs;
++ struct list_head *entry, *entry2;
++ ipmi_user_t user;
++ int rv = 0;
++ int deliver_count = 0;
++ unsigned long flags;
++
++ if (msg->rsp_size < 19) {
++ /* Message is too small to be an IPMB event. */
++ return 0;
++ }
++
++ if (msg->rsp[2] != 0) {
++ /* An error getting the event, just ignore it. */
++ return 0;
++ }
++
++ INIT_LIST_HEAD(&msgs);
++
++ spin_lock_irqsave(&(intf->events_lock), flags);
++
++ /* Allocate and fill in one message for every user that is getting
++ events. */
++ list_for_each(entry, &(intf->users)) {
++ user = list_entry(entry, struct ipmi_user, link);
++
++ if (! user->gets_events)
++ continue;
++
++ recv_msg = ipmi_alloc_recv_msg();
++ if (! recv_msg) {
++ list_for_each_safe(entry, entry2, &msgs) {
++ recv_msg = list_entry(entry,
++ struct ipmi_recv_msg,
++ link);
++ list_del(entry);
++ ipmi_free_recv_msg(recv_msg);
++ }
++ /* We couldn't allocate memory for the
++ message, so requeue it for handling
++ later. */
++ rv = 1;
++ goto out;
++ }
++
++ deliver_count++;
++
++ copy_event_into_recv_msg(recv_msg, msg);
++ recv_msg->user = user;
++ list_add_tail(&(recv_msg->link), &msgs);
++ }
++
++ if (deliver_count) {
++ /* Now deliver all the messages. */
++ list_for_each_safe(entry, entry2, &msgs) {
++ recv_msg = list_entry(entry,
++ struct ipmi_recv_msg,
++ link);
++ list_del(entry);
++ deliver_response(recv_msg);
++ }
++ } else if (intf->waiting_events_count < MAX_EVENTS_IN_QUEUE) {
++ /* No one to receive the message, put it in queue if there's
++ not already too many things in the queue. */
++ recv_msg = ipmi_alloc_recv_msg();
++ if (! recv_msg) {
++ /* We couldn't allocate memory for the
++ message, so requeue it for handling
++ later. */
++ rv = 1;
++ goto out;
++ }
++
++ copy_event_into_recv_msg(recv_msg, msg);
++ list_add_tail(&(recv_msg->link), &(intf->waiting_events));
++ } else {
++ /* There's too many things in the queue, discard this
++ message. */
++ printk(KERN_WARNING "ipmi: Event queue full, discarding an"
++ " incoming event\n");
++ }
++
++ out:
++ spin_unlock_irqrestore(&(intf->events_lock), flags);
++
++ return rv;
++}
++
++static int handle_bmc_rsp(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ struct ipmi_recv_msg *recv_msg;
++ int found = 0;
++ struct list_head *entry;
++
++ recv_msg = (struct ipmi_recv_msg *) msg->user_data;
++
++ /* Make sure the user still exists. */
++ list_for_each(entry, &(intf->users)) {
++ if (list_entry(entry, struct ipmi_user, link)
++ == recv_msg->user)
++ {
++ /* Found it, so we can deliver it */
++ found = 1;
++ break;
++ }
++ }
++
++ if (!found) {
++ /* The user for the message went away, so give up. */
++ ipmi_free_recv_msg(recv_msg);
++ } else {
++ struct ipmi_system_interface_addr *smi_addr;
++
++ recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
++ recv_msg->msgid = msg->msgid;
++ smi_addr = ((struct ipmi_system_interface_addr *)
++ &(recv_msg->addr));
++ smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr->channel = IPMI_BMC_CHANNEL;
++ smi_addr->lun = msg->rsp[0] & 3;
++ recv_msg->msg.netfn = msg->rsp[0] >> 2;
++ recv_msg->msg.cmd = msg->rsp[1];
++ memcpy(recv_msg->msg_data,
++ &(msg->rsp[2]),
++ msg->rsp_size - 2);
++ recv_msg->msg.data = recv_msg->msg_data;
++ recv_msg->msg.data_len = msg->rsp_size - 2;
++ deliver_response(recv_msg);
++ }
++
++ return 0;
++}
++
++/* Handle a new message. Return 1 if the message should be requeued,
++ 0 if the message should be freed, or -1 if the message should not
++ be freed or requeued. */
++static int handle_new_recv_msg(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ int requeue;
++
++ if (msg->rsp_size < 2) {
++ /* Message is too small to be correct. */
++ requeue = 0;
++ } else if (msg->rsp[1] == IPMI_GET_MSG_CMD) {
++#if DEBUG_MSGING
++ int m;
++ printk("Response:");
++ for (m=0; m<msg->rsp_size; m++)
++ printk(" %2.2x", msg->rsp[m]);
++ printk("\n");
++#endif
++ /* It's from the receive queue. */
++ if (msg->rsp[4] & 0x04) {
++ /* It's a response, so find the
++ requesting message and send it up. */
++ requeue = handle_get_msg_rsp(intf, msg);
++ } else {
++ /* It's a command to the SMS from some other
++ entity. Handle that. */
++ requeue = handle_get_msg_cmd(intf, msg);
++ }
++ } else if (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD) {
++ /* It's an asyncronous event. */
++ requeue = handle_read_event_rsp(intf, msg);
++ } else {
++ /* It's a response from the local BMC. */
++ requeue = handle_bmc_rsp(intf, msg);
++ }
++
++ return requeue;
++}
++
++/* Handle a new message from the lower layer. */
++void ipmi_smi_msg_received(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ unsigned long flags;
++ int rv;
++
++
++ /* Lock the user lock so the user can't go away while we are
++ working on it. */
++ read_lock(&(intf->users_lock));
++
++ if ((msg->data_size >= 2) && (msg->data[1] == IPMI_SEND_MSG_CMD)) {
++ /* This is the local response to a send, start the
++ timer for these. */
++ intf_start_seq_timer(intf, msg->msgid);
++ ipmi_free_smi_msg(msg);
++ goto out_unlock;
++ }
++
++ /* To preserve message order, if the list is not empty, we
++ tack this message onto the end of the list. */
++ spin_lock_irqsave(&(intf->waiting_msgs_lock), flags);
++ if (!list_empty(&(intf->waiting_msgs))) {
++ list_add_tail(&(msg->link), &(intf->waiting_msgs));
++ spin_unlock(&(intf->waiting_msgs_lock));
++ goto out_unlock;
++ }
++ spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
++
++ rv = handle_new_recv_msg(intf, msg);
++ if (rv > 0) {
++ /* Could not handle the message now, just add it to a
++ list to handle later. */
++ spin_lock(&(intf->waiting_msgs_lock));
++ list_add_tail(&(msg->link), &(intf->waiting_msgs));
++ spin_unlock(&(intf->waiting_msgs_lock));
++ } else if (rv == 0) {
++ ipmi_free_smi_msg(msg);
++ }
++
++ out_unlock:
++ read_unlock(&(intf->users_lock));
++}
++
++void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf)
++{
++ struct list_head *entry;
++ ipmi_user_t user;
++
++ read_lock(&(intf->users_lock));
++ list_for_each(entry, &(intf->users)) {
++ user = list_entry(entry, struct ipmi_user, link);
++
++ if (! user->handler->ipmi_watchdog_pretimeout)
++ continue;
++
++ user->handler->ipmi_watchdog_pretimeout(user->handler_data);
++ }
++ read_unlock(&(intf->users_lock));
++}
++
++static void
++handle_msg_timeout(struct ipmi_recv_msg *msg)
++{
++ msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
++ msg->msg_data[0] = IPMI_TIMEOUT_COMPLETION_CODE;
++ msg->msg.netfn |= 1; /* Convert to a response. */
++ msg->msg.data_len = 1;
++ msg->msg.data = msg->msg_data;
++ deliver_response(msg);
++}
++
++static void
++send_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
++ struct ipmi_smi_msg *smi_msg,
++ unsigned char seq, long seqid)
++{
++ if (!smi_msg)
++ smi_msg = ipmi_alloc_smi_msg();
++ if (!smi_msg)
++ /* If we can't allocate the message, then just return, we
++ get 4 retries, so this should be ok. */
++ return;
++
++ memcpy(smi_msg->data, recv_msg->msg.data, recv_msg->msg.data_len);
++ smi_msg->data_size = recv_msg->msg.data_len;
++ smi_msg->msgid = STORE_SEQ_IN_MSGID(seq, seqid);
++
++ /* Send the new message. We send with a zero priority. It
++ timed out, I doubt time is that critical now, and high
++ priority messages are really only for messages to the local
++ MC, which don't get resent. */
++ intf->handlers->sender(intf->send_info, smi_msg, 0);
++
++#if DEBUG_MSGING
++ {
++ int m;
++ printk("Resend: ");
++ for (m=0; m<smi_msg->data_size; m++)
++ printk(" %2.2x", smi_msg->data[m]);
++ printk("\n");
++ }
++#endif
++}
++
++static void
++ipmi_timeout_handler(long timeout_period)
++{
++ ipmi_smi_t intf;
++ struct list_head timeouts;
++ struct ipmi_recv_msg *msg;
++ struct ipmi_smi_msg *smi_msg;
++ unsigned long flags;
++ struct list_head *entry, *entry2;
++ int i, j;
++
++ INIT_LIST_HEAD(&timeouts);
++
++ spin_lock(&interfaces_lock);
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ intf = ipmi_interfaces[i];
++ if (intf == NULL)
++ continue;
++
++ read_lock(&(intf->users_lock));
++
++ /* See if any waiting messages need to be processed. */
++ spin_lock_irqsave(&(intf->waiting_msgs_lock), flags);
++ list_for_each_safe(entry, entry2, &(intf->waiting_msgs)) {
++ smi_msg = list_entry(entry, struct ipmi_smi_msg, link);
++ if (! handle_new_recv_msg(intf, smi_msg)) {
++ list_del(entry);
++ ipmi_free_smi_msg(smi_msg);
++ } else {
++ /* To preserve message order, quit if we
++ can't handle a message. */
++ break;
++ }
++ }
++ spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
++
++ /* Go through the seq table and find any messages that
++ have timed out, putting them in the timeouts
++ list. */
++ spin_lock_irqsave(&(intf->seq_lock), flags);
++ for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) {
++ struct seq_table *ent = &(intf->seq_table[j]);
++ if (!ent->inuse)
++ continue;
++
++ ent->timeout -= timeout_period;
++ if (ent->timeout > 0)
++ continue;
++
++ if (ent->retries_left == 0) {
++ /* The message has used all its retries. */
++ ent->inuse = 0;
++ msg = ent->recv_msg;
++ list_add_tail(&(msg->link), &timeouts);
++ } else {
++ /* More retries, send again. */
++
++ /* Start with the max timer, set to normal
++ timer after the message is sent. */
++ ent->timeout = MAX_MSG_TIMEOUT;
++ ent->retries_left--;
++ send_from_recv_msg(intf, ent->recv_msg, NULL,
++ j, ent->seqid);
++ }
++ }
++ spin_unlock_irqrestore(&(intf->seq_lock), flags);
++
++ list_for_each_safe(entry, entry2, &timeouts) {
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ handle_msg_timeout(msg);
++ }
++
++ read_unlock(&(intf->users_lock));
++ }
++ spin_unlock(&interfaces_lock);
++}
++
++static void ipmi_request_event(void)
++{
++ ipmi_smi_t intf;
++ int i;
++
++ spin_lock(&interfaces_lock);
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ intf = ipmi_interfaces[i];
++ if (intf == NULL)
++ continue;
++
++ intf->handlers->request_events(intf->send_info);
++ }
++ spin_unlock(&interfaces_lock);
++}
++
++static struct timer_list ipmi_timer;
++
++/* Call every 100 ms. */
++#define IPMI_TIMEOUT_TIME 100
++#define IPMI_TIMEOUT_JIFFIES (IPMI_TIMEOUT_TIME/(1000/HZ))
++
++/* Request events from the queue every second. Hopefully, in the
++ future, IPMI will add a way to know immediately if an event is
++ in the queue. */
++#define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME))
++
++static volatile int stop_operation = 0;
++static volatile int timer_stopped = 0;
++static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
++
++static void ipmi_timeout(unsigned long data)
++{
++ if (stop_operation) {
++ timer_stopped = 1;
++ return;
++ }
++
++ ticks_to_req_ev--;
++ if (ticks_to_req_ev == 0) {
++ ipmi_request_event();
++ ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
++ }
++
++ ipmi_timeout_handler(IPMI_TIMEOUT_TIME);
++
++ ipmi_timer.expires += IPMI_TIMEOUT_JIFFIES;
++ add_timer(&ipmi_timer);
++}
++
++
++/* FIXME - convert these to slabs. */
++static void free_smi_msg(struct ipmi_smi_msg *msg)
++{
++ kfree(msg);
++}
++
++struct ipmi_smi_msg *ipmi_alloc_smi_msg(void)
++{
++ struct ipmi_smi_msg *rv;
++ rv = kmalloc(sizeof(struct ipmi_smi_msg), GFP_ATOMIC);
++ if (rv)
++ rv->done = free_smi_msg;
++ return rv;
++}
++
++static void free_recv_msg(struct ipmi_recv_msg *msg)
++{
++ kfree(msg);
++}
++
++struct ipmi_recv_msg *ipmi_alloc_recv_msg(void)
++{
++ struct ipmi_recv_msg *rv;
++
++ rv = kmalloc(sizeof(struct ipmi_recv_msg), GFP_ATOMIC);
++ if (rv)
++ rv->done = free_recv_msg;
++ return rv;
++}
++
++#ifdef CONFIG_IPMI_PANIC_EVENT
++
++static void dummy_smi_done_handler(struct ipmi_smi_msg *msg)
++{
++}
++
++static void dummy_recv_done_handler(struct ipmi_recv_msg *msg)
++{
++}
++
++static void send_panic_events(void)
++{
++ struct ipmi_msg msg;
++ ipmi_smi_t intf;
++ unsigned char data[8];
++ int i;
++ struct ipmi_system_interface_addr addr;
++ struct ipmi_smi_msg smi_msg;
++ struct ipmi_recv_msg recv_msg;
++
++ addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ addr.channel = IPMI_BMC_CHANNEL;
++
++ /* Fill in an event telling that we have failed. */
++ msg.netfn = 0x04; /* Sensor or Event. */
++ msg.cmd = 2; /* Platform event command. */
++ msg.data = data;
++ msg.data_len = 8;
++ data[0] = 0x21; /* Kernel generator ID, IPMI table 5-4 */
++ data[1] = 0x03; /* This is for IPMI 1.0. */
++ data[2] = 0x20; /* OS Critical Stop, IPMI table 36-3 */
++ data[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
++ data[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
++
++ /* These used to have the first three bytes of the panic string,
++ but not only is that not terribly useful, it's not available
++ any more. */
++ data[3] = 0;
++ data[6] = 0;
++ data[7] = 0;
++
++ smi_msg.done = dummy_smi_done_handler;
++ recv_msg.done = dummy_recv_done_handler;
++
++ /* For every registered interface, send the event. */
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ intf = ipmi_interfaces[i];
++ if (intf == NULL)
++ continue;
++
++ intf->handlers->set_run_to_completion(intf->send_info, 1);
++ i_ipmi_request(NULL,
++ intf,
++ (struct ipmi_addr *) &addr,
++ 0,
++ &msg,
++ &smi_msg,
++ &recv_msg,
++ 0,
++ intf->my_address,
++ intf->my_lun);
++ }
++}
++#endif /* CONFIG_IPMI_PANIC_EVENT */
++
++static int has_paniced = 0;
++
++static int panic_event(struct notifier_block *this,
++ unsigned long event,
++ void *ptr)
++{
++ int i;
++ ipmi_smi_t intf;
++
++ if (has_paniced)
++ return NOTIFY_DONE;
++ has_paniced = 1;
++
++ /* For every registered interface, set it to run to completion. */
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ intf = ipmi_interfaces[i];
++ if (intf == NULL)
++ continue;
++
++ intf->handlers->set_run_to_completion(intf->send_info, 1);
++ }
++
++#ifdef CONFIG_IPMI_PANIC_EVENT
++ send_panic_events();
++#endif
++
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block panic_block = {
++ panic_event,
++ NULL,
++ 200 /* priority: INT_MAX >= x >= 0 */
++};
++
++
++static __init int ipmi_init_msghandler(void)
++{
++ int i;
++
++ if (initialized)
++ return 0;
++
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ ipmi_interfaces[i] = NULL;
++ }
++
++ init_timer(&ipmi_timer);
++ ipmi_timer.data = 0;
++ ipmi_timer.function = ipmi_timeout;
++ ipmi_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES;
++ add_timer(&ipmi_timer);
++
++ notifier_chain_register(&panic_notifier_list, &panic_block);
++
++ initialized = 1;
++
++ printk(KERN_INFO "ipmi: message handler initialized\n");
++
++ return 0;
++}
++
++static __exit void cleanup_ipmi(void)
++{
++ if (!initialized)
++ return;
++
++ notifier_chain_unregister(&panic_notifier_list, &panic_block);
++
++ /* This can't be called if any interfaces exist, so no worry about
++ shutting down the interfaces. */
++
++ /* Tell the timer to stop, then wait for it to stop. This avoids
++ problems with race conditions removing the timer here. */
++ stop_operation = 1;
++ while (!timer_stopped) {
++ schedule_timeout(1);
++ }
++
++ initialized = 0;
++}
++module_exit(cleanup_ipmi);
++
++module_init(ipmi_init_msghandler);
++MODULE_LICENSE("GPL");
++
++EXPORT_SYMBOL(ipmi_alloc_recv_msg);
++EXPORT_SYMBOL(ipmi_create_user);
++EXPORT_SYMBOL(ipmi_destroy_user);
++EXPORT_SYMBOL(ipmi_get_version);
++EXPORT_SYMBOL(ipmi_request);
++EXPORT_SYMBOL(ipmi_request_supply_msgs);
++EXPORT_SYMBOL(ipmi_request_with_source);
++EXPORT_SYMBOL(ipmi_register_smi);
++EXPORT_SYMBOL(ipmi_unregister_smi);
++EXPORT_SYMBOL(ipmi_register_for_cmd);
++EXPORT_SYMBOL(ipmi_unregister_for_cmd);
++EXPORT_SYMBOL(ipmi_smi_msg_received);
++EXPORT_SYMBOL(ipmi_smi_watchdog_pretimeout);
++EXPORT_SYMBOL(ipmi_alloc_smi_msg);
++EXPORT_SYMBOL(ipmi_register_all_cmd_rcvr);
++EXPORT_SYMBOL(ipmi_unregister_all_cmd_rcvr);
++EXPORT_SYMBOL(ipmi_addr_length);
++EXPORT_SYMBOL(ipmi_validate_addr);
++EXPORT_SYMBOL(ipmi_set_gets_events);
++EXPORT_SYMBOL(ipmi_addr_equal);
++EXPORT_SYMBOL(ipmi_smi_watcher_register);
++EXPORT_SYMBOL(ipmi_smi_watcher_unregister);
++EXPORT_SYMBOL(ipmi_set_my_address);
++EXPORT_SYMBOL(ipmi_get_my_address);
++EXPORT_SYMBOL(ipmi_set_my_LUN);
++EXPORT_SYMBOL(ipmi_get_my_LUN);
+diff -urN linux.orig/drivers/char/ipmi/ipmi_watchdog.c linux/drivers/char/ipmi/ipmi_watchdog.c
+--- linux.orig/drivers/char/ipmi/ipmi_watchdog.c Wed Dec 31 18:00:00 1969
++++ linux/drivers/char/ipmi/ipmi_watchdog.c Thu Jan 2 17:14:49 2003
+@@ -0,0 +1,1113 @@
++/*
++ * ipmi_watchdog.c
++ *
++ * A watchdog timer based upon the IPMI interface.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/ipmi.h>
++#include <linux/ipmi_smi.h>
++#include <linux/watchdog.h>
++#include <linux/miscdevice.h>
++#include <linux/init.h>
++#include <linux/rwsem.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <linux/notifier.h>
++#include <linux/nmi.h>
++#include <linux/reboot.h>
++#include <linux/wait.h>
++#include <linux/poll.h>
++#ifdef CONFIG_X86_LOCAL_APIC
++#include <asm/apic.h>
++#endif
++
++/*
++ * The IPMI command/response information for the watchdog timer.
++ */
++
++/* values for byte 1 of the set command, byte 2 of the get response. */
++#define WDOG_DONT_LOG (1 << 7)
++#define WDOG_DONT_STOP_ON_SET (1 << 6)
++#define WDOG_SET_TIMER_USE(byte, use) \
++ byte = ((byte) & 0xf8) | ((use) & 0x7)
++#define WDOG_GET_TIMER_USE(byte) ((byte) & 0x7)
++#define WDOG_TIMER_USE_BIOS_FRB2 1
++#define WDOG_TIMER_USE_BIOS_POST 2
++#define WDOG_TIMER_USE_OS_LOAD 3
++#define WDOG_TIMER_USE_SMS_OS 4
++#define WDOG_TIMER_USE_OEM 5
++
++/* values for byte 2 of the set command, byte 3 of the get response. */
++#define WDOG_SET_PRETIMEOUT_ACT(byte, use) \
++ byte = ((byte) & 0x8f) | (((use) & 0x7) << 4)
++#define WDOG_GET_PRETIMEOUT_ACT(byte) (((byte) >> 4) & 0x7)
++#define WDOG_PRETIMEOUT_NONE 0
++#define WDOG_PRETIMEOUT_SMI 1
++#define WDOG_PRETIMEOUT_NMI 2
++#define WDOG_PRETIMEOUT_MSG_INT 3
++
++/* Operations that can be performed on a pretimout. */
++#define WDOG_PREOP_NONE 0
++#define WDOG_PREOP_PANIC 1
++#define WDOG_PREOP_GIVE_DATA 2 /* Cause data to be available to
++ read. Doesn't work in NMI
++ mode. */
++
++/* Actions to perform on a full timeout. */
++#define WDOG_SET_TIMEOUT_ACT(byte, use) \
++ byte = ((byte) & 0xf8) | ((use) & 0x7)
++#define WDOG_GET_TIMEOUT_ACT(byte) ((byte) & 0x7)
++#define WDOG_TIMEOUT_NONE 0
++#define WDOG_TIMEOUT_RESET 1
++#define WDOG_TIMEOUT_POWER_DOWN 2
++#define WDOG_TIMEOUT_POWER_CYCLE 3
++
++/* Byte 3 of the get command, byte 4 of the get response is the
++ pre-timeout in seconds. */
++
++/* Bits for setting byte 4 of the set command, byte 5 of the get response. */
++#define WDOG_EXPIRE_CLEAR_BIOS_FRB2 (1 << 1)
++#define WDOG_EXPIRE_CLEAR_BIOS_POST (1 << 2)
++#define WDOG_EXPIRE_CLEAR_OS_LOAD (1 << 3)
++#define WDOG_EXPIRE_CLEAR_SMS_OS (1 << 4)
++#define WDOG_EXPIRE_CLEAR_OEM (1 << 5)
++
++/* Setting/getting the watchdog timer value. This is for bytes 5 and
++ 6 (the timeout time) of the set command, and bytes 6 and 7 (the
++ timeout time) and 8 and 9 (the current countdown value) of the
++ response. The timeout value is given in seconds (in the command it
++ is 100ms intervals). */
++#define WDOG_SET_TIMEOUT(byte1, byte2, val) \
++ (byte1) = (((val) * 10) & 0xff), (byte2) = (((val) * 10) >> 8)
++#define WDOG_GET_TIMEOUT(byte1, byte2) \
++ (((byte1) | ((byte2) << 8)) / 10)
++
++#define IPMI_WDOG_RESET_TIMER 0x22
++#define IPMI_WDOG_SET_TIMER 0x24
++#define IPMI_WDOG_GET_TIMER 0x25
++
++/* These are here until the real ones get into the watchdog.h interface. */
++#ifndef WDIOC_GETTIMEOUT
++#define WDIOC_GETTIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 20, int)
++#endif
++#ifndef WDIOC_SET_PRETIMEOUT
++#define WDIOC_SET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 21, int)
++#endif
++#ifndef WDIOC_GET_PRETIMEOUT
++#define WDIOC_GET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 22, int)
++#endif
++
++static ipmi_user_t watchdog_user = NULL;
++
++/* Default the timeout to 10 seconds. */
++static int timeout = 10;
++
++/* The pre-timeout is disabled by default. */
++static int pretimeout = 0;
++
++/* Default action is to reset the board on a timeout. */
++static unsigned char action_val = WDOG_TIMEOUT_RESET;
++
++static char *action = "reset";
++
++static unsigned char preaction_val = WDOG_PRETIMEOUT_NONE;
++
++static char *preaction = "pre_none";
++
++static unsigned char preop_val = WDOG_PREOP_NONE;
++
++static char *preop = "preop_none";
++static spinlock_t ipmi_read_lock = SPIN_LOCK_UNLOCKED;
++static char data_to_read = 0;
++static DECLARE_WAIT_QUEUE_HEAD(read_q);
++static struct fasync_struct *fasync_q = NULL;
++static char pretimeout_since_last_heartbeat = 0;
++
++MODULE_PARM(timeout, "i");
++MODULE_PARM(pretimeout, "i");
++MODULE_PARM(action, "s");
++MODULE_PARM(preaction, "s");
++MODULE_PARM(preop, "s");
++
++/* Default state of the timer. */
++static unsigned char ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
++
++/* If shutting down via IPMI, we ignore the heartbeat. */
++static int ipmi_ignore_heartbeat = 0;
++
++/* Is someone using the watchdog? Only one user is allowed. */
++static int ipmi_wdog_open = 0;
++
++/* If true, the driver will start running as soon as it is configured
++ and ready. */
++static int start_now = 0;
++
++/* If set to 1, the heartbeat command will set the state to reset and
++ start the timer. The timer doesn't normally run when the driver is
++ first opened until the heartbeat is set the first time, this
++ variable is used to accomplish this. */
++static int ipmi_start_timer_on_heartbeat = 0;
++
++/* IPMI version of the BMC. */
++static unsigned char ipmi_version_major;
++static unsigned char ipmi_version_minor;
++
++
++static int ipmi_heartbeat(void);
++static void panic_halt_ipmi_heartbeat(void);
++
++
++/* We use a semaphore to make sure that only one thing can send a set
++ timeout at one time, because we only have one copy of the data.
++ The semaphore is claimed when the set_timeout is sent and freed
++ when both messages are free. */
++static atomic_t set_timeout_tofree = ATOMIC_INIT(0);
++static DECLARE_MUTEX(set_timeout_lock);
++static void set_timeout_free_smi(struct ipmi_smi_msg *msg)
++{
++ if (atomic_dec_and_test(&set_timeout_tofree))
++ up(&set_timeout_lock);
++}
++static void set_timeout_free_recv(struct ipmi_recv_msg *msg)
++{
++ if (atomic_dec_and_test(&set_timeout_tofree))
++ up(&set_timeout_lock);
++}
++static struct ipmi_smi_msg set_timeout_smi_msg =
++{
++ .done = set_timeout_free_smi
++};
++static struct ipmi_recv_msg set_timeout_recv_msg =
++{
++ .done = set_timeout_free_recv
++};
++
++static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
++ struct ipmi_recv_msg *recv_msg,
++ int *send_heartbeat_now)
++{
++ struct ipmi_msg msg;
++ unsigned char data[6];
++ int rv;
++ struct ipmi_system_interface_addr addr;
++
++
++ *send_heartbeat_now = 0;
++ data[0] = 0;
++ WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);
++
++ if ((ipmi_version_major > 1)
++ || ((ipmi_version_major == 1) && (ipmi_version_minor >= 5)))
++ {
++ /* This is an IPMI 1.5-only feature. */
++ data[0] |= WDOG_DONT_STOP_ON_SET;
++ } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
++ /* In ipmi 1.0, setting the timer stops the watchdog, we
++ need to start it back up again. */
++ *send_heartbeat_now = 1;
++ }
++
++ data[1] = 0;
++ WDOG_SET_TIMEOUT_ACT(data[1], ipmi_watchdog_state);
++ if (pretimeout > 0) {
++ WDOG_SET_PRETIMEOUT_ACT(data[1], preaction_val);
++ data[2] = pretimeout;
++ } else {
++ WDOG_SET_PRETIMEOUT_ACT(data[1], WDOG_PRETIMEOUT_NONE);
++ data[2] = 0; /* No pretimeout. */
++ }
++ data[3] = 0;
++ WDOG_SET_TIMEOUT(data[4], data[5], timeout);
++
++ addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ addr.channel = IPMI_BMC_CHANNEL;
++ addr.lun = 0;
++
++ msg.netfn = 0x06;
++ msg.cmd = IPMI_WDOG_SET_TIMER;
++ msg.data = data;
++ msg.data_len = sizeof(data);
++ rv = ipmi_request_supply_msgs(watchdog_user,
++ (struct ipmi_addr *) &addr,
++ 0,
++ &msg,
++ smi_msg,
++ recv_msg,
++ 1);
++ if (rv) {
++ printk(KERN_WARNING "IPMI Watchdog, set timeout error: %d\n",
++ rv);
++ }
++
++ return rv;
++}
++
++static int ipmi_set_timeout(void)
++{
++ int send_heartbeat_now;
++ int rv;
++
++
++ /* We can only send one of these at a time. */
++ down(&set_timeout_lock);
++
++ atomic_set(&set_timeout_tofree, 2);
++
++ rv = i_ipmi_set_timeout(&set_timeout_smi_msg,
++ &set_timeout_recv_msg,
++ &send_heartbeat_now);
++ if (rv) {
++ up(&set_timeout_lock);
++ } else {
++ if (send_heartbeat_now)
++ rv = ipmi_heartbeat();
++ }
++
++ return rv;
++}
++
++static void dummy_smi_free(struct ipmi_smi_msg *msg)
++{
++}
++static void dummy_recv_free(struct ipmi_recv_msg *msg)
++{
++}
++static struct ipmi_smi_msg panic_halt_smi_msg =
++{
++ .done = dummy_smi_free
++};
++static struct ipmi_recv_msg panic_halt_recv_msg =
++{
++ .done = dummy_recv_free
++};
++
++/* Special call, doesn't claim any locks. This is only to be called
++ at panic or halt time, in run-to-completion mode, when the caller
++ is the only CPU and the only thing that will be going IPMI
++ calls. */
++static void panic_halt_ipmi_set_timeout(void)
++{
++ int send_heartbeat_now;
++ int rv;
++
++ rv = i_ipmi_set_timeout(&panic_halt_smi_msg,
++ &panic_halt_recv_msg,
++ &send_heartbeat_now);
++ if (!rv) {
++ if (send_heartbeat_now)
++ panic_halt_ipmi_heartbeat();
++ }
++}
++
++/* Do a delayed shutdown, with the delay in milliseconds. If power_off is
++ false, do a reset. If power_off is true, do a power down. This is
++ primarily for the IMB code's shutdown. */
++void ipmi_delayed_shutdown(long delay, int power_off)
++{
++ ipmi_ignore_heartbeat = 1;
++ if (power_off)
++ ipmi_watchdog_state = WDOG_TIMEOUT_POWER_DOWN;
++ else
++ ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
++ timeout = delay;
++ ipmi_set_timeout();
++}
++
++/* We use a semaphore to make sure that only one thing can send a
++ heartbeat at one time, because we only have one copy of the data.
++ The semaphore is claimed when the set_timeout is sent and freed
++ when both messages are free. */
++static atomic_t heartbeat_tofree = ATOMIC_INIT(0);
++static DECLARE_MUTEX(heartbeat_lock);
++static DECLARE_MUTEX_LOCKED(heartbeat_wait_lock);
++static void heartbeat_free_smi(struct ipmi_smi_msg *msg)
++{
++ if (atomic_dec_and_test(&heartbeat_tofree))
++ up(&heartbeat_wait_lock);
++}
++static void heartbeat_free_recv(struct ipmi_recv_msg *msg)
++{
++ if (atomic_dec_and_test(&heartbeat_tofree))
++ up(&heartbeat_wait_lock);
++}
++static struct ipmi_smi_msg heartbeat_smi_msg =
++{
++ .done = heartbeat_free_smi
++};
++static struct ipmi_recv_msg heartbeat_recv_msg =
++{
++ .done = heartbeat_free_recv
++};
++
++static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg =
++{
++ .done = dummy_smi_free
++};
++static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
++{
++ .done = dummy_recv_free
++};
++
++static int ipmi_heartbeat(void)
++{
++ struct ipmi_msg msg;
++ int rv;
++ struct ipmi_system_interface_addr addr;
++
++ if (ipmi_ignore_heartbeat) {
++ return 0;
++ }
++
++ if (ipmi_start_timer_on_heartbeat) {
++ ipmi_start_timer_on_heartbeat = 0;
++ ipmi_watchdog_state = action_val;
++ return ipmi_set_timeout();
++ }
++
++ if (pretimeout_since_last_heartbeat) {
++ /* A pretimeout occurred, make sure we set the timeout.
++ We don't want to set the action, though, we want to
++ leave that alone (thus it can't be combined with the
++ above operation. */
++ pretimeout_since_last_heartbeat = 0;
++ return ipmi_set_timeout();
++ }
++
++ down(&heartbeat_lock);
++
++ atomic_set(&heartbeat_tofree, 2);
++
++ /* Don't reset the timer if we have the timer turned off, that
++ re-enables the watchdog. */
++ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) {
++ up(&heartbeat_lock);
++ return 0;
++ }
++
++ addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ addr.channel = IPMI_BMC_CHANNEL;
++ addr.lun = 0;
++
++ msg.netfn = 0x06;
++ msg.cmd = IPMI_WDOG_RESET_TIMER;
++ msg.data = NULL;
++ msg.data_len = 0;
++ rv = ipmi_request_supply_msgs(watchdog_user,
++ (struct ipmi_addr *) &addr,
++ 0,
++ &msg,
++ &heartbeat_smi_msg,
++ &heartbeat_recv_msg,
++ 1);
++ if (rv) {
++ up(&heartbeat_lock);
++ printk(KERN_WARNING "IPMI Watchdog, heartbeat failure: %d\n",
++ rv);
++ return rv;
++ }
++
++ /* Wait for the heartbeat to be sent. */
++ down(&heartbeat_wait_lock);
++
++ if (heartbeat_recv_msg.msg.data[0] != 0) {
++ /* Got an error in the heartbeat response. It was already
++ reported in ipmi_wdog_msg_handler, but we should return
++ an error here. */
++ rv = -EINVAL;
++ }
++
++ up(&heartbeat_lock);
++
++ return rv;
++}
++
++static void panic_halt_ipmi_heartbeat(void)
++{
++ struct ipmi_msg msg;
++ struct ipmi_system_interface_addr addr;
++
++
++ /* Don't reset the timer if we have the timer turned off, that
++ re-enables the watchdog. */
++ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
++ return;
++
++ addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ addr.channel = IPMI_BMC_CHANNEL;
++ addr.lun = 0;
++
++ msg.netfn = 0x06;
++ msg.cmd = IPMI_WDOG_RESET_TIMER;
++ msg.data = NULL;
++ msg.data_len = 0;
++ ipmi_request_supply_msgs(watchdog_user,
++ (struct ipmi_addr *) &addr,
++ 0,
++ &msg,
++ &panic_halt_heartbeat_smi_msg,
++ &panic_halt_heartbeat_recv_msg,
++ 1);
++}
++
++static struct watchdog_info ident=
++{
++ 0, /* WDIOF_SETTIMEOUT, */
++ 1,
++ "IPMI"
++};
++
++static int ipmi_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ int i;
++ int val;
++
++ switch(cmd) {
++ case WDIOC_GETSUPPORT:
++ i = copy_to_user((void*)arg, &ident, sizeof(ident));
++ return i ? -EFAULT : 0;
++
++ case WDIOC_SETTIMEOUT:
++ i = copy_from_user(&val, (void *) arg, sizeof(int));
++ if (i)
++ return -EFAULT;
++ timeout = val;
++ return ipmi_set_timeout();
++
++ case WDIOC_GETTIMEOUT:
++ i = copy_to_user((void *) arg,
++ &timeout,
++ sizeof(timeout));
++ if (i)
++ return -EFAULT;
++ return 0;
++
++ case WDIOC_SET_PRETIMEOUT:
++ i = copy_from_user(&val, (void *) arg, sizeof(int));
++ if (i)
++ return -EFAULT;
++ pretimeout = val;
++ return ipmi_set_timeout();
++
++ case WDIOC_GET_PRETIMEOUT:
++ i = copy_to_user((void *) arg,
++ &pretimeout,
++ sizeof(pretimeout));
++ if (i)
++ return -EFAULT;
++ return 0;
++
++ case WDIOC_KEEPALIVE:
++ return ipmi_heartbeat();
++
++ case WDIOC_SETOPTIONS:
++ i = copy_from_user(&val, (void *) arg, sizeof(int));
++ if (i)
++ return -EFAULT;
++ if (val & WDIOS_DISABLECARD)
++ {
++ ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
++ ipmi_set_timeout();
++ ipmi_start_timer_on_heartbeat = 0;
++ }
++
++ if (val & WDIOS_ENABLECARD)
++ {
++ ipmi_watchdog_state = action_val;
++ ipmi_set_timeout();
++ }
++ return 0;
++
++ case WDIOC_GETSTATUS:
++ val = 0;
++ return copy_to_user((void *) arg, &val, sizeof(val));
++
++ default:
++ return -ENOIOCTLCMD;
++ }
++}
++
++static ssize_t ipmi_write(struct file *file,
++ const char *buf,
++ size_t len,
++ loff_t *ppos)
++{
++ int rv;
++
++ /* Can't seek (pwrite) on this device */
++ if (ppos != &file->f_pos)
++ return -ESPIPE;
++
++ if (len) {
++ rv = ipmi_heartbeat();
++ if (rv)
++ return rv;
++ return 1;
++ }
++ return 0;
++}
++
++static ssize_t ipmi_read(struct file *file,
++ char *buf,
++ size_t count,
++ loff_t *ppos)
++{
++ int rv = 0;
++ wait_queue_t wait;
++
++ /* Can't seek (pread) on this device */
++ if (ppos != &file->f_pos)
++ return -ESPIPE;
++
++ if (count <= 0)
++ return 0;
++
++ /* Reading returns if the pretimeout has gone off, and it only does
++ it once per pretimeout. */
++ spin_lock(&ipmi_read_lock);
++ if (!data_to_read) {
++ if (file->f_flags & O_NONBLOCK) {
++ rv = -EAGAIN;
++ goto out;
++ }
++
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&read_q, &wait);
++ while (!data_to_read) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ spin_unlock(&ipmi_read_lock);
++ schedule();
++ spin_lock(&ipmi_read_lock);
++ }
++ remove_wait_queue(&read_q, &wait);
++
++ if (signal_pending(current)) {
++ rv = -ERESTARTSYS;
++ goto out;
++ }
++ }
++ data_to_read = 0;
++
++ out:
++ spin_unlock(&ipmi_read_lock);
++
++ if (rv == 0) {
++ if (copy_to_user(buf, &data_to_read, 1))
++ rv = -EFAULT;
++ else
++ rv = 1;
++ }
++
++ return rv;
++}
++
++static int ipmi_open(struct inode *ino, struct file *filep)
++{
++ switch (minor(ino->i_rdev))
++ {
++ case WATCHDOG_MINOR:
++ if (ipmi_wdog_open)
++ return -EBUSY;
++
++ ipmi_wdog_open = 1;
++
++ /* Don't start the timer now, let it start on the
++ first heartbeat. */
++ ipmi_start_timer_on_heartbeat = 1;
++ return(0);
++
++ default:
++ return (-ENODEV);
++ }
++}
++
++static unsigned int ipmi_poll(struct file *file, poll_table *wait)
++{
++ unsigned int mask = 0;
++
++ poll_wait(file, &read_q, wait);
++
++ spin_lock(&ipmi_read_lock);
++ if (data_to_read)
++ mask |= (POLLIN | POLLRDNORM);
++ spin_unlock(&ipmi_read_lock);
++
++ return mask;
++}
++
++static int ipmi_fasync(int fd, struct file *file, int on)
++{
++ int result;
++
++ result = fasync_helper(fd, file, on, &fasync_q);
++
++ return (result);
++}
++
++static int ipmi_close(struct inode *ino, struct file *filep)
++{
++ if (minor(ino->i_rdev)==WATCHDOG_MINOR)
++ {
++#ifndef CONFIG_WATCHDOG_NOWAYOUT
++ ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
++ ipmi_set_timeout();
++#endif
++ ipmi_wdog_open = 0;
++ }
++
++ ipmi_fasync (-1, filep, 0);
++
++ return 0;
++}
++
++static struct file_operations ipmi_wdog_fops = {
++ .owner = THIS_MODULE,
++ .read = ipmi_read,
++ .poll = ipmi_poll,
++ .write = ipmi_write,
++ .ioctl = ipmi_ioctl,
++ .open = ipmi_open,
++ .release = ipmi_close,
++ .fasync = ipmi_fasync,
++};
++
++static struct miscdevice ipmi_wdog_miscdev = {
++ WATCHDOG_MINOR,
++ "watchdog",
++ &ipmi_wdog_fops
++};
++
++static DECLARE_RWSEM(register_sem);
++
++static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
++ void *handler_data)
++{
++ if (msg->msg.data[0] != 0) {
++ printk(KERN_ERR "IPMI Watchdog response: Error %x on cmd %x\n",
++ msg->msg.data[0],
++ msg->msg.cmd);
++ }
++
++ ipmi_free_recv_msg(msg);
++}
++
++static void ipmi_wdog_pretimeout_handler(void *handler_data)
++{
++ if (preaction_val != WDOG_PRETIMEOUT_NONE) {
++ if (preop_val == WDOG_PREOP_PANIC)
++ panic("Watchdog pre-timeout");
++ else if (preop_val == WDOG_PREOP_GIVE_DATA) {
++ spin_lock(&ipmi_read_lock);
++ data_to_read = 1;
++ wake_up_interruptible(&read_q);
++ kill_fasync(&fasync_q, SIGIO, POLL_IN);
++
++ /* On some machines, the heartbeat will give
++ an error and not work unless we re-enable
++ the timer. So do so. */
++ pretimeout_since_last_heartbeat = 1;
++
++ spin_unlock(&ipmi_read_lock);
++ }
++ }
++}
++
++static struct ipmi_user_hndl ipmi_hndlrs =
++{
++ .ipmi_recv_hndl = ipmi_wdog_msg_handler,
++ .ipmi_watchdog_pretimeout = ipmi_wdog_pretimeout_handler
++};
++
++static void ipmi_register_watchdog(int ipmi_intf)
++{
++ int rv = -EBUSY;
++
++ down_read(&register_sem);
++ if (watchdog_user)
++ goto out;
++
++ rv = ipmi_create_user(ipmi_intf, &ipmi_hndlrs, NULL, &watchdog_user);
++ if (rv < 0) {
++ printk("IPMI watchdog: Unable to register with ipmi\n");
++ goto out;
++ }
++
++ ipmi_get_version(watchdog_user,
++ &ipmi_version_major,
++ &ipmi_version_minor);
++
++ rv = misc_register(&ipmi_wdog_miscdev);
++ if (rv < 0) {
++ ipmi_destroy_user(watchdog_user);
++ watchdog_user = NULL;
++ printk("IPMI watchdog: Unable to register misc device\n");
++ }
++
++ out:
++ up_write(&register_sem);
++
++ if ((start_now) && (rv == 0)) {
++ /* Run from startup, so start the timer now. */
++ start_now = 0; /* Disable this function after first startup. */
++ ipmi_watchdog_state = action_val;
++ ipmi_set_timeout();
++ printk("Starting IPMI Watchdog now!\n");
++ }
++}
++
++#ifdef HAVE_NMI_HANDLER
++static int
++ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled)
++{
++ /* If no one else handled the NMI, we assume it was the IPMI
++ watchdog. */
++ if ((!handled) && (preop_val == WDOG_PREOP_PANIC))
++ panic("IPMI watchdog pre-timeout");
++ return NOTIFY_DONE;
++}
++
++static struct nmi_handler ipmi_nmi_handler =
++{
++ .dev_name = "ipmi_watchdog",
++ .dev_id = NULL,
++ .handler = ipmi_nmi,
++ .priority = 0, /* Call us last. */
++};
++#endif
++
++static int wdog_reboot_handler(struct notifier_block *this,
++ unsigned long code,
++ void *unused)
++{
++ static int reboot_event_handled = 0;
++
++ if ((watchdog_user) && (!reboot_event_handled)) {
++ /* Make sure we only do this once. */
++ reboot_event_handled = 1;
++
++ if (code == SYS_DOWN || code == SYS_HALT) {
++ /* Disable the WDT if we are shutting down. */
++ ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
++ panic_halt_ipmi_set_timeout();
++ } else {
++ /* Set a long timer to let the reboot happens, but
++ reboot if it hangs. */
++ timeout = 120;
++ pretimeout = 0;
++ ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
++ panic_halt_ipmi_set_timeout();
++ }
++ }
++ return NOTIFY_OK;
++}
++
++static struct notifier_block wdog_reboot_notifier = {
++ wdog_reboot_handler,
++ NULL,
++ 0
++};
++
++extern int panic_timeout; /* Why isn't this defined anywhere? */
++
++static int wdog_panic_handler(struct notifier_block *this,
++ unsigned long event,
++ void *unused)
++{
++ static int panic_event_handled = 0;
++
++ /* On a panic, if we have a panic timeout, make sure that the thing
++ reboots, even if it hangs during that panic. */
++ if (watchdog_user && !panic_event_handled && (panic_timeout > 0)) {
++ /* Make sure the panic doesn't hang, and make sure we
++ do this only once. */
++ panic_event_handled = 1;
++
++ timeout = panic_timeout + 120;
++ if (timeout > 255)
++ timeout = 255;
++ pretimeout = 0;
++ ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
++ panic_halt_ipmi_set_timeout();
++ }
++
++ return NOTIFY_OK;
++}
++
++static struct notifier_block wdog_panic_notifier = {
++ wdog_panic_handler,
++ NULL,
++ 150 /* priority: INT_MAX >= x >= 0 */
++};
++
++
++static void ipmi_new_smi(int if_num)
++{
++ ipmi_register_watchdog(if_num);
++}
++
++static void ipmi_smi_gone(int if_num)
++{
++ /* This can never be called, because once the watchdog is
++ registered, the interface can't go away until the watchdog
++ is unregistered. */
++}
++
++static struct ipmi_smi_watcher smi_watcher =
++{
++ .new_smi = ipmi_new_smi,
++ .smi_gone = ipmi_smi_gone
++};
++
++static int __init ipmi_wdog_init(void)
++{
++ int rv;
++
++ if (strcmp(action, "reset") == 0) {
++ action_val = WDOG_TIMEOUT_RESET;
++ } else if (strcmp(action, "none") == 0) {
++ action_val = WDOG_TIMEOUT_NONE;
++ } else if (strcmp(action, "power_cycle") == 0) {
++ action_val = WDOG_TIMEOUT_POWER_CYCLE;
++ } else if (strcmp(action, "power_off") == 0) {
++ action_val = WDOG_TIMEOUT_POWER_DOWN;
++ } else {
++ action_val = WDOG_TIMEOUT_RESET;
++ printk("ipmi_watchdog: Unknown action '%s', defaulting to"
++ " reset\n", action);
++ }
++
++ if (strcmp(preaction, "pre_none") == 0) {
++ preaction_val = WDOG_PRETIMEOUT_NONE;
++ } else if (strcmp(preaction, "pre_smi") == 0) {
++ preaction_val = WDOG_PRETIMEOUT_SMI;
++#ifdef HAVE_NMI_HANDLER
++ } else if (strcmp(preaction, "pre_nmi") == 0) {
++ preaction_val = WDOG_PRETIMEOUT_NMI;
++#endif
++ } else if (strcmp(preaction, "pre_int") == 0) {
++ preaction_val = WDOG_PRETIMEOUT_MSG_INT;
++ } else {
++ action_val = WDOG_PRETIMEOUT_NONE;
++ printk("ipmi_watchdog: Unknown preaction '%s', defaulting to"
++ " none\n", preaction);
++ }
++
++ if (strcmp(preop, "preop_none") == 0) {
++ preop_val = WDOG_PREOP_NONE;
++ } else if (strcmp(preop, "preop_panic") == 0) {
++ preop_val = WDOG_PREOP_PANIC;
++ } else if (strcmp(preop, "preop_give_data") == 0) {
++ preop_val = WDOG_PREOP_GIVE_DATA;
++ } else {
++ action_val = WDOG_PREOP_NONE;
++ printk("ipmi_watchdog: Unknown preop '%s', defaulting to"
++ " none\n", preop);
++ }
++
++#ifdef HAVE_NMI_HANDLER
++ if (preaction_val == WDOG_PRETIMEOUT_NMI) {
++ if (preop_val == WDOG_PREOP_GIVE_DATA) {
++ printk(KERN_WARNING
++ "ipmi_watchdog: Pretimeout op is to give data"
++ " but NMI pretimeout is enabled, setting"
++ " pretimeout op to none\n");
++ preop_val = WDOG_PREOP_NONE;
++ }
++#ifdef CONFIG_X86_LOCAL_APIC
++ if (nmi_watchdog == NMI_IO_APIC) {
++ printk(KERN_WARNING
++ "ipmi_watchdog: nmi_watchdog is set to IO APIC"
++ " mode (value is %d), that is incompatible"
++ " with using NMI in the IPMI watchdog."
++ " Disabling IPMI nmi pretimeout.\n",
++ nmi_watchdog);
++ preaction_val = WDOG_PRETIMEOUT_NONE;
++ } else {
++#endif
++ rv = request_nmi(&ipmi_nmi_handler);
++ if (rv) {
++ printk(KERN_WARNING
++ "ipmi_watchdog: Can't register nmi handler\n");
++ return rv;
++ }
++#ifdef CONFIG_X86_LOCAL_APIC
++ }
++#endif
++ }
++#endif
++
++ rv = ipmi_smi_watcher_register(&smi_watcher);
++ if (rv) {
++#ifdef HAVE_NMI_HANDLER
++ if (preaction_val == WDOG_PRETIMEOUT_NMI)
++ release_nmi(&ipmi_nmi_handler);
++#endif
++ printk(KERN_WARNING
++ "ipmi_watchdog: can't register smi watcher\n");
++ return rv;
++ }
++
++ register_reboot_notifier(&wdog_reboot_notifier);
++ notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier);
++
++ printk(KERN_INFO "IPMI watchdog by "
++ "Corey Minyard (minyard@mvista.com)\n");
++
++ return 0;
++}
++
++#ifdef MODULE
++static void ipmi_unregister_watchdog(void)
++{
++ int rv;
++
++ down_write(&register_sem);
++
++#ifdef HAVE_NMI_HANDLER
++ if (preaction_val == WDOG_PRETIMEOUT_NMI)
++ release_nmi(&ipmi_nmi_handler);
++#endif
++
++ notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier);
++ unregister_reboot_notifier(&wdog_reboot_notifier);
++
++ if (! watchdog_user)
++ goto out;
++
++ /* Make sure no one can call us any more. */
++ misc_deregister(&ipmi_wdog_miscdev);
++
++ /* Disable the timer. */
++ ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
++ ipmi_set_timeout();
++
++ /* Wait to make sure the message makes it out. The lower layer has
++ pointers to our buffers, we want to make sure they are done before
++ we release our memory. */
++ while (atomic_read(&set_timeout_tofree)) {
++ schedule_timeout(1);
++ }
++
++ /* Disconnect from IPMI. */
++ rv = ipmi_destroy_user(watchdog_user);
++ if (rv) {
++ printk(KERN_WARNING
++ "IPMI Watchdog, error unlinking from IPMI: %d\n",
++ rv);
++ }
++ watchdog_user = NULL;
++
++ out:
++ up_write(&register_sem);
++}
++
++static void __exit ipmi_wdog_exit(void)
++{
++ ipmi_smi_watcher_unregister(&smi_watcher);
++ ipmi_unregister_watchdog();
++}
++module_exit(ipmi_wdog_exit);
++#else
++static int __init ipmi_wdog_setup(char *str)
++{
++ int val;
++ int rv;
++ char *option;
++
++ rv = get_option(&str, &val);
++ if (rv == 0)
++ return 1;
++ if (val > 0)
++ timeout = val;
++ if (rv == 1)
++ return 1;
++
++ rv = get_option(&str, &val);
++ if (rv == 0)
++ return 1;
++ if (val >= 0)
++ pretimeout = val;
++ if (rv == 1)
++ return 1;
++
++ while ((option = strsep(&str, ",")) != NULL) {
++ if (strcmp(option, "reset") == 0) {
++ action = "reset";
++ }
++ else if (strcmp(option, "none") == 0) {
++ action = "none";
++ }
++ else if (strcmp(option, "power_cycle") == 0) {
++ action = "power_cycle";
++ }
++ else if (strcmp(option, "power_off") == 0) {
++ action = "power_off";
++ }
++ else if (strcmp(option, "pre_none") == 0) {
++ preaction = "pre_none";
++ }
++ else if (strcmp(option, "pre_smi") == 0) {
++ preaction = "pre_smi";
++ }
++#ifdef HAVE_NMI_HANDLER
++ else if (strcmp(option, "pre_nmi") == 0) {
++ preaction = "pre_nmi";
++ }
++#endif
++ else if (strcmp(option, "pre_int") == 0) {
++ preaction = "pre_int";
++ }
++ else if (strcmp(option, "start_now") == 0) {
++ start_now = 1;
++ }
++ else if (strcmp(option, "preop_none") == 0) {
++ preop = "preop_none";
++ }
++ else if (strcmp(option, "preop_panic") == 0) {
++ preop = "preop_panic";
++ }
++ else if (strcmp(option, "preop_none") == 0) {
++ preop = "preop_give_data";
++ } else {
++ printk("Unknown IPMI watchdog option: '%s'\n", option);
++ }
++ }
++
++ return 1;
++}
++__setup("ipmi_wdog=", ipmi_wdog_setup);
++#endif
++
++EXPORT_SYMBOL(ipmi_delayed_shutdown);
++
++module_init(ipmi_wdog_init);
++MODULE_LICENSE("GPL");
+diff -urN linux.orig/include/linux/ipmi.h linux/include/linux/ipmi.h
+--- linux.orig/include/linux/ipmi.h Wed Dec 31 18:00:00 1969
++++ linux/include/linux/ipmi.h Mon Jan 13 09:46:54 2003
+@@ -0,0 +1,516 @@
++/*
++ * ipmi.h
++ *
++ * MontaVista IPMI interface
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __LINUX_IPMI_H
++#define __LINUX_IPMI_H
++
++#include <linux/ipmi_msgdefs.h>
++
++/*
++ * This file describes an interface to an IPMI driver. You have to
++ * have a fairly good understanding of IPMI to use this, so go read
++ * the specs first before actually trying to do anything.
++ *
++ * With that said, this driver provides a multi-user interface to the
++ * IPMI driver, and it allows multiple IPMI physical interfaces below
++ * the driver. The physical interfaces bind as a lower layer on the
++ * driver. They appear as interfaces to the application using this
++ * interface.
++ *
++ * Multi-user means that multiple applications may use the driver,
++ * send commands, receive responses, etc. The driver keeps track of
++ * commands the user sends and tracks the responses. The responses
++ * will go back to the application that send the command. If the
++ * response doesn't come back in time, the driver will return a
++ * timeout error response to the application. Asynchronous events
++ * from the BMC event queue will go to all users bound to the driver.
++ * The incoming event queue in the BMC will automatically be flushed
++ * if it becomes full and it is queried once a second to see if
++ * anything is in it. Incoming commands to the driver will get
++ * delivered as commands.
++ *
++ * This driver provides two main interfaces: one for in-kernel
++ * applications and another for userland applications. The
++ * capabilities are basically the same for both interface, although
++ * the interfaces are somewhat different. The stuff in the
++ * #ifdef KERNEL below is the in-kernel interface. The userland
++ * interface is defined later in the file. */
++
++
++
++/*
++ * This is an overlay for all the address types, so it's easy to
++ * determine the actual address type. This is kind of like addresses
++ * work for sockets.
++ */
++#define IPMI_MAX_ADDR_SIZE 32
++struct ipmi_addr
++{
++ /* Try to take these from the "Channel Medium Type" table
++ in section 6.5 of the IPMI 1.5 manual. */
++ int addr_type;
++ short channel;
++ char data[IPMI_MAX_ADDR_SIZE];
++};
++
++/*
++ * When the address is not used, the type will be set to this value.
++ * The channel is the BMC's channel number for the channel (usually
++ * 0), or IPMC_BMC_CHANNEL if communicating directly with the BMC.
++ */
++#define IPMI_SYSTEM_INTERFACE_ADDR_TYPE 0x0c
++struct ipmi_system_interface_addr
++{
++ int addr_type;
++ short channel;
++ unsigned char lun;
++};
++
++/* An IPMB Address. */
++#define IPMI_IPMB_ADDR_TYPE 0x01
++/* Used for broadcast get device id as described in section 17.9 of the
++ IPMI 1.5 manual. */
++#define IPMI_IPMB_BROADCAST_ADDR_TYPE 0x41
++struct ipmi_ipmb_addr
++{
++ int addr_type;
++ short channel;
++ unsigned char slave_addr;
++ unsigned char lun;
++};
++
++
++/*
++ * Channel for talking directly with the BMC. When using this
++ * channel, This is for the system interface address type only. FIXME
++ * - is this right, or should we use -1?
++ */
++#define IPMI_BMC_CHANNEL 0xf
++#define IPMI_NUM_CHANNELS 0x10
++
++
++/*
++ * A raw IPMI message without any addressing. This covers both
++ * commands and responses. The completion code is always the first
++ * byte of data in the response (as the spec shows the messages laid
++ * out).
++ */
++struct ipmi_msg
++{
++ unsigned char netfn;
++ unsigned char cmd;
++ unsigned short data_len;
++ unsigned char *data;
++};
++
++/*
++ * Various defines that are useful for IPMI applications.
++ */
++#define IPMI_INVALID_CMD_COMPLETION_CODE 0xC1
++#define IPMI_TIMEOUT_COMPLETION_CODE 0xC3
++#define IPMI_UNKNOWN_ERR_COMPLETION_CODE 0xff
++
++
++/*
++ * Receive types for messages coming from the receive interface. This
++ * is used for the receive in-kernel interface and in the receive
++ * IOCTL.
++ */
++#define IPMI_RESPONSE_RECV_TYPE 1 /* A response to a command */
++#define IPMI_ASYNC_EVENT_RECV_TYPE 2 /* Something from the event queue */
++#define IPMI_CMD_RECV_TYPE 3 /* A command from somewhere else */
++/* Note that async events and received commands do not have a completion
++ code as the first byte of the incoming data, unlike a response. */
++
++
++
++#ifdef __KERNEL__
++
++/*
++ * The in-kernel interface.
++ */
++#include <linux/list.h>
++
++/* Opaque type for a IPMI message user. One of these is needed to
++ send and receive messages. */
++typedef struct ipmi_user *ipmi_user_t;
++
++/*
++ * Stuff coming from the recieve interface comes as one of these.
++ * They are allocated, the receiver must free them with
++ * ipmi_free_recv_msg() when done with the message. The link is not
++ * used after the message is delivered, so the upper layer may use the
++ * link to build a linked list, if it likes.
++ */
++struct ipmi_recv_msg
++{
++ struct list_head link;
++
++ /* The type of message as defined in the "Receive Types"
++ defines above. */
++ int recv_type;
++
++ ipmi_user_t user;
++ struct ipmi_addr addr;
++ long msgid;
++ struct ipmi_msg msg;
++
++ /* Call this when done with the message. It will presumably free
++ the message and do any other necessary cleanup. */
++ void (*done)(struct ipmi_recv_msg *msg);
++
++ /* Place-holder for the data, don't make any assumptions about
++ the size or existance of this, since it may change. */
++ unsigned char msg_data[IPMI_MAX_MSG_LENGTH];
++};
++
++/* Allocate and free the receive message. */
++static inline void ipmi_free_recv_msg(struct ipmi_recv_msg *msg)
++{
++ msg->done(msg);
++}
++struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
++
++struct ipmi_user_hndl
++{
++ /* Routine type to call when a message needs to be routed to
++ the upper layer. This will be called with some locks held,
++ the only IPMI routines that can be called are ipmi_request
++ and the alloc/free operations. */
++ void (*ipmi_recv_hndl)(struct ipmi_recv_msg *msg,
++ void *handler_data);
++
++ /* Called when the interface detects a watchdog pre-timeout. If
++ this is NULL, it will be ignored for the user. */
++ void (*ipmi_watchdog_pretimeout)(void *handler_data);
++};
++
++/* Create a new user of the IPMI layer on the given interface number. */
++int ipmi_create_user(unsigned int if_num,
++ struct ipmi_user_hndl *handler,
++ void *handler_data,
++ ipmi_user_t *user);
++
++/* Destroy the given user of the IPMI layer. */
++int ipmi_destroy_user(ipmi_user_t user);
++
++/* Get the IPMI version of the BMC we are talking to. */
++void ipmi_get_version(ipmi_user_t user,
++ unsigned char *major,
++ unsigned char *minor);
++
++/* Set and get the slave address and LUN that we will use for our
++ source messages. Note that this affects the interface, not just
++ this user, so it will affect all users of this interface. This is
++ so some initialization code can come in and do the OEM-specific
++ things it takes to determine your address (if not the BMC) and set
++ it for everyone else. */
++void ipmi_set_my_address(ipmi_user_t user,
++ unsigned char address);
++unsigned char ipmi_get_my_address(ipmi_user_t user);
++void ipmi_set_my_LUN(ipmi_user_t user,
++ unsigned char LUN);
++unsigned char ipmi_get_my_LUN(ipmi_user_t user);
++
++/*
++ * Send a command request from the given user. The address is the
++ * proper address for the channel type. If this is a command, then
++ * the message response comes back, the receive handler for this user
++ * will be called with the given msgid value in the recv msg. If this
++ * is a response to a command, then the msgid will be used as the
++ * sequence number for the response (truncated if necessary), so when
++ * sending a response you should use the sequence number you received
++ * in the msgid field of the received command. If the priority is >
++ * 0, the message will go into a high-priority queue and be sent
++ * first. Otherwise, it goes into a normal-priority queue.
++ */
++int ipmi_request(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ int priority);
++
++/*
++ * Like ipmi_request, but lets you specify the slave return address.
++ */
++int ipmi_request_with_source(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ int priority,
++ unsigned char source_address,
++ unsigned char source_lun);
++
++/*
++ * Like ipmi_request, but with messages supplied. This will not
++ * allocate any memory, and the messages may be statically allocated
++ * (just make sure to do the "done" handling on them). Note that this
++ * is primarily for the watchdog timer, since it should be able to
++ * send messages even if no memory is available. This is subject to
++ * change as the system changes, so don't use it unless you REALLY
++ * have to.
++ */
++int ipmi_request_supply_msgs(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ void *supplied_smi,
++ struct ipmi_recv_msg *supplied_recv,
++ int priority);
++
++/*
++ * When commands come in to the SMS, the user can register to receive
++ * them. Only one user can be listening on a specific netfn/cmd pair
++ * at a time, you will get an EBUSY error if the command is already
++ * registered. If a command is received that does not have a user
++ * registered, the driver will automatically return the proper
++ * error.
++ */
++int ipmi_register_for_cmd(ipmi_user_t user,
++ unsigned char netfn,
++ unsigned char cmd);
++int ipmi_unregister_for_cmd(ipmi_user_t user,
++ unsigned char netfn,
++ unsigned char cmd);
++
++/*
++ * When the user is created, it will not receive IPMI events by
++ * default. The user must set this to TRUE to get incoming events.
++ * The first user that sets this to TRUE will receive all events that
++ * have been queued while no one was waiting for events.
++ */
++int ipmi_set_gets_events(ipmi_user_t user, int val);
++
++/*
++ * Register the given user to handle all received IPMI commands. This
++ * will fail if anyone is registered as a command receiver or if
++ * another is already registered to receive all commands. NOTE THAT
++ * THIS IS FOR EMULATION USERS ONLY, DO NOT USER THIS FOR NORMAL
++ * STUFF.
++ */
++int ipmi_register_all_cmd_rcvr(ipmi_user_t user);
++int ipmi_unregister_all_cmd_rcvr(ipmi_user_t user);
++
++
++/*
++ * Called when a new SMI is registered. This will also be called on
++ * every existing interface when a new watcher is registered with
++ * ipmi_smi_watcher_register().
++ */
++struct ipmi_smi_watcher
++{
++ struct list_head link;
++
++ /* These two are called with read locks held for the interface
++ the watcher list. So you can add and remove users from the
++ IPMI interface, send messages, etc., but you cannot add
++ or remove SMI watchers or SMI interfaces. */
++ void (*new_smi)(int if_num);
++ void (*smi_gone)(int if_num);
++};
++
++int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher);
++int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher);
++
++/* The following are various helper functions for dealing with IPMI
++ addresses. */
++
++/* Return the maximum length of an IPMI address given it's type. */
++unsigned int ipmi_addr_length(int addr_type);
++
++/* Validate that the given IPMI address is valid. */
++int ipmi_validate_addr(struct ipmi_addr *addr, int len);
++
++/* Return 1 if the given addresses are equal, 0 if not. */
++int ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2);
++
++#endif /* __KERNEL__ */
++
++
++/*
++ * The userland interface
++ */
++
++/*
++ * The userland interface for the IPMI driver is a standard character
++ * device, with each instance of an interface registered as a minor
++ * number under the major character device.
++ *
++ * The read and write calls do not work, to get messages in and out
++ * requires ioctl calls because of the complexity of the data. select
++ * and poll do work, so you can wait for input using the file
++ * descriptor, you just can use read to get it.
++ *
++ * In general, you send a command down to the interface and receive
++ * responses back. You can use the msgid value to correlate commands
++ * and responses, the driver will take care of figuring out which
++ * incoming messages are for which command and find the proper msgid
++ * value to report. You will only receive reponses for commands you
++ * send. Asynchronous events, however, go to all open users, so you
++ * must be ready to handle these (or ignore them if you don't care).
++ *
++ * The address type depends upon the channel type. When talking
++ * directly to the BMC (IPMC_BMC_CHANNEL), the address is ignored
++ * (IPMI_UNUSED_ADDR_TYPE). When talking to an IPMB channel, you must
++ * supply a valid IPMB address with the addr_type set properly.
++ *
++ * When talking to normal channels, the driver takes care of the
++ * details of formatting and sending messages on that channel. You do
++ * not, for instance, have to format a send command, you just send
++ * whatever command you want to the channel, the driver will create
++ * the send command, automatically issue receive command and get even
++ * commands, and pass those up to the proper user.
++ */
++
++
++/* The magic IOCTL value for this interface. */
++#define IPMI_IOC_MAGIC 'i'
++
++
++/* Messages sent to the interface are this format. */
++struct ipmi_req
++{
++ unsigned char *addr; /* Address to send the message to. */
++ unsigned int addr_len;
++
++ long msgid; /* The sequence number for the message. This
++ exact value will be reported back in the
++ response to this request if it is a command.
++ If it is a response, this will be used as
++ the sequence value for the response. */
++
++ struct ipmi_msg msg;
++};
++/*
++ * Send a message to the interfaces. error values are:
++ * - EFAULT - an address supplied was invalid.
++ * - EINVAL - The address supplied was not valid, or the command
++ * was not allowed.
++ * - EMSGSIZE - The message to was too large.
++ * - ENOMEM - Buffers could not be allocated for the command.
++ */
++#define IPMICTL_SEND_COMMAND _IOR(IPMI_IOC_MAGIC, 13, \
++ struct ipmi_req)
++
++/* Messages received from the interface are this format. */
++struct ipmi_recv
++{
++ int recv_type; /* Is this a command, response or an
++ asyncronous event. */
++
++ unsigned char *addr; /* Address the message was from is put
++ here. The caller must supply the
++ memory. */
++ unsigned int addr_len; /* The size of the address buffer.
++ The caller supplies the full buffer
++ length, this value is updated to
++ the actual message length when the
++ message is received. */
++
++ long msgid; /* The sequence number specified in the request
++ if this is a response. If this is a command,
++ this will be the sequence number from the
++ command. */
++
++ struct ipmi_msg msg; /* The data field must point to a buffer.
++ The data_size field must be set to the
++ size of the message buffer. The
++ caller supplies the full buffer
++ length, this value is updated to the
++ actual message length when the message
++ is received. */
++};
++
++/*
++ * Receive a message. error values:
++ * - EAGAIN - no messages in the queue.
++ * - EFAULT - an address supplied was invalid.
++ * - EINVAL - The address supplied was not valid.
++ * - EMSGSIZE - The message to was too large to fit into the message buffer,
++ * the message will be left in the buffer. */
++#define IPMICTL_RECEIVE_MSG _IOWR(IPMI_IOC_MAGIC, 12, \
++ struct ipmi_recv)
++
++/*
++ * Like RECEIVE_MSG, but if the message won't fit in the buffer, it
++ * will truncate the contents instead of leaving the data in the
++ * buffer.
++ */
++#define IPMICTL_RECEIVE_MSG_TRUNC _IOWR(IPMI_IOC_MAGIC, 11, \
++ struct ipmi_recv)
++
++/* Register to get commands from other entities on this interface. */
++struct ipmi_cmdspec
++{
++ unsigned char netfn;
++ unsigned char cmd;
++};
++
++/*
++ * Register to receive a specific command. error values:
++ * - EFAULT - an address supplied was invalid.
++ * - EBUSY - The netfn/cmd supplied was already in use.
++ * - ENOMEM - could not allocate memory for the entry.
++ */
++#define IPMICTL_REGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 14, \
++ struct ipmi_cmdspec)
++/*
++ * Unregister a regsitered command. error values:
++ * - EFAULT - an address supplied was invalid.
++ * - ENOENT - The netfn/cmd was not found registered for this user.
++ */
++#define IPMICTL_UNREGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 15, \
++ struct ipmi_cmdspec)
++
++/*
++ * Set whether this interface receives events. Note that the first
++ * user registered for events will get all pending events for the
++ * interface. error values:
++ * - EFAULT - an address supplied was invalid.
++ */
++#define IPMICTL_SET_GETS_EVENTS_CMD _IOR(IPMI_IOC_MAGIC, 16, int)
++
++/*
++ * Set and get the slave address and LUN that we will use for our
++ * source messages. Note that this affects the interface, not just
++ * this user, so it will affect all users of this interface. This is
++ * so some initialization code can come in and do the OEM-specific
++ * things it takes to determine your address (if not the BMC) and set
++ * it for everyone else. You should probably leave the LUN alone.
++ */
++#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)
++#define IPMICTL_SET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 19, unsigned int)
++#define IPMICTL_GET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 20, unsigned int)
++
++#endif /* __LINUX_IPMI_H */
+diff -urN linux.orig/include/linux/ipmi_msgdefs.h linux/include/linux/ipmi_msgdefs.h
+--- linux.orig/include/linux/ipmi_msgdefs.h Wed Dec 31 18:00:00 1969
++++ linux/include/linux/ipmi_msgdefs.h Thu Aug 22 16:56:10 2002
+@@ -0,0 +1,58 @@
++/*
++ * ipmi_smi.h
++ *
++ * MontaVista IPMI system management interface
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __LINUX_IPMI_MSGDEFS_H
++#define __LINUX_IPMI_MSGDEFS_H
++
++/* Various definitions for IPMI messages used by almost everything in
++ the IPMI stack. */
++
++#define IPMI_NETFN_APP_REQUEST 0x06
++#define IPMI_NETFN_APP_RESPONSE 0x07
++
++#define IPMI_BMC_SLAVE_ADDR 0x20
++
++#define IPMI_GET_DEVICE_ID_CMD 0x01
++
++#define IPMI_CLEAR_MSG_FLAGS_CMD 0x30
++#define IPMI_GET_MSG_FLAGS_CMD 0x31
++#define IPMI_SEND_MSG_CMD 0x34
++#define IPMI_GET_MSG_CMD 0x33
++
++#define IPMI_SET_BMC_GLOBAL_ENABLES_CMD 0x2e
++#define IPMI_GET_BMC_GLOBAL_ENABLES_CMD 0x2f
++#define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35
++
++#define IPMI_MAX_MSG_LENGTH 80
++
++#endif /* __LINUX_IPMI_MSGDEFS_H */
+diff -urN linux.orig/include/linux/ipmi_smi.h linux/include/linux/ipmi_smi.h
+--- linux.orig/include/linux/ipmi_smi.h Wed Dec 31 18:00:00 1969
++++ linux/include/linux/ipmi_smi.h Mon Jan 13 10:23:45 2003
+@@ -0,0 +1,144 @@
++/*
++ * ipmi_smi.h
++ *
++ * MontaVista IPMI system management interface
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __LINUX_IPMI_SMI_H
++#define __LINUX_IPMI_SMI_H
++
++#include <linux/ipmi_msgdefs.h>
++
++/* This files describes the interface for IPMI system management interface
++ drivers to bind into the IPMI message handler. */
++
++/* Structure for the low-level drivers. */
++typedef struct ipmi_smi *ipmi_smi_t;
++
++/*
++ * Messages to/from the lower layer. The smi interface will take one
++ * of these to send. After the send has occurred and a response has
++ * been received, it will report this same data structure back up to
++ * the upper layer. If an error occurs, it should fill in the
++ * response with an error code in the completion code location. When
++ * asyncronous data is received, one of these is allocated, the
++ * data_size is set to zero and the response holds the data from the
++ * get message or get event command that the interface initiated.
++ * Note that it is the interfaces responsibility to detect
++ * asynchronous data and messages and request them from the
++ * interface.
++ */
++struct ipmi_smi_msg
++{
++ struct list_head link;
++
++ long msgid;
++ void *user_data;
++
++ /* If 0, add to the end of the queue. If 1, add to the beginning. */
++ int prio;
++
++ int data_size;
++ unsigned char data[IPMI_MAX_MSG_LENGTH];
++
++ int rsp_size;
++ unsigned char rsp[IPMI_MAX_MSG_LENGTH];
++
++ /* Will be called when the system is done with the message
++ (presumably to free it). */
++ void (*done)(struct ipmi_smi_msg *msg);
++};
++
++struct ipmi_smi_handlers
++{
++ /* Called to enqueue an SMI message to be sent. This
++ operation is not allowed to fail. If an error occurs, it
++ should report back the error in a received message. It may
++ do this in the current call context, since no write locks
++ are held when this is run. If the priority is > 0, the
++ message will go into a high-priority queue and be sent
++ first. Otherwise, it goes into a normal-priority queue. */
++ void (*sender)(void *send_info,
++ struct ipmi_smi_msg *msg,
++ int priority);
++
++ /* Called by the upper layer to request that we try to get
++ events from the BMC we are attached to. */
++ void (*request_events)(void *send_info);
++
++ /* Called when someone is using the interface, so the module can
++ adjust it's use count. Return zero if successful, or an
++ errno if not. */
++ int (*new_user)(void *send_info);
++
++ /* Called when someone is no longer using the interface, so the
++ module can adjust it's use count. */
++ void (*user_left)(void *send_info);
++
++ /* Called when the interface should go into "run to
++ completion" mode. If this call sets the value to true, the
++ interface should make sure that all messages are flushed
++ out and that none are pending, and any new requests are run
++ to completion immediately. */
++ void (*set_run_to_completion)(void *send_info, int run_to_completion);
++};
++
++/* Add a low-level interface to the IPMI driver. */
++int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
++ void *send_info,
++ unsigned char version_major,
++ unsigned char version_minor,
++ ipmi_smi_t *intf);
++
++/*
++ * Remove a low-level interface from the IPMI driver. This will
++ * return an error if the interface is still in use by a user.
++ */
++int ipmi_unregister_smi(ipmi_smi_t intf);
++
++/*
++ * The lower layer reports received messages through this interface.
++ * The data_size should be zero if this is an asyncronous message. If
++ * the lower layer gets an error sending a message, it should format
++ * an error response in the message response.
++ */
++void ipmi_smi_msg_received(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg);
++
++/* The lower layer received a watchdog pre-timeout on interface. */
++void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf);
++
++struct ipmi_smi_msg *ipmi_alloc_smi_msg(void);
++static inline void ipmi_free_smi_msg(struct ipmi_smi_msg *msg)
++{
++ msg->done(msg);
++}
++
++#endif /* __LINUX_IPMI_SMI_H */
+--- linux.orig/kernel/ksyms.c Fri Dec 6 09:12:07 2002
++++ linux/kernel/ksyms.c Fri Dec 6 09:13:01 2002
+@@ -65,6 +65,8 @@
+ extern int request_dma(unsigned int dmanr, char * deviceID);
+ extern void free_dma(unsigned int dmanr);
+ extern spinlock_t dma_spin_lock;
++extern int panic_timeout;
++
+
+ #ifdef CONFIG_MODVERSIONS
+ const struct module_symbol __export_Using_Versions
+@@ -467,6 +469,8 @@
+
+ /* misc */
+ EXPORT_SYMBOL(panic);
++EXPORT_SYMBOL(panic_notifier_list);
++EXPORT_SYMBOL(panic_timeout);
+ EXPORT_SYMBOL(__out_of_line_bug);
+ EXPORT_SYMBOL(sprintf);
+ EXPORT_SYMBOL(snprintf);
diff --git a/kern/linux-ipmi-2.5.44-v12.diff b/kern/linux-ipmi-2.5.44-v12.diff
new file mode 100644
index 0000000..b0350d6
--- /dev/null
+++ b/kern/linux-ipmi-2.5.44-v12.diff
@@ -0,0 +1,7362 @@
+diff -urN linux.orig/CREDITS linux/CREDITS
+--- linux.orig/CREDITS Mon Oct 21 13:25:57 2002
++++ linux/CREDITS Mon Oct 21 13:27:53 2002
+@@ -2161,9 +2161,15 @@
+
+ N: Corey Minyard
+ E: minyard@wf-rch.cirr.com
++E: minyard@mvista.com
++W: http://home.attbi.com/~minyard
+ D: Sony CDU31A CDROM Driver
+-S: 1805 Marquette
+-S: Richardson, Texas 75081
++D: IPMI driver
++D: Various networking fixes long ago
++D: Original ppc_md work
++D: Shared zlib
++S: 7406 Wheat Field Rd
++S: Garland, Texas 75066
+ S: USA
+
+ N: Patrick Mochel
+diff -urN linux.orig/Documentation/IPMI.txt linux/Documentation/IPMI.txt
+--- linux.orig/Documentation/IPMI.txt Wed Dec 31 18:00:00 1969
++++ linux/Documentation/IPMI.txt Tue Oct 22 09:35:21 2002
+@@ -0,0 +1,317 @@
++
++ The Linux IPMI Driver
++ ---------------------
++ Corey Minyard
++ <minyard@mvista.com>
++ <minyard@acm.org>
++
++This document describes how to use the IPMI driver for Linux. If you
++are not familiar with IPMI itself, see the web site at
++http://www.intel.com/design/servers/ipmi/index.htm. IPMI is a big
++subject and I can't cover it all here!
++
++Basic Design
++------------
++
++The Linux IPMI driver is designed to be very modular and flexible, you
++only need to take the pieces you need and you can use it in many
++different ways. Because of that, it's broken into many chunks of
++code. These chunks are:
++
++ipmi_msghandler - This is the central piece of software for the IPMI
++system. It handles all messages, message timing, and responses. The
++IPMI users tie into this, and the IPMI physical interfaces (called
++System Management Interfaces, or SMIs) also tie in here. This
++provides the kernelland interface for IPMI, but does not provide an
++interface for use by application processes.
++
++ipmi_devintf - This provides a userland IOCTL interface for the IPMI
++driver, each open file for this device ties in to the message handler
++as an IPMI user.
++
++ipmi_kcs_drv - A driver for the KCS SMI. Most system have a KCS
++interface for IPMI.
++
++
++Much documentation for the interface is in the include files. The
++IPMI include files are:
++
++ipmi.h - Contains the user interface and IOCTL interface for IPMI.
++
++ipmi_smi.h - Contains the interface for SMI drivers to use.
++
++ipmi_msgdefs.h - General definitions for base IPMI messaging.
++
++
++Addressing
++----------
++
++The IPMI addressing works much like IP addresses, you have an overlay
++to handle the different address types. The overlay is:
++
++ struct ipmi_addr
++ {
++ int addr_type;
++ short channel;
++ char data[IPMI_MAX_ADDR_SIZE];
++ };
++
++The addr_type determines what the address really is. The driver
++currently understands two different types of addresses.
++
++"System Interface" addresses are defined as:
++
++ struct ipmi_system_interface_addr
++ {
++ int addr_type;
++ short channel;
++ };
++
++and the type is IPMI_SYSTEM_INTERFACE_ADDR_TYPE. This is used for talking
++straight to the BMC on the current card. The channel must be
++IPMI_BMC_CHANNEL.
++
++Messages that are destined to go out on the IPMB bus use the
++IPMI_IPMB_ADDR_TYPE address type. The format is
++
++ struct ipmi_ipmb_addr
++ {
++ int addr_type;
++ short channel;
++ unsigned char slave_addr;
++ unsigned char lun;
++ };
++
++The "channel" here is generally zero, but some devices support more
++than one channel, it corresponds to the channel as defined in the IPMI
++spec.
++
++
++Messages
++--------
++
++Messages are defined as:
++
++struct ipmi_msg
++{
++ unsigned char netfn;
++ unsigned char lun;
++ unsigned char cmd;
++ unsigned char *data;
++ int data_len;
++};
++
++The driver takes care of adding/stripping the header information. The
++data portion is just the data to be send (do NOT put addressing info
++here) or the response. Note that the completion code of a response is
++the first item in "data", it is not stripped out because that is how
++all the messages are defined in the spec (and thus makes counting the
++offsets a little easier :-).
++
++When using the IOCTL interface from userland, you must provide a block
++of data for "data", fill it, and set data_len to the length of the
++block of data, even when receiving messages. Otherwise the driver
++will have no place to put the message.
++
++Messages coming up from the message handler in kernelland will come in
++as:
++
++ struct ipmi_recv_msg
++ {
++ struct list_head link;
++
++ /* The type of message as defined in the "Receive Types"
++ defines above. */
++ int recv_type;
++
++ ipmi_user_t *user;
++ struct ipmi_addr addr;
++ long msgid;
++ struct ipmi_msg msg;
++
++ /* Call this when done with the message. It will presumably free
++ the message and do any other necessary cleanup. */
++ void (*done)(struct ipmi_recv_msg *msg);
++
++ /* Place-holder for the data, don't make any assumptions about
++ the size or existence of this, since it may change. */
++ unsigned char msg_data[IPMI_MAX_MSG_LENGTH];
++ };
++
++You should look at the receive type and handle the message
++appropriately.
++
++
++The Upper Layer Interface (Message Handler)
++-------------------------------------------
++
++The upper layer of the interface provides the users with a consistent
++view of the IPMI interfaces. It allows multiple SMI interfaces to be
++addressed (because some boards actually have multiple BMCs on them)
++and the user should not have to care what type of SMI is below them.
++
++
++Creating the User
++
++To user the message handler, you must first create a user using
++ipmi_create_user. The interface number specifies which SMI you want
++to connect to, and you must supply callback functions to be called
++when data comes in. The callback function can run at interrupt level,
++so be careful using the callbacks. This also allows to you pass in a
++piece of data, the handler_data, that will be passed back to you on
++all calls.
++
++Once you are done, call ipmi_destroy_user() to get rid of the user.
++
++From userland, opening the device automatically creates a user, and
++closing the device automatically destroys the user.
++
++
++Messaging
++
++To send a message from kernel-land, the ipmi_request() call does
++pretty much all message handling. Most of the parameter are
++self-explanatory. However, it takes a "msgid" parameter. This is NOT
++the sequence number of messages. It is simply a long value that is
++passed back when the response for the message is returned. You may
++use it for anything you like.
++
++Responses come back in the function pointed to by the ipmi_recv_hndl
++field of the "handler" that you passed in to ipmi_create_user().
++Remember again, these may be running at interrupt level. Remember to
++look at the receive type, too.
++
++From userland, you fill out an ipmi_req_t structure and use the
++IPMICTL_SEND_COMMAND ioctl. For incoming stuff, you can use select()
++or poll() to wait for messages to come in. However, you cannot use
++read() to get them, you must call the IPMICTL_RECEIVE_MSG with the
++ipmi_recv_t structure to actually get the message. Remember that you
++must supply a pointer to a block of data in the msg.data field, and
++you must fill in the msg.data_len field with the size of the data.
++This gives the receiver a place to actually put the message.
++
++If the message cannot fit into the data you provide, you will get an
++EMSGSIZE error and the driver will leave the data in the receive
++queue. If you want to get it and have it truncate the message, us
++the IPMICTL_RECEIVE_MSG_TRUNC ioctl.
++
++When you send a command (which is defined by the lowest-order bit of
++the netfn per the IPMI spec) on the IPMB bus, the driver will
++automatically assign the sequence number to the command and save the
++command. If the response is not receive in the IMPI-specified 5
++seconds, it will generate a response automatically saying the command
++timed out. If an unsolicited response comes in (if it was after 5
++seconds, for instance), that response will be ignored.
++
++In kernelland, after you receive a message and are done with it, you
++MUST call ipmi_free_recv_msg() on it, or you will leak messages. Note
++that you should NEVER mess with the "done" field of a message, that is
++required to properly clean up the message.
++
++Note that when sending, there is an ipmi_request_supply_msgs() call
++that lets you supply the smi and receive message. This is useful for
++pieces of code that need to work even if the system is out of buffers
++(the watchdog timer uses this, for instance). You supply your own
++buffer and own free routines. This is not recommended for normal use,
++though, since it is tricky to manage your own buffers.
++
++
++Events and Incoming Commands
++
++The driver takes care of polling for IPMI events and receiving
++commands (commands are messages that are not responses, they are
++commands that other things on the IPMB bus have sent you). To receive
++these, you must register for them, they will not automatically be sent
++to you.
++
++To receive events, you must call ipmi_set_gets_events() and set the
++"val" to non-zero. Any events that have been received by the driver
++since startup will immediately be delivered to the first user that
++registers for events. After that, if multiple users are registered
++for events, they will all receive all events that come in.
++
++For receiving commands, you have to individually register commands you
++want to receive. Call ipmi_register_for_cmd() and supply the netfn
++and command name for each command you want to receive. Only one user
++may be registered for each netfn/cmd, but different users may register
++for different commands.
++
++From userland, equivalent IOCTLs are provided to do these functions.
++
++
++The Lower Layer (SMI) Interface
++-------------------------------
++
++As mentioned before, multiple SMI interfaces may be registered to the
++message handler, each of these is assigned an interface number when
++they register with the message handler. They are generally assigned
++in the order they register, although if an SMI unregisters and then
++another one registers, all bets are off.
++
++The ipmi_smi.h defines the interface for SMIs, see that for more
++details.
++
++
++The KCS Driver
++--------------
++
++The KCS driver allows up to 4 KCS interfaces to be configured in the
++system. By default, the driver will register one KCS interface at the
++spec-specified address 0xca2 without interrupts. You can change this
++at module load time (for a module) with:
++
++ insmod ipmi_kcs_drv.o kcs_addrs=<addr1>,<addr2>.. kcs_irqs=<irq1>,<irq2>..
++
++When compiled into the kernel, the addresses can be specified on the
++kernel command line as:
++
++ ipmi_kcs=<addr1>,<irq1>,<addr2>,<irq2>....
++
++If you specify zero for an address, the driver will use 0xca2. If you
++specify zero for in irq, the driver will run polled.
++
++If you have high-res timers compiled into the kernel, the driver will
++use them to provide much better performance. Note that if you do not
++have high-res timers enabled in the kernel and you don't have
++interrupts enabled, the driver will run VERY slowly. Don't blame me,
++the KCS interface sucks.
++
++
++Other Pieces
++------------
++
++Watchdog
++
++A watchdog timer is provided that implements the Linux-standard
++watchdog timer interface. It has three module parameters that can be
++used to control it:
++
++ insmod ipmi_watchdog timeout=<t> pretimeout=<t> action=<action type>
++ preaction=<preaction type>
++
++The timeout is the number of seconds to the action, and the pretimeout
++is the amount of seconds before the reset that the pre-timeout panic will
++occur (if pretimeout is zero, then pretimeout will not be enabled).
++
++The action may be "reset", "power_cycle", or "power_off", and
++specifies what to do when the timer times out, and defaults to
++"reset".
++
++The preaction may be "pre_smi" for an indication through the SMI
++interface, "pre_int" for an indication through the SMI with an
++interrupts, and "pre_nmi" for a NMI on a preaction.
++
++When compiled into the kernel, the kernel command line is available
++for configuring the watchdog:
++
++ ipmi_wdog=<timeout>[,<pretimeout>[,<option>[,<options>....]]]
++
++The options are the actions and preaction above (if an option
++controlling the same thing is specified twice, the last is taken). An
++options "start_now" is also there, if included, the watchdog will
++start running immediately when all the drivers are ready, it doesn't
++have to have a user hooked up to start it.
++
++The watchdog will panic and start a 120 second reset timeout if it
++gets a pre-action. During a panic or a reboot, the watchdog will
++start a 120 timer if it is running to make sure the reboot occurs.
+diff -urN linux.orig/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile
+--- linux.orig/arch/i386/kernel/Makefile Mon Oct 21 13:25:58 2002
++++ linux/arch/i386/kernel/Makefile Thu Oct 24 12:48:14 2002
+@@ -9,7 +9,7 @@
+ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
+ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
+ pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o \
+- bootflag.o
++ bootflag.o nmi.o
+
+ obj-y += cpu/
+ obj-y += timers/
+@@ -23,7 +23,7 @@
+ obj-$(CONFIG_ACPI_SLEEP) += acpi_wakeup.o
+ obj-$(CONFIG_X86_SMP) += smp.o smpboot.o trampoline.o
+ obj-$(CONFIG_X86_MPPARSE) += mpparse.o
+-obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
++obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi_watchdog.o
+ obj-$(CONFIG_X86_IO_APIC) += io_apic.o
+ obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
+ obj-$(CONFIG_X86_NUMAQ) += numaq.o
+diff -urN linux.orig/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
+--- linux.orig/arch/i386/kernel/i386_ksyms.c Mon Oct 21 13:25:58 2002
++++ linux/arch/i386/kernel/i386_ksyms.c Thu Oct 24 14:01:05 2002
+@@ -90,6 +90,9 @@
+ EXPORT_SYMBOL(cpu_khz);
+ EXPORT_SYMBOL(apm_info);
+
++EXPORT_SYMBOL(request_nmi);
++EXPORT_SYMBOL(release_nmi);
++
+ #ifdef CONFIG_DEBUG_IOVIRT
+ EXPORT_SYMBOL(__io_virt_debug);
+ #endif
+@@ -176,8 +179,6 @@
+
+ EXPORT_SYMBOL_GPL(register_profile_notifier);
+ EXPORT_SYMBOL_GPL(unregister_profile_notifier);
+-EXPORT_SYMBOL_GPL(set_nmi_callback);
+-EXPORT_SYMBOL_GPL(unset_nmi_callback);
+
+ #undef memcpy
+ #undef memset
+diff -urN linux.orig/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
+--- linux.orig/arch/i386/kernel/irq.c Mon Oct 21 13:25:58 2002
++++ linux/arch/i386/kernel/irq.c Tue Oct 22 12:08:20 2002
+@@ -131,6 +131,8 @@
+ * Generic, controller-independent functions:
+ */
+
++extern void nmi_append_user_names(struct seq_file *p);
++
+ int show_interrupts(struct seq_file *p, void *v)
+ {
+ int i, j;
+@@ -166,6 +168,8 @@
+ for (j = 0; j < NR_CPUS; j++)
+ if (cpu_online(j))
+ p += seq_printf(p, "%10u ", nmi_count(j));
++ seq_printf(p, " ");
++ nmi_append_user_names(p);
+ seq_putc(p, '\n');
+ #if CONFIG_X86_LOCAL_APIC
+ seq_printf(p, "LOC: ");
+diff -urN linux.orig/arch/i386/kernel/nmi.c linux/arch/i386/kernel/nmi.c
+--- linux.orig/arch/i386/kernel/nmi.c Mon Oct 21 13:25:45 2002
++++ linux/arch/i386/kernel/nmi.c Fri Oct 25 08:21:22 2002
+@@ -1,404 +1,239 @@
+ /*
+ * linux/arch/i386/nmi.c
+ *
+- * NMI watchdog support on APIC systems
++ * NMI support.
+ *
+- * Started by Ingo Molnar <mingo@redhat.com>
++ * Corey Minyard <cminyard@mvista.com>
+ *
+- * Fixes:
+- * Mikael Pettersson : AMD K7 support for local APIC NMI watchdog.
+- * Mikael Pettersson : Power Management for local APIC NMI watchdog.
+- * Mikael Pettersson : Pentium 4 support for local APIC NMI watchdog.
++ * Moved some of this over from traps.c.
+ */
+
+ #include <linux/config.h>
+-#include <linux/mm.h>
+-#include <linux/irq.h>
+ #include <linux/delay.h>
+-#include <linux/bootmem.h>
+-#include <linux/smp_lock.h>
++#include <linux/spinlock.h>
++#include <linux/list.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/rcupdate.h>
++#include <linux/seq_file.h>
++#include <linux/notifier.h>
+ #include <linux/interrupt.h>
+-#include <linux/mc146818rtc.h>
+-#include <linux/kernel_stat.h>
+
+-#include <asm/smp.h>
+-#include <asm/mtrr.h>
+-#include <asm/mpspec.h>
+-
+-unsigned int nmi_watchdog = NMI_NONE;
+-static unsigned int nmi_hz = HZ;
+-unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
+-extern void show_registers(struct pt_regs *regs);
+-
+-#define K7_EVNTSEL_ENABLE (1 << 22)
+-#define K7_EVNTSEL_INT (1 << 20)
+-#define K7_EVNTSEL_OS (1 << 17)
+-#define K7_EVNTSEL_USR (1 << 16)
+-#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76
+-#define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
+-
+-#define P6_EVNTSEL0_ENABLE (1 << 22)
+-#define P6_EVNTSEL_INT (1 << 20)
+-#define P6_EVNTSEL_OS (1 << 17)
+-#define P6_EVNTSEL_USR (1 << 16)
+-#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79
+-#define P6_NMI_EVENT P6_EVENT_CPU_CLOCKS_NOT_HALTED
+-
+-#define MSR_P4_MISC_ENABLE 0x1A0
+-#define MSR_P4_MISC_ENABLE_PERF_AVAIL (1<<7)
+-#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL (1<<12)
+-#define MSR_P4_PERFCTR0 0x300
+-#define MSR_P4_CCCR0 0x360
+-#define P4_ESCR_EVENT_SELECT(N) ((N)<<25)
+-#define P4_ESCR_OS (1<<3)
+-#define P4_ESCR_USR (1<<2)
+-#define P4_CCCR_OVF_PMI (1<<26)
+-#define P4_CCCR_THRESHOLD(N) ((N)<<20)
+-#define P4_CCCR_COMPLEMENT (1<<19)
+-#define P4_CCCR_COMPARE (1<<18)
+-#define P4_CCCR_REQUIRED (3<<16)
+-#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
+-#define P4_CCCR_ENABLE (1<<12)
+-/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
+- CRU_ESCR0 (with any non-null event selector) through a complemented
+- max threshold. [IA32-Vol3, Section 14.9.9] */
+-#define MSR_P4_IQ_COUNTER0 0x30C
+-#define MSR_P4_IQ_CCCR0 0x36C
+-#define MSR_P4_CRU_ESCR0 0x3B8
+-#define P4_NMI_CRU_ESCR0 (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
+-#define P4_NMI_IQ_CCCR0 \
+- (P4_CCCR_OVF_PMI|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \
+- P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
+-
+-int __init check_nmi_watchdog (void)
+-{
+- unsigned int prev_nmi_count[NR_CPUS];
+- int cpu;
+-
+- printk(KERN_INFO "testing NMI watchdog ... ");
+-
+- for (cpu = 0; cpu < NR_CPUS; cpu++)
+- prev_nmi_count[cpu] = irq_stat[cpu].__nmi_count;
+- local_irq_enable();
+- mdelay((10*1000)/nmi_hz); // wait 10 ticks
+-
+- /* FIXME: Only boot CPU is online at this stage. Check CPUs
+- as they come up. */
+- for (cpu = 0; cpu < NR_CPUS; cpu++) {
+- if (!cpu_online(cpu))
+- continue;
+- if (nmi_count(cpu) - prev_nmi_count[cpu] <= 5) {
+- printk("CPU#%d: NMI appears to be stuck!\n", cpu);
+- return -1;
+- }
+- }
+- printk("OK.\n");
++#include <asm/io.h>
++#include <asm/nmi.h>
+
+- /* now that we know it works we can reduce NMI frequency to
+- something more reasonable; makes a difference in some configs */
+- if (nmi_watchdog == NMI_LOCAL_APIC)
+- nmi_hz = 1;
++extern void show_registers(struct pt_regs *regs);
+
+- return 0;
+-}
++/*
++ * A list of handlers for NMIs. This list will be called in order
++ * when an NMI from an otherwise unidentifiable source comes in. If
++ * one of these handles the NMI, it should return NOTIFY_OK, otherwise
++ * it should return NOTIFY_DONE. NMI handlers cannot claim spinlocks,
++ * so we have to handle freeing these in a different manner. A
++ * spinlock protects the list from multiple writers. When something
++ * is removed from the list, it is thrown into another list (with
++ * another link, so the "next" element stays valid) and scheduled to
++ * run as an rcu. When the rcu runs, it is guaranteed that nothing in
++ * the NMI code will be using it.
++ */
++static struct list_head nmi_handler_list = LIST_HEAD_INIT(nmi_handler_list);
++static spinlock_t nmi_handler_lock = SPIN_LOCK_UNLOCKED;
+
+-static int __init setup_nmi_watchdog(char *str)
++/*
++ * To free the list item, we use an rcu. The rcu-function will not
++ * run until all processors have done a context switch, gone idle, or
++ * gone to a user process, so it's guaranteed that when this runs, any
++ * NMI handler running at release time has completed and the list item
++ * can be safely freed.
++ */
++static void free_nmi_handler(void *arg)
+ {
+- int nmi;
++ struct nmi_handler *handler = arg;
+
+- get_option(&str, &nmi);
+-
+- if (nmi >= NMI_INVALID)
+- return 0;
+- if (nmi == NMI_NONE)
+- nmi_watchdog = nmi;
+- /*
+- * If any other x86 CPU has a local APIC, then
+- * please test the NMI stuff there and send me the
+- * missing bits. Right now Intel P6/P4 and AMD K7 only.
+- */
+- if ((nmi == NMI_LOCAL_APIC) &&
+- (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
+- (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15))
+- nmi_watchdog = nmi;
+- if ((nmi == NMI_LOCAL_APIC) &&
+- (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
+- (boot_cpu_data.x86 == 6))
+- nmi_watchdog = nmi;
+- /*
+- * We can enable the IO-APIC watchdog
+- * unconditionally.
+- */
+- if (nmi == NMI_IO_APIC)
+- nmi_watchdog = nmi;
+- return 1;
++ INIT_LIST_HEAD(&(handler->link));
++ complete(&(handler->complete));
+ }
+
+-__setup("nmi_watchdog=", setup_nmi_watchdog);
+-
+-#ifdef CONFIG_PM
++int request_nmi(struct nmi_handler *handler)
++{
++ struct list_head *curr;
++ struct nmi_handler *curr_h = NULL;
+
+-#include <linux/pm.h>
++ if (!list_empty(&(handler->link)))
++ return -EBUSY;
+
+-struct pm_dev *nmi_pmdev;
++ spin_lock(&nmi_handler_lock);
+
+-static void disable_apic_nmi_watchdog(void)
+-{
+- switch (boot_cpu_data.x86_vendor) {
+- case X86_VENDOR_AMD:
+- wrmsr(MSR_K7_EVNTSEL0, 0, 0);
+- break;
+- case X86_VENDOR_INTEL:
+- switch (boot_cpu_data.x86) {
+- case 6:
+- wrmsr(MSR_P6_EVNTSEL0, 0, 0);
++ __list_for_each(curr, &nmi_handler_list) {
++ curr_h = list_entry(curr, struct nmi_handler, link);
++ if (curr_h->priority <= handler->priority)
+ break;
+- case 15:
+- wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
+- wrmsr(MSR_P4_CRU_ESCR0, 0, 0);
+- break;
+- }
+- break;
+ }
+-}
+
+-static int nmi_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
+-{
+- switch (rqst) {
+- case PM_SUSPEND:
+- disable_apic_nmi_watchdog();
+- break;
+- case PM_RESUME:
+- setup_apic_nmi_watchdog();
+- break;
+- }
++ /* list_add_rcu takes care of memory barrier */
++ if (curr_h)
++ if (curr_h->priority <= handler->priority)
++ list_add_rcu(&(handler->link), curr_h->link.prev);
++ else
++ list_add_rcu(&(handler->link), &(curr_h->link));
++ else
++ list_add_rcu(&(handler->link), &nmi_handler_list);
++
++ spin_unlock(&nmi_handler_lock);
+ return 0;
+ }
+
+-struct pm_dev * set_nmi_pm_callback(pm_callback callback)
++void release_nmi(struct nmi_handler *handler)
+ {
+- apic_pm_unregister(nmi_pmdev);
+- return apic_pm_register(PM_SYS_DEV, 0, callback);
+-}
++ spin_lock(&nmi_handler_lock);
++ list_del_rcu(&(handler->link));
++ init_completion(&(handler->complete));
++ call_rcu(&(handler->rcu), free_nmi_handler, handler);
++ spin_unlock(&nmi_handler_lock);
+
+-void unset_nmi_pm_callback(struct pm_dev * dev)
+-{
+- apic_pm_unregister(dev);
+- nmi_pmdev = apic_pm_register(PM_SYS_DEV, 0, nmi_pm_callback);
+-}
+-
+-static void nmi_pm_init(void)
+-{
+- if (!nmi_pmdev)
+- nmi_pmdev = apic_pm_register(PM_SYS_DEV, 0, nmi_pm_callback);
++ /* Wait for handler to finish being freed. This can't be
++ interrupted, we must wait until it finished. */
++ wait_for_completion(&(handler->complete));
+ }
+
+-#define __pminit /*empty*/
+-
+-#else /* CONFIG_PM */
+-
+-static inline void nmi_pm_init(void) { }
+-
+-#define __pminit __init
+-
+-#endif /* CONFIG_PM */
+-
+-/*
+- * Activate the NMI watchdog via the local APIC.
+- * Original code written by Keith Owens.
+- */
+-
+-static void __pminit clear_msr_range(unsigned int base, unsigned int n)
++void nmi_append_user_names(struct seq_file *p)
+ {
+- unsigned int i;
++ struct list_head *curr;
++ struct nmi_handler *curr_h;
+
+- for(i = 0; i < n; ++i)
+- wrmsr(base+i, 0, 0);
++ spin_lock(&nmi_handler_lock);
++ __list_for_each(curr, &nmi_handler_list) {
++ curr_h = list_entry(curr, struct nmi_handler, link);
++ if (curr_h->dev_name)
++ p += seq_printf(p, " %s", curr_h->dev_name);
++ }
++ spin_unlock(&nmi_handler_lock);
+ }
+
+-static void __pminit setup_k7_watchdog(void)
++static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
+ {
+- unsigned int evntsel;
+-
+- nmi_perfctr_msr = MSR_K7_PERFCTR0;
+-
+- clear_msr_range(MSR_K7_EVNTSEL0, 4);
+- clear_msr_range(MSR_K7_PERFCTR0, 4);
++ printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
++ printk("You probably have a hardware problem with your RAM chips\n");
+
+- evntsel = K7_EVNTSEL_INT
+- | K7_EVNTSEL_OS
+- | K7_EVNTSEL_USR
+- | K7_NMI_EVENT;
+-
+- wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
+- Dprintk("setting K7_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000));
+- wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
+- apic_write(APIC_LVTPC, APIC_DM_NMI);
+- evntsel |= K7_EVNTSEL_ENABLE;
+- wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
++ /* Clear and disable the memory parity error line. */
++ reason = (reason & 0xf) | 4;
++ outb(reason, 0x61);
+ }
+
+-static void __pminit setup_p6_watchdog(void)
++static void io_check_error(unsigned char reason, struct pt_regs * regs)
+ {
+- unsigned int evntsel;
+-
+- nmi_perfctr_msr = MSR_P6_PERFCTR0;
+-
+- clear_msr_range(MSR_P6_EVNTSEL0, 2);
+- clear_msr_range(MSR_P6_PERFCTR0, 2);
+-
+- evntsel = P6_EVNTSEL_INT
+- | P6_EVNTSEL_OS
+- | P6_EVNTSEL_USR
+- | P6_NMI_EVENT;
+-
+- wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
+- Dprintk("setting P6_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000));
+- wrmsr(MSR_P6_PERFCTR0, -(cpu_khz/nmi_hz*1000), 0);
+- apic_write(APIC_LVTPC, APIC_DM_NMI);
+- evntsel |= P6_EVNTSEL0_ENABLE;
+- wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
+-}
++ unsigned long i;
+
+-static int __pminit setup_p4_watchdog(void)
+-{
+- unsigned int misc_enable, dummy;
++ printk("NMI: IOCK error (debug interrupt?)\n");
++ show_registers(regs);
+
+- rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy);
+- if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
+- return 0;
+-
+- nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
+-
+- if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL))
+- clear_msr_range(0x3F1, 2);
+- /* MSR 0x3F0 seems to have a default value of 0xFC00, but current
+- docs doesn't fully define it, so leave it alone for now. */
+- clear_msr_range(0x3A0, 31);
+- clear_msr_range(0x3C0, 6);
+- clear_msr_range(0x3C8, 6);
+- clear_msr_range(0x3E0, 2);
+- clear_msr_range(MSR_P4_CCCR0, 18);
+- clear_msr_range(MSR_P4_PERFCTR0, 18);
+-
+- wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
+- wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
+- Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
+- wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
+- apic_write(APIC_LVTPC, APIC_DM_NMI);
+- wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0);
+- return 1;
++ /* Re-enable the IOCK line, wait for a few seconds */
++ reason = (reason & 0xf) | 8;
++ outb(reason, 0x61);
++ i = 2000;
++ while (--i) udelay(1000);
++ reason &= ~8;
++ outb(reason, 0x61);
+ }
+
+-void __pminit setup_apic_nmi_watchdog (void)
++static void unknown_nmi_error(struct pt_regs * regs, int cpu)
+ {
+- switch (boot_cpu_data.x86_vendor) {
+- case X86_VENDOR_AMD:
+- if (boot_cpu_data.x86 != 6)
+- return;
+- setup_k7_watchdog();
+- break;
+- case X86_VENDOR_INTEL:
+- switch (boot_cpu_data.x86) {
+- case 6:
+- setup_p6_watchdog();
+- break;
+- case 15:
+- if (!setup_p4_watchdog())
+- return;
+- break;
+- default:
+- return;
+- }
+- break;
+- default:
++#ifdef CONFIG_MCA
++ /* Might actually be able to figure out what the guilty party
++ * is. */
++ if( MCA_bus ) {
++ mca_handle_nmi();
+ return;
+ }
+- nmi_pm_init();
++#endif
++ printk("Uhhuh. Received NMI for unknown reason on CPU %d.\n", cpu);
++ printk("Dazed and confused, but trying to continue\n");
++ printk("Do you have a strange power saving mode enabled?\n");
+ }
+
+-static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED;
++/* Check "normal" sources of NMI. */
++static int nmi_std (void * dev_id, struct pt_regs * regs, int cpu, int handled)
++{
++ unsigned char reason;
+
+-/*
+- * the best way to detect whether a CPU has a 'hard lockup' problem
+- * is to check it's local APIC timer IRQ counts. If they are not
+- * changing then that CPU has some problem.
+- *
+- * as these watchdog NMI IRQs are generated on every CPU, we only
+- * have to check the current processor.
+- *
+- * since NMIs dont listen to _any_ locks, we have to be extremely
+- * careful not to rely on unsafe variables. The printk might lock
+- * up though, so we have to break up any console locks first ...
+- * [when there will be more tty-related locks, break them up
+- * here too!]
+- */
++ reason = inb(0x61);
++ if (reason & 0xc0) {
++ if (reason & 0x80)
++ mem_parity_error(reason, regs);
++ if (reason & 0x40)
++ io_check_error(reason, regs);
++ return NOTIFY_OK;
++ }
+
+-static unsigned int
+- last_irq_sums [NR_CPUS],
+- alert_counter [NR_CPUS];
+-
+-void touch_nmi_watchdog (void)
+-{
+- int i;
+-
+- /*
+- * Just reset the alert counters, (other CPUs might be
+- * spinning on locks we hold):
+- */
+- for (i = 0; i < NR_CPUS; i++)
+- alert_counter[i] = 0;
++ return NOTIFY_DONE;
+ }
+
+-void nmi_watchdog_tick (struct pt_regs * regs)
++static struct nmi_handler nmi_std_handler =
++{
++ .link = LIST_HEAD_INIT(nmi_std_handler.link),
++ .dev_name = "nmi_std",
++ .dev_id = NULL,
++ .handler = nmi_std,
++ .priority = 128, /* mid-level priority. */
++};
++
++asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
+ {
++ struct list_head *curr;
++ struct nmi_handler *curr_h;
++ int val;
++ int cpu = smp_processor_id();
++ int handled = 0;
++
+
+- /*
+- * Since current_thread_info()-> is always on the stack, and we
+- * always switch the stack NMI-atomically, it's safe to use
+- * smp_processor_id().
+- */
+- int sum, cpu = smp_processor_id();
++ ++nmi_count(cpu);
+
+- sum = irq_stat[cpu].apic_timer_irqs;
++ /* Since NMIs are edge-triggered, we could possibly miss one if we
++ don't call them all, so we call them all. */
+
+- if (last_irq_sums[cpu] == sum) {
+- /*
+- * Ayiee, looks like this CPU is stuck ...
+- * wait a few IRQs (5 seconds) before doing the oops ...
+- */
+- alert_counter[cpu]++;
+- if (alert_counter[cpu] == 5*nmi_hz) {
+- spin_lock(&nmi_print_lock);
+- /*
+- * We are in trouble anyway, lets at least try
+- * to get a message out.
+- */
+- bust_spinlocks(1);
+- printk("NMI Watchdog detected LOCKUP on CPU%d, eip %08lx, registers:\n", cpu, regs->eip);
+- show_registers(regs);
+- printk("console shuts up ...\n");
+- console_silent();
+- spin_unlock(&nmi_print_lock);
+- bust_spinlocks(0);
+- do_exit(SIGSEGV);
++ __list_for_each_rcu(curr, &nmi_handler_list) {
++ curr_h = list_entry(curr, struct nmi_handler, link);
++ val = curr_h->handler(curr_h->dev_id, regs, cpu, handled);
++ switch (val & ~NOTIFY_STOP_MASK) {
++ case NOTIFY_OK:
++ handled = 1;
++ break;
++
++ case NOTIFY_DONE:
++ default:;
+ }
+- } else {
+- last_irq_sums[cpu] = sum;
+- alert_counter[cpu] = 0;
++ if (val & NOTIFY_STOP_MASK)
++ break;
+ }
+- if (nmi_perfctr_msr) {
+- if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) {
+- /*
+- * P4 quirks:
+- * - An overflown perfctr will assert its interrupt
+- * until the OVF flag in its CCCR is cleared.
+- * - LVTPC is masked on interrupt and must be
+- * unmasked by the LVTPC handler.
+- */
+- wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0);
+- apic_write(APIC_LVTPC, APIC_DM_NMI);
+- }
+- wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
++
++ if (!handled)
++ unknown_nmi_error(regs, cpu);
++ else {
++ /*
++ * Reassert NMI in case it became active meanwhile
++ * as it's edge-triggered. Don't do this if the NMI
++ * wasn't handled to avoid an infinite NMI loop.
++ *
++ * This is necessary in case we have another external
++ * NMI while processing this one. The external NMIs
++ * are level-generated, into the processor NMIs are
++ * edge-triggered, so if you have one NMI source
++ * come in while another is already there, the level
++ * will never go down to cause another edge, and
++ * no more NMIs will happen. This does NOT apply
++ * to internally generated NMIs, though, so you
++ * can't use the same trick to only call one handler
++ * at a time. Otherwise, if two internal NMIs came
++ * in at the same time you might miss one.
++ */
++ outb(0x8f, 0x70);
++ inb(0x71); /* dummy */
++ outb(0x0f, 0x70);
++ inb(0x71); /* dummy */
+ }
++}
++
++void __init init_nmi(void)
++{
++ request_nmi(&nmi_std_handler);
+ }
+diff -urN linux.orig/arch/i386/kernel/nmi_watchdog.c linux/arch/i386/kernel/nmi_watchdog.c
+--- linux.orig/arch/i386/kernel/nmi_watchdog.c Thu Oct 24 19:56:54 2002
++++ linux/arch/i386/kernel/nmi_watchdog.c Thu Oct 24 20:54:19 2002
+@@ -0,0 +1,481 @@
++/*
++ * linux/arch/i386/nmi_watchdog.c
++ *
++ * NMI watchdog support on APIC systems
++ *
++ * Started by Ingo Molnar <mingo@redhat.com>
++ *
++ * Fixes:
++ * Mikael Pettersson : AMD K7 support for local APIC NMI watchdog.
++ * Mikael Pettersson : Power Management for local APIC NMI watchdog.
++ * Mikael Pettersson : Pentium 4 support for local APIC NMI watchdog.
++ */
++
++#include <linux/config.h>
++#include <linux/mm.h>
++#include <linux/irq.h>
++#include <linux/delay.h>
++#include <linux/bootmem.h>
++#include <linux/smp_lock.h>
++#include <linux/interrupt.h>
++#include <linux/mc146818rtc.h>
++#include <linux/kernel_stat.h>
++#include <linux/notifier.h>
++
++#include <asm/smp.h>
++#include <asm/mtrr.h>
++#include <asm/mpspec.h>
++#include <asm/nmi.h>
++
++unsigned int nmi_watchdog = NMI_NONE;
++static unsigned int nmi_hz = HZ;
++
++/* This is for I/O APIC, until we can figure out how to tell if it's from the
++ I/O APIC. If the NMI was not handled before now, we handle it. */
++static int dummy_watchdog_reset(int handled)
++{
++ return !handled;
++}
++
++/*
++ * Returns 1 if it is a source of the NMI, and resets the NMI to go
++ * off again.
++ */
++static int (*watchdog_reset)(int handled) = dummy_watchdog_reset;
++
++extern void show_registers(struct pt_regs *regs);
++
++#define K7_EVNTSEL_ENABLE (1 << 22)
++#define K7_EVNTSEL_INT (1 << 20)
++#define K7_EVNTSEL_OS (1 << 17)
++#define K7_EVNTSEL_USR (1 << 16)
++#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76
++#define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
++
++#define P6_EVNTSEL0_ENABLE (1 << 22)
++#define P6_EVNTSEL_INT (1 << 20)
++#define P6_EVNTSEL_OS (1 << 17)
++#define P6_EVNTSEL_USR (1 << 16)
++#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79
++#define P6_NMI_EVENT P6_EVENT_CPU_CLOCKS_NOT_HALTED
++
++#define MSR_P4_MISC_ENABLE 0x1A0
++#define MSR_P4_MISC_ENABLE_PERF_AVAIL (1<<7)
++#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL (1<<12)
++#define MSR_P4_PERFCTR0 0x300
++#define MSR_P4_CCCR0 0x360
++#define P4_ESCR_EVENT_SELECT(N) ((N)<<25)
++#define P4_ESCR_OS (1<<3)
++#define P4_ESCR_USR (1<<2)
++#define P4_CCCR_OVF_PMI (1<<26)
++#define P4_CCCR_THRESHOLD(N) ((N)<<20)
++#define P4_CCCR_COMPLEMENT (1<<19)
++#define P4_CCCR_COMPARE (1<<18)
++#define P4_CCCR_REQUIRED (3<<16)
++#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
++#define P4_CCCR_ENABLE (1<<12)
++/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
++ CRU_ESCR0 (with any non-null event selector) through a complemented
++ max threshold. [IA32-Vol3, Section 14.9.9] */
++#define MSR_P4_IQ_COUNTER0 0x30C
++#define MSR_P4_IQ_CCCR0 0x36C
++#define MSR_P4_CRU_ESCR0 0x3B8
++#define P4_NMI_CRU_ESCR0 (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
++#define P4_NMI_IQ_CCCR0 \
++ (P4_CCCR_OVF_PMI|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \
++ P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
++
++int __init check_nmi_watchdog (void)
++{
++ unsigned int prev_nmi_count[NR_CPUS];
++ int cpu;
++
++ printk(KERN_INFO "testing NMI watchdog ... ");
++
++ for (cpu = 0; cpu < NR_CPUS; cpu++)
++ prev_nmi_count[cpu] = irq_stat[cpu].__nmi_count;
++ local_irq_enable();
++ mdelay((10*1000)/nmi_hz); // wait 10 ticks
++
++ /* FIXME: Only boot CPU is online at this stage. Check CPUs
++ as they come up. */
++ for (cpu = 0; cpu < NR_CPUS; cpu++) {
++ if (!cpu_online(cpu))
++ continue;
++ if (nmi_count(cpu) - prev_nmi_count[cpu] <= 5) {
++ printk("CPU#%d: NMI appears to be stuck!\n", cpu);
++ return -1;
++ }
++ }
++ printk("OK.\n");
++
++ /* now that we know it works we can reduce NMI frequency to
++ something more reasonable; makes a difference in some configs */
++ if (nmi_watchdog == NMI_LOCAL_APIC)
++ nmi_hz = 1;
++
++ return 0;
++}
++
++static int nmi_watchdog_tick (void * dev_id, struct pt_regs * regs, int cpu,
++ int handled);
++
++static struct nmi_handler nmi_watchdog_handler =
++{
++ .link = LIST_HEAD_INIT(nmi_watchdog_handler.link),
++ .dev_name = "nmi_watchdog",
++ .dev_id = NULL,
++ .handler = nmi_watchdog_tick,
++ .priority = 255, /* We want to be relatively high priority. */
++};
++
++static int __init setup_nmi_watchdog(char *str)
++{
++ int nmi;
++
++ get_option(&str, &nmi);
++
++ if (nmi >= NMI_INVALID)
++ return 0;
++
++ if (nmi == NMI_NONE)
++ nmi_watchdog = nmi;
++ /*
++ * If any other x86 CPU has a local APIC, then
++ * please test the NMI stuff there and send me the
++ * missing bits. Right now Intel P6/P4 and AMD K7 only.
++ */
++ if ((nmi == NMI_LOCAL_APIC) &&
++ (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
++ (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15))
++ nmi_watchdog = nmi;
++ if ((nmi == NMI_LOCAL_APIC) &&
++ (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
++ (boot_cpu_data.x86 == 6))
++ nmi_watchdog = nmi;
++ /*
++ * We can enable the IO-APIC watchdog
++ * unconditionally.
++ */
++ if (nmi == NMI_IO_APIC)
++ nmi_watchdog = nmi;
++
++ if (nmi_watchdog != NMI_NONE) {
++ if (request_nmi(&nmi_watchdog_handler) != 0) {
++ /* Couldn't add a watchdog handler, give up. */
++ printk(KERN_WARNING
++ "nmi_watchdog: Couldn't request nmi\n");
++ nmi_watchdog = NMI_NONE;
++ return 0;
++ }
++ }
++
++ return 1;
++}
++
++__setup("nmi_watchdog=", setup_nmi_watchdog);
++
++#ifdef CONFIG_PM
++
++#include <linux/pm.h>
++
++struct pm_dev *nmi_pmdev;
++
++static void disable_apic_nmi_watchdog(void)
++{
++ switch (boot_cpu_data.x86_vendor) {
++ case X86_VENDOR_AMD:
++ wrmsr(MSR_K7_EVNTSEL0, 0, 0);
++ break;
++ case X86_VENDOR_INTEL:
++ switch (boot_cpu_data.x86) {
++ case 6:
++ wrmsr(MSR_P6_EVNTSEL0, 0, 0);
++ break;
++ case 15:
++ wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
++ wrmsr(MSR_P4_CRU_ESCR0, 0, 0);
++ break;
++ }
++ break;
++ }
++}
++
++static int nmi_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
++{
++ switch (rqst) {
++ case PM_SUSPEND:
++ disable_apic_nmi_watchdog();
++ break;
++ case PM_RESUME:
++ setup_apic_nmi_watchdog();
++ break;
++ }
++ return 0;
++}
++
++struct pm_dev * set_nmi_pm_callback(pm_callback callback)
++{
++ apic_pm_unregister(nmi_pmdev);
++ return apic_pm_register(PM_SYS_DEV, 0, callback);
++}
++
++void unset_nmi_pm_callback(struct pm_dev * dev)
++{
++ apic_pm_unregister(dev);
++ nmi_pmdev = apic_pm_register(PM_SYS_DEV, 0, nmi_pm_callback);
++}
++
++static void nmi_pm_init(void)
++{
++ if (!nmi_pmdev)
++ nmi_pmdev = apic_pm_register(PM_SYS_DEV, 0, nmi_pm_callback);
++}
++
++#define __pminit /*empty*/
++
++#else /* CONFIG_PM */
++
++static inline void nmi_pm_init(void) { }
++
++#define __pminit __init
++
++#endif /* CONFIG_PM */
++
++/*
++ * Activate the NMI watchdog via the local APIC.
++ * Original code written by Keith Owens.
++ */
++
++static void __pminit clear_msr_range(unsigned int base, unsigned int n)
++{
++ unsigned int i;
++
++ for(i = 0; i < n; ++i)
++ wrmsr(base+i, 0, 0);
++}
++
++static int k7_watchdog_reset(int handled)
++{
++ unsigned int low, high;
++ int source;
++
++ rdmsr(MSR_K7_PERFCTR0, low, high);
++ source = (low & (1 << 31)) == 0;
++ if (source)
++ wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
++ return source;
++}
++
++static void __pminit setup_k7_watchdog(void)
++{
++ unsigned int evntsel;
++
++ watchdog_reset = k7_watchdog_reset;
++
++ clear_msr_range(MSR_K7_EVNTSEL0, 4);
++ clear_msr_range(MSR_K7_PERFCTR0, 4);
++
++ evntsel = K7_EVNTSEL_INT
++ | K7_EVNTSEL_OS
++ | K7_EVNTSEL_USR
++ | K7_NMI_EVENT;
++
++ wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
++ Dprintk("setting K7_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000));
++ wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
++ apic_write(APIC_LVTPC, APIC_DM_NMI);
++ evntsel |= K7_EVNTSEL_ENABLE;
++ wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
++}
++
++static int p6_watchdog_reset(int handled)
++{
++ unsigned int low, high;
++ int source;
++
++ rdmsr(MSR_P6_PERFCTR0, low, high);
++ source = (low & (1 << 31)) == 0;
++ if (source)
++ wrmsr(MSR_P6_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
++ return source;
++}
++
++static void __pminit setup_p6_watchdog(void)
++{
++ unsigned int evntsel;
++
++ watchdog_reset = p6_watchdog_reset;
++
++ clear_msr_range(MSR_P6_EVNTSEL0, 2);
++ clear_msr_range(MSR_P6_PERFCTR0, 2);
++
++ evntsel = P6_EVNTSEL_INT
++ | P6_EVNTSEL_OS
++ | P6_EVNTSEL_USR
++ | P6_NMI_EVENT;
++
++ wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
++ Dprintk("setting P6_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000));
++ wrmsr(MSR_P6_PERFCTR0, -(cpu_khz/nmi_hz*1000), 0);
++ apic_write(APIC_LVTPC, APIC_DM_NMI);
++ evntsel |= P6_EVNTSEL0_ENABLE;
++ wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
++}
++
++static int p4_watchdog_reset(int handled)
++{
++ unsigned int low, high;
++ int source;
++
++ rdmsr(MSR_P4_IQ_COUNTER0, low, high);
++ source = (low & (1 << 31)) == 0;
++ if (source) {
++ /*
++ * P4 quirks:
++ * - An overflown perfctr will assert its interrupt
++ * until the OVF flag in its CCCR is cleared.
++ * - LVTPC is masked on interrupt and must be
++ * unmasked by the LVTPC handler.
++ */
++ wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0);
++ apic_write(APIC_LVTPC, APIC_DM_NMI);
++
++ wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
++ }
++ return source;
++}
++
++static int __pminit setup_p4_watchdog(void)
++{
++ unsigned int misc_enable, dummy;
++
++ rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy);
++ if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
++ return 0;
++
++ watchdog_reset = p4_watchdog_reset;
++
++ if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL))
++ clear_msr_range(0x3F1, 2);
++ /* MSR 0x3F0 seems to have a default value of 0xFC00, but current
++ docs doesn't fully define it, so leave it alone for now. */
++ clear_msr_range(0x3A0, 31);
++ clear_msr_range(0x3C0, 6);
++ clear_msr_range(0x3C8, 6);
++ clear_msr_range(0x3E0, 2);
++ clear_msr_range(MSR_P4_CCCR0, 18);
++ clear_msr_range(MSR_P4_PERFCTR0, 18);
++
++ wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
++ wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
++ Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
++ wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
++ apic_write(APIC_LVTPC, APIC_DM_NMI);
++ wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0);
++ return 1;
++}
++
++void __pminit setup_apic_nmi_watchdog (void)
++{
++ switch (boot_cpu_data.x86_vendor) {
++ case X86_VENDOR_AMD:
++ if (boot_cpu_data.x86 != 6)
++ return;
++ setup_k7_watchdog();
++ break;
++ case X86_VENDOR_INTEL:
++ switch (boot_cpu_data.x86) {
++ case 6:
++ setup_p6_watchdog();
++ break;
++ case 15:
++ if (!setup_p4_watchdog())
++ return;
++ break;
++ default:
++ return;
++ }
++ break;
++ default:
++ return;
++ }
++ nmi_pm_init();
++}
++
++static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED;
++
++/*
++ * the best way to detect whether a CPU has a 'hard lockup' problem
++ * is to check it's local APIC timer IRQ counts. If they are not
++ * changing then that CPU has some problem.
++ *
++ * as these watchdog NMI IRQs are generated on every CPU, we only
++ * have to check the current processor.
++ *
++ * since NMIs dont listen to _any_ locks, we have to be extremely
++ * careful not to rely on unsafe variables. The printk might lock
++ * up though, so we have to break up any console locks first ...
++ * [when there will be more tty-related locks, break them up
++ * here too!]
++ */
++
++static unsigned int
++ last_irq_sums [NR_CPUS],
++ alert_counter [NR_CPUS];
++
++void touch_nmi_watchdog (void)
++{
++ int i;
++
++ /*
++ * Just reset the alert counters, (other CPUs might be
++ * spinning on locks we hold):
++ */
++ for (i = 0; i < NR_CPUS; i++)
++ alert_counter[i] = 0;
++}
++
++static int nmi_watchdog_tick (void * dev_id, struct pt_regs * regs, int cpu,
++ int handled)
++{
++ /*
++ * Since current_thread_info()-> is always on the stack, and we
++ * always switch the stack NMI-atomically, it's safe to use
++ * smp_processor_id().
++ */
++ int sum;
++
++ if (! watchdog_reset(handled))
++ return NOTIFY_DONE; /* We are not an NMI source. */
++
++ sum = irq_stat[cpu].apic_timer_irqs;
++
++ if (last_irq_sums[cpu] == sum) {
++ /*
++ * Ayiee, looks like this CPU is stuck ...
++ * wait a few IRQs (5 seconds) before doing the oops ...
++ */
++ alert_counter[cpu]++;
++ if (alert_counter[cpu] == 5*nmi_hz) {
++ spin_lock(&nmi_print_lock);
++ /*
++ * We are in trouble anyway, lets at least try
++ * to get a message out.
++ */
++ bust_spinlocks(1);
++ printk("NMI Watchdog detected LOCKUP on CPU%d, eip %08lx, registers:\n", cpu, regs->eip);
++ show_registers(regs);
++ printk("console shuts up ...\n");
++ console_silent();
++ spin_unlock(&nmi_print_lock);
++ bust_spinlocks(0);
++ do_exit(SIGSEGV);
++ }
++ } else {
++ last_irq_sums[cpu] = sum;
++ alert_counter[cpu] = 0;
++ }
++
++ return NOTIFY_OK;
++}
+diff -urN linux.orig/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
+--- linux.orig/arch/i386/kernel/traps.c Mon Oct 21 13:25:45 2002
++++ linux/arch/i386/kernel/traps.c Thu Oct 24 19:54:16 2002
+@@ -40,7 +40,6 @@
+ #include <asm/debugreg.h>
+ #include <asm/desc.h>
+ #include <asm/i387.h>
+-#include <asm/nmi.h>
+
+ #include <asm/smp.h>
+ #include <asm/pgalloc.h>
+@@ -52,6 +51,7 @@
+ asmlinkage int system_call(void);
+ asmlinkage void lcall7(void);
+ asmlinkage void lcall27(void);
++void init_nmi(void);
+
+ struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
+ { 0, 0 }, { 0, 0 } };
+@@ -443,107 +443,6 @@
+ }
+ }
+
+-static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
+-{
+- printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
+- printk("You probably have a hardware problem with your RAM chips\n");
+-
+- /* Clear and disable the memory parity error line. */
+- reason = (reason & 0xf) | 4;
+- outb(reason, 0x61);
+-}
+-
+-static void io_check_error(unsigned char reason, struct pt_regs * regs)
+-{
+- unsigned long i;
+-
+- printk("NMI: IOCK error (debug interrupt?)\n");
+- show_registers(regs);
+-
+- /* Re-enable the IOCK line, wait for a few seconds */
+- reason = (reason & 0xf) | 8;
+- outb(reason, 0x61);
+- i = 2000;
+- while (--i) udelay(1000);
+- reason &= ~8;
+- outb(reason, 0x61);
+-}
+-
+-static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
+-{
+-#ifdef CONFIG_MCA
+- /* Might actually be able to figure out what the guilty party
+- * is. */
+- if( MCA_bus ) {
+- mca_handle_nmi();
+- return;
+- }
+-#endif
+- printk("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
+- reason, smp_processor_id());
+- printk("Dazed and confused, but trying to continue\n");
+- printk("Do you have a strange power saving mode enabled?\n");
+-}
+-
+-static void default_do_nmi(struct pt_regs * regs)
+-{
+- unsigned char reason = inb(0x61);
+-
+- if (!(reason & 0xc0)) {
+-#if CONFIG_X86_LOCAL_APIC
+- /*
+- * Ok, so this is none of the documented NMI sources,
+- * so it must be the NMI watchdog.
+- */
+- if (nmi_watchdog) {
+- nmi_watchdog_tick(regs);
+- return;
+- }
+-#endif
+- unknown_nmi_error(reason, regs);
+- return;
+- }
+- if (reason & 0x80)
+- mem_parity_error(reason, regs);
+- if (reason & 0x40)
+- io_check_error(reason, regs);
+- /*
+- * Reassert NMI in case it became active meanwhile
+- * as it's edge-triggered.
+- */
+- outb(0x8f, 0x70);
+- inb(0x71); /* dummy */
+- outb(0x0f, 0x70);
+- inb(0x71); /* dummy */
+-}
+-
+-static int dummy_nmi_callback(struct pt_regs * regs, int cpu)
+-{
+- return 0;
+-}
+-
+-static nmi_callback_t nmi_callback = dummy_nmi_callback;
+-
+-asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
+-{
+- int cpu = smp_processor_id();
+-
+- ++nmi_count(cpu);
+-
+- if (!nmi_callback(regs, cpu))
+- default_do_nmi(regs);
+-}
+-
+-void set_nmi_callback(nmi_callback_t callback)
+-{
+- nmi_callback = callback;
+-}
+-
+-void unset_nmi_callback(void)
+-{
+- nmi_callback = dummy_nmi_callback;
+-}
+-
+ /*
+ * Our handling of the processor debug registers is non-trivial.
+ * We do not clear them on entry and exit from the kernel. Therefore
+@@ -924,4 +823,6 @@
+ cpu_init();
+
+ trap_init_hook();
++
++ init_nmi();
+ }
+diff -urN linux.orig/arch/i386/oprofile/nmi_int.c linux/arch/i386/oprofile/nmi_int.c
+--- linux.orig/arch/i386/oprofile/nmi_int.c Mon Oct 21 13:25:45 2002
++++ linux/arch/i386/oprofile/nmi_int.c Thu Oct 24 16:03:31 2002
+@@ -54,12 +54,24 @@
+
+
+ // FIXME: kernel_only
+-static int nmi_callback(struct pt_regs * regs, int cpu)
++static int nmi_callback(void *dev_id, struct pt_regs *regs, int cpu, int handled)
+ {
+- return (model->check_ctrs(cpu, &cpu_msrs[cpu], regs));
++ if (model->check_ctrs(cpu, &cpu_msrs[cpu], regs))
++ return NOTIFY_OK;
++
++ return NOTIFY_DONE;
+ }
+
+-
++static struct nmi_handler nmi_handler =
++{
++ .link = LIST_HEAD_INIT(nmi_handler.link),
++ .dev_name = "oprofile",
++ .dev_id = NULL,
++ .handler = nmi_callback,
++ .priority = 1023, /* Very high priority. */
++};
++
++
+ static void nmi_save_registers(struct op_msrs * msrs)
+ {
+ unsigned int const nr_ctrs = model->num_counters;
+@@ -96,8 +108,12 @@
+ }
+
+
++static void nmi_cpu_shutdown(void * dummy);
++
+ static int nmi_setup(void)
+ {
++ int rv;
++
+ /* We walk a thin line between law and rape here.
+ * We need to be careful to install our NMI handler
+ * without actually triggering any NMIs as this will
+@@ -105,7 +121,13 @@
+ */
+ smp_call_function(nmi_cpu_setup, NULL, 0, 1);
+ nmi_cpu_setup(0);
+- set_nmi_callback(nmi_callback);
++ rv = request_nmi(&nmi_handler);
++ if (rv) {
++ smp_call_function(nmi_cpu_shutdown, NULL, 0, 1);
++ nmi_cpu_shutdown(0);
++ return rv;
++ }
++
+ oprofile_pmdev = set_nmi_pm_callback(oprofile_pm_callback);
+ return 0;
+ }
+@@ -145,7 +167,7 @@
+ static void nmi_shutdown(void)
+ {
+ unset_nmi_pm_callback(oprofile_pmdev);
+- unset_nmi_callback();
++ release_nmi(&nmi_handler);
+ smp_call_function(nmi_cpu_shutdown, NULL, 0, 1);
+ nmi_cpu_shutdown(0);
+ }
+diff -urN linux.orig/drivers/char/Config.help linux/drivers/char/Config.help
+--- linux.orig/drivers/char/Config.help Mon Oct 21 13:26:00 2002
++++ linux/drivers/char/Config.help Wed Oct 30 10:09:07 2002
+@@ -946,6 +946,26 @@
+
+ If compiled as a module, it will be called scx200_gpio.o.
+
++CONFIG_IPMI_HANDLER
++ This enables the central IMPI message handler, required for IPMI
++ to work. Note that you must have this enabled to do any other IPMI
++ things. See IPMI.txt for more details.
++
++CONFIG_IPMI_PANIC_EVENT
++ When a panic occurs, this will cause the IPMI message handler to
++ generate an IPMI event describing the panic to each interface
++ registered with the message handler.
++
++CONFIG_IPMI_DEVICE_INTERFACE
++ This provides an IOCTL interface to the IPMI message handler so
++ userland processes may use IPMI. It supports poll() and select().
++
++CONFIG_IPMI_KCS
++ Provides a driver for a KCS-style interface to a BMC.
++
++CONFIG_IPMI_WATCHDOG
++ This enables the IPMI watchdog timer.
++
+ Texas Instruments parallel link cable support
+ CONFIG_TIPAR
+ If you own a Texas Instruments graphing calculator and use a
+@@ -966,4 +986,4 @@
+ Instruments graphing calculator is, then you probably don't need this
+ driver.
+
+- If unsure, say N.
+\ No newline at end of file
++ If unsure, say N.
+diff -urN linux.orig/drivers/char/Config.in linux/drivers/char/Config.in
+--- linux.orig/drivers/char/Config.in Mon Oct 21 13:25:47 2002
++++ linux/drivers/char/Config.in Wed Oct 30 10:07:53 2002
+@@ -105,6 +105,12 @@
+ fi
+ fi
+
++tristate 'IPMI top-level message handler' CONFIG_IPMI_HANDLER
++dep_mbool ' Generate a panic event to all BMCs on a panic' CONFIG_IPMI_PANIC_EVENT $CONFIG_IPMI_HANDLER
++dep_tristate ' Device interface for IPMI' CONFIG_IPMI_DEVICE_INTERFACE $CONFIG_IPMI_HANDLER
++dep_tristate ' IPMI KCS handler' CONFIG_IPMI_KCS $CONFIG_IPMI_HANDLER
++dep_tristate ' IPMI Watchdog Timer' CONFIG_IPMI_WATCHDOG $CONFIG_IPMI_HANDLER
++
+ mainmenu_option next_comment
+ comment 'Watchdog Cards'
+ bool 'Watchdog Timer Support' CONFIG_WATCHDOG
+diff -urN linux.orig/drivers/char/Makefile linux/drivers/char/Makefile
+--- linux.orig/drivers/char/Makefile Mon Oct 21 13:26:00 2002
++++ linux/drivers/char/Makefile Mon Oct 21 13:27:57 2002
+@@ -103,6 +103,7 @@
+ obj-$(CONFIG_AGP) += agp/
+ obj-$(CONFIG_DRM) += drm/
+ obj-$(CONFIG_PCMCIA) += pcmcia/
++obj-$(CONFIG_IPMI_HANDLER) += ipmi/
+
+ # Files generated that shall be removed upon make clean
+ clean-files := consolemap_deftbl.c defkeymap.c qtronixmap.c
+diff -urN linux.orig/drivers/char/ipmi/Makefile linux/drivers/char/ipmi/Makefile
+--- linux.orig/drivers/char/ipmi/Makefile Wed Dec 31 18:00:00 1969
++++ linux/drivers/char/ipmi/Makefile Sun Oct 13 16:46:24 2002
+@@ -0,0 +1,17 @@
++#
++# Makefile for the ipmi drivers.
++#
++
++export-objs := ipmi_msghandler.o ipmi_watchdog.o
++
++ipmi_kcs_drv-objs := ipmi_kcs_sm.o ipmi_kcs_intf.o
++
++obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o
++obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
++obj-$(CONFIG_IPMI_KCS) += ipmi_kcs_drv.o
++obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
++
++include $(TOPDIR)/Rules.make
++
++ipmi_kcs_drv.o: $(ipmi_kcs_drv-objs)
++ $(LD) -r -o $@ $(ipmi_kcs_drv-objs)
+diff -urN linux.orig/drivers/char/ipmi/ipmi_devintf.c linux/drivers/char/ipmi/ipmi_devintf.c
+--- linux.orig/drivers/char/ipmi/ipmi_devintf.c Wed Dec 31 18:00:00 1969
++++ linux/drivers/char/ipmi/ipmi_devintf.c Wed Oct 30 13:51:55 2002
+@@ -0,0 +1,539 @@
++/*
++ * ipmi_devintf.c
++ *
++ * Linux device interface for the IPMI message handler.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <asm/system.h>
++#include <linux/sched.h>
++#include <linux/poll.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/devfs_fs_kernel.h>
++#include <linux/ipmi.h>
++#include <asm/semaphore.h>
++#include <linux/init.h>
++
++struct ipmi_file_private
++{
++ ipmi_user_t user;
++ spinlock_t recv_msg_lock;
++ struct list_head recv_msgs;
++ struct file *file;
++ struct fasync_struct *fasync_queue;
++ wait_queue_head_t wait;
++ struct semaphore recv_sem;
++};
++
++static void file_receive_handler(struct ipmi_recv_msg *msg,
++ void *handler_data)
++{
++ struct ipmi_file_private *priv = handler_data;
++ int was_empty;
++ unsigned long flags;
++
++ spin_lock_irqsave(&(priv->recv_msg_lock), flags);
++
++ was_empty = list_empty(&(priv->recv_msgs));
++ list_add_tail(&(msg->link), &(priv->recv_msgs));
++
++ if (was_empty) {
++ wake_up_interruptible(&priv->wait);
++ kill_fasync(&priv->fasync_queue, SIGIO, POLL_IN);
++ }
++
++ spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
++}
++
++static unsigned int ipmi_poll(struct file *file, poll_table *wait)
++{
++ struct ipmi_file_private *priv = file->private_data;
++ unsigned int mask = 0;
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->recv_msg_lock, flags);
++
++ poll_wait(file, &priv->wait, wait);
++
++ if (! list_empty(&(priv->recv_msgs)))
++ mask |= (POLLIN | POLLRDNORM);
++
++ spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
++
++ return mask;
++}
++
++static int ipmi_fasync(int fd, struct file *file, int on)
++{
++ struct ipmi_file_private *priv = file->private_data;
++ int result;
++
++ result = fasync_helper(fd, file, on, &priv->fasync_queue);
++
++ return (result);
++}
++
++static struct ipmi_user_hndl ipmi_hndlrs =
++{
++ ipmi_recv_hndl : file_receive_handler
++};
++
++static int ipmi_open(struct inode *inode, struct file *file)
++{
++ int if_num = minor(inode->i_rdev);
++ int rv;
++ struct ipmi_file_private *priv;
++
++
++ MOD_INC_USE_COUNT;
++
++ priv = kmalloc(sizeof(*priv), GFP_KERNEL);
++ if (!priv) {
++ MOD_DEC_USE_COUNT;
++ return -ENOMEM;
++ }
++
++ priv->file = file;
++
++ rv = ipmi_create_user(if_num,
++ &ipmi_hndlrs,
++ priv,
++ &(priv->user));
++ if (rv) {
++ kfree(priv);
++ MOD_DEC_USE_COUNT;
++ return rv;
++ }
++
++ file->private_data = priv;
++
++ spin_lock_init(&(priv->recv_msg_lock));
++ INIT_LIST_HEAD(&(priv->recv_msgs));
++ init_waitqueue_head(&priv->wait);
++ priv->fasync_queue = NULL;
++ sema_init(&(priv->recv_sem), 1);
++
++ return 0;
++}
++
++static int ipmi_release(struct inode *inode, struct file *file)
++{
++ struct ipmi_file_private *priv = file->private_data;
++ int rv;
++
++ rv = ipmi_destroy_user(priv->user);
++ if (rv)
++ return rv;
++
++ ipmi_fasync (-1, file, 0);
++
++ /* FIXME - free the messages in the list. */
++ kfree(priv);
++
++ MOD_DEC_USE_COUNT;
++
++ return 0;
++}
++
++static int ipmi_ioctl(struct inode *inode,
++ struct file *file,
++ unsigned int cmd,
++ unsigned long data)
++{
++ int rv = -EINVAL;
++ struct ipmi_file_private *priv = file->private_data;
++
++ switch (cmd)
++ {
++ case IPMICTL_SEND_COMMAND:
++ {
++ struct ipmi_req req;
++ struct ipmi_addr addr;
++ unsigned char msgdata[IPMI_MAX_MSG_LENGTH];
++
++ if (copy_from_user(&req, (void *) data, sizeof(req))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ if (req.addr_len > sizeof(struct ipmi_addr))
++ {
++ rv = -EINVAL;
++ break;
++ }
++
++ if (copy_from_user(&addr, req.addr, req.addr_len)) {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = ipmi_validate_addr(&addr, req.addr_len);
++ if (rv)
++ break;
++
++ if (req.msg.data != NULL) {
++ if (req.msg.data_len > IPMI_MAX_MSG_LENGTH) {
++ rv = -EMSGSIZE;
++ break;
++ }
++
++ if (copy_from_user(&msgdata,
++ req.msg.data,
++ req.msg.data_len))
++ {
++ rv = -EFAULT;
++ break;
++ }
++ } else {
++ req.msg.data_len = 0;
++ }
++
++ req.msg.data = msgdata;
++
++ rv = ipmi_request(priv->user,
++ &addr,
++ req.msgid,
++ &(req.msg),
++ 0);
++ break;
++ }
++
++ case IPMICTL_RECEIVE_MSG:
++ case IPMICTL_RECEIVE_MSG_TRUNC:
++ {
++ struct ipmi_recv rsp;
++ int addr_len;
++ struct list_head *entry;
++ struct ipmi_recv_msg *msg;
++ unsigned long flags;
++
++
++ rv = 0;
++ if (copy_from_user(&rsp, (void *) data, sizeof(rsp))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ /* We claim a semaphore because we don't want two
++ users getting something from the queue at a time.
++ Since we have to release the spinlock before we can
++ copy the data to the user, it's possible another
++ user will grab something from the queue, too. Then
++ the messages might get out of order if something
++ fails and the message gets put back onto the
++ queue. This semaphore prevents that problem. */
++ down(&(priv->recv_sem));
++
++ /* Grab the message off the list. */
++ spin_lock_irqsave(&(priv->recv_msg_lock), flags);
++ if (list_empty(&(priv->recv_msgs))) {
++ spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
++ rv = -EAGAIN;
++ goto recv_err;
++ }
++ entry = priv->recv_msgs.next;
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ list_del(entry);
++ spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
++
++ addr_len = ipmi_addr_length(msg->addr.addr_type);
++ if (rsp.addr_len < addr_len)
++ {
++ rv = -EINVAL;
++ goto recv_putback_on_err;
++ }
++
++ if (copy_to_user(rsp.addr, &(msg->addr), addr_len)) {
++ rv = -EFAULT;
++ goto recv_putback_on_err;
++ }
++ rsp.addr_len = addr_len;
++
++ rsp.recv_type = msg->recv_type;
++ rsp.msgid = msg->msgid;
++ rsp.msg.netfn = msg->msg.netfn;
++ rsp.msg.cmd = msg->msg.cmd;
++
++ if (msg->msg.data_len > 0) {
++ if (rsp.msg.data_len < msg->msg.data_len) {
++ rv = -EMSGSIZE;
++ if (cmd == IPMICTL_RECEIVE_MSG_TRUNC) {
++ msg->msg.data_len = rsp.msg.data_len;
++ } else {
++ goto recv_putback_on_err;
++ }
++ }
++
++ if (copy_to_user(rsp.msg.data,
++ msg->msg.data,
++ msg->msg.data_len))
++ {
++ rv = -EFAULT;
++ goto recv_putback_on_err;
++ }
++ rsp.msg.data_len = msg->msg.data_len;
++ } else {
++ rsp.msg.data_len = 0;
++ }
++
++ if (copy_to_user((void *) data, &rsp, sizeof(rsp))) {
++ rv = -EFAULT;
++ goto recv_putback_on_err;
++ }
++
++ up(&(priv->recv_sem));
++ ipmi_free_recv_msg(msg);
++ break;
++
++ recv_putback_on_err:
++ /* If we got an error, put the message back onto
++ the head of the queue. */
++ spin_lock_irqsave(&(priv->recv_msg_lock), flags);
++ list_add(entry, &(priv->recv_msgs));
++ spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
++ up(&(priv->recv_sem));
++ break;
++
++ recv_err:
++ up(&(priv->recv_sem));
++ break;
++ }
++
++ case IPMICTL_REGISTER_FOR_CMD:
++ {
++ struct ipmi_cmdspec val;
++
++ if (copy_from_user(&val, (void *) data, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd);
++ break;
++ }
++
++ case IPMICTL_UNREGISTER_FOR_CMD:
++ {
++ struct ipmi_cmdspec val;
++
++ if (copy_from_user(&val, (void *) data, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd);
++ break;
++ }
++
++ case IPMICTL_SET_GETS_EVENTS_CMD:
++ {
++ int val;
++
++ if (copy_from_user(&val, (void *) data, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = ipmi_set_gets_events(priv->user, val);
++ break;
++ }
++
++ case IPMICTL_SET_MY_ADDRESS_CMD:
++ {
++ unsigned int val;
++
++ if (copy_from_user(&val, (void *) data, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ ipmi_set_my_address(priv->user, val);
++ rv = 0;
++ break;
++ }
++
++ case IPMICTL_GET_MY_ADDRESS_CMD:
++ {
++ unsigned int val;
++
++ val = ipmi_get_my_address(priv->user);
++
++ if (copy_to_user((void *) data, &val, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++ rv = 0;
++ break;
++ }
++
++ case IPMICTL_SET_MY_LUN_CMD:
++ {
++ unsigned int val;
++
++ if (copy_from_user(&val, (void *) data, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ ipmi_set_my_LUN(priv->user, val);
++ rv = 0;
++ break;
++ }
++
++ case IPMICTL_GET_MY_LUN_CMD:
++ {
++ unsigned int val;
++
++ val = ipmi_get_my_LUN(priv->user);
++
++ if (copy_to_user((void *) data, &val, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++ rv = 0;
++ break;
++ }
++
++ }
++
++ return rv;
++}
++
++
++static struct file_operations ipmi_fops = {
++ owner: THIS_MODULE,
++ ioctl: ipmi_ioctl,
++ open: ipmi_open,
++ release: ipmi_release,
++ fasync: ipmi_fasync,
++ poll: ipmi_poll
++};
++
++#define DEVICE_NAME "ipmidev"
++
++static int ipmi_major = 0;
++MODULE_PARM(ipmi_major, "i");
++
++static devfs_handle_t devfs_handle;
++
++#define MAX_DEVICES 10
++static devfs_handle_t handles[MAX_DEVICES];
++
++static void ipmi_new_smi(int if_num)
++{
++ char name[2];
++
++ if (if_num > MAX_DEVICES)
++ return;
++
++ name[0] = if_num + '0';
++ name[1] = '\0';
++
++ handles[if_num] = devfs_register(devfs_handle, name, DEVFS_FL_NONE,
++ ipmi_major, if_num,
++ S_IFCHR | S_IRUSR | S_IWUSR,
++ &ipmi_fops, NULL);
++}
++
++static void ipmi_smi_gone(int if_num)
++{
++ if (if_num > MAX_DEVICES)
++ return;
++
++ devfs_unregister(handles[if_num]);
++}
++
++static struct ipmi_smi_watcher smi_watcher =
++{
++ new_smi : ipmi_new_smi,
++ smi_gone : ipmi_smi_gone
++};
++
++static __init int init_ipmi_devintf(void)
++{
++ int rv;
++
++ if (ipmi_major < 0)
++ return -EINVAL;
++
++ rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
++ if (rv < 0) {
++ printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major);
++ return rv;
++ }
++
++ if (ipmi_major == 0) {
++ ipmi_major = rv;
++ }
++
++ rv = ipmi_smi_watcher_register(&smi_watcher);
++ if (rv) {
++ unregister_chrdev(ipmi_major, DEVICE_NAME);
++ printk(KERN_WARNING "ipmi: can't register smi watcher");
++ return rv;
++ }
++
++ devfs_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL);
++
++ printk(KERN_INFO "ipmi: device interface at char major %d\n",
++ ipmi_major);
++
++ return 0;
++}
++module_init(init_ipmi_devintf);
++
++static __exit void cleanup_ipmi(void)
++{
++ ipmi_smi_watcher_unregister(&smi_watcher);
++ devfs_unregister(devfs_handle);
++ unregister_chrdev(ipmi_major, DEVICE_NAME);
++}
++module_exit(cleanup_ipmi);
++#ifndef MODULE
++static __init int ipmi_setup (char *str)
++{
++ int x;
++
++ if (get_option (&str, &x)) {
++ /* ipmi=x sets the major number to x. */
++ ipmi_major = x;
++ } else if (!strcmp(str, "off")) {
++ ipmi_major = -1;
++ }
++
++ return 1;
++}
++#endif
++
++__setup("ipmi=", ipmi_setup);
++MODULE_LICENSE("GPL");
+diff -urN linux.orig/drivers/char/ipmi/ipmi_kcs_intf.c linux/drivers/char/ipmi/ipmi_kcs_intf.c
+--- linux.orig/drivers/char/ipmi/ipmi_kcs_intf.c Wed Dec 31 18:00:00 1969
++++ linux/drivers/char/ipmi/ipmi_kcs_intf.c Wed Oct 30 13:51:55 2002
+@@ -0,0 +1,991 @@
++/*
++ * ipmi_kcs_intf.c
++ *
++ * The interface to the IPMI driver for the KCS.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++/*
++ * This file holds the "policy" for the interface to the KCS state
++ * machine. It does the configuration, handles timers and interrupts,
++ * and drives the real KCS state machine.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <asm/system.h>
++#include <linux/sched.h>
++#include <linux/timer.h>
++#include <linux/errno.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/list.h>
++#include <linux/ioport.h>
++#ifdef CONFIG_HIGH_RES_TIMERS
++#include <linux/hrtime.h>
++#endif
++#include <linux/ipmi_smi.h>
++#include <asm/irq.h>
++#include <asm/io.h>
++#include "ipmi_kcs_sm.h"
++#include <linux/init.h>
++
++/* Measure times between events in the driver. */
++#undef DEBUG_TIMING
++
++#ifdef CONFIG_IPMI_KCS
++/* This forces a dependency to the config file for this option. */
++#endif
++
++enum kcs_intf_state {
++ KCS_NORMAL,
++ KCS_GETTING_FLAGS,
++ KCS_GETTING_EVENTS,
++ KCS_CLEARING_FLAGS,
++ KCS_CLEARING_FLAGS_THEN_SET_IRQ,
++ KCS_GETTING_MESSAGES,
++ KCS_ENABLE_INTERRUPTS1,
++ KCS_ENABLE_INTERRUPTS2
++ /* FIXME - add watchdog stuff. */
++};
++
++struct kcs_info
++{
++ ipmi_smi_t intf;
++ struct kcs_data *kcs_sm;
++ spinlock_t kcs_lock;
++ struct list_head xmit_msgs;
++ struct list_head hp_xmit_msgs;
++ struct ipmi_smi_msg *curr_msg;
++ enum kcs_intf_state kcs_state;
++
++ /* Flags from the last GET_MSG_FLAGS command, used when an ATTN
++ is set to hold the flags until we are done handling everything
++ from the flags. */
++#define RECEIVE_MSG_AVAIL 0x01
++#define EVENT_MSG_BUFFER_FULL 0x02
++#define WDT_PRE_TIMEOUT_INT 0x08
++ unsigned char msg_flags;
++
++ /* If set to true, this will request events the next time the
++ state machine is idle. */
++ int req_events;
++
++ /* If true, run the state machine to completion on every send
++ call. Generally used after a panic to make sure stuff goes
++ out. */
++ int run_to_completion;
++
++ /* The I/O address of the KCS interface. */
++ int addr;
++
++ /* zero if no irq; */
++ int irq;
++
++ /* The timer for this kcs. */
++ struct timer_list kcs_timer;
++
++ /* The time (in jiffies) the last timeout occurred at. */
++ unsigned long last_timeout_jiffies;
++
++ /* Used to gracefully stop the timer without race conditions. */
++ volatile int stop_operation;
++ volatile int timer_stopped;
++
++ /* The driver will disable interrupts when it gets into a
++ situation where it cannot handle messages due to lack of
++ memory. Once that situation clears up, it will re-enable
++ interupts. */
++ int interrupt_disabled;
++};
++
++static void deliver_recv_msg(struct kcs_info *kcs_info, struct ipmi_smi_msg *msg)
++{
++ /* Deliver the message to the upper layer with the lock
++ released. */
++ spin_unlock(&(kcs_info->kcs_lock));
++ ipmi_smi_msg_received(kcs_info->intf, msg);
++ spin_lock(&(kcs_info->kcs_lock));
++}
++
++static void return_hosed_msg(struct kcs_info *kcs_info)
++{
++ struct ipmi_smi_msg *msg = kcs_info->curr_msg;
++
++ /* Make it a reponse */
++ msg->rsp[0] = msg->data[0] | 4;
++ msg->rsp[1] = msg->data[1];
++ msg->rsp[2] = 0xff; /* Unknown error. */
++ msg->rsp_size = 3;
++
++ deliver_recv_msg(kcs_info, msg);
++ kcs_info->curr_msg = NULL;
++}
++
++static enum kcs_result start_next_msg(struct kcs_info *kcs_info)
++{
++ int rv;
++ struct list_head *entry = NULL;
++#ifdef DEBUG_TIMING
++ struct timeval t;
++#endif
++
++ /* Pick the high priority queue first. */
++ if (! list_empty(&(kcs_info->hp_xmit_msgs))) {
++ entry = kcs_info->hp_xmit_msgs.next;
++ } else if (! list_empty(&(kcs_info->xmit_msgs))) {
++ entry = kcs_info->xmit_msgs.next;
++ }
++
++ if (!entry) {
++ kcs_info->curr_msg = NULL;
++ return KCS_SM_IDLE;
++ } else {
++ list_del(entry);
++ kcs_info->curr_msg = list_entry(entry,
++ struct ipmi_smi_msg,
++ link);
++#ifdef DEBUG_TIMING
++ do_gettimeofday(&t);
++ printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++ rv = start_kcs_transaction(kcs_info->kcs_sm,
++ kcs_info->curr_msg->data,
++ kcs_info->curr_msg->data_size);
++ if (rv) {
++ return_hosed_msg(kcs_info);
++ }
++
++ return KCS_CALL_WITHOUT_DELAY;
++ }
++}
++
++static void start_enable_irq(struct kcs_info *kcs_info)
++{
++ unsigned char msg[2];
++
++ /* If we are enabling interrupts, we have to tell the
++ BMC to use them. */
++ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
++
++ start_kcs_transaction(kcs_info->kcs_sm, msg, 2);
++ kcs_info->kcs_state = KCS_ENABLE_INTERRUPTS1;
++}
++
++static void start_clear_flags(struct kcs_info *kcs_info)
++{
++ unsigned char msg[3];
++
++ /* Make sure the watchdog pre-timeout flag is not set at startup. */
++ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
++ msg[2] = WDT_PRE_TIMEOUT_INT;
++
++ start_kcs_transaction(kcs_info->kcs_sm, msg, 3);
++ kcs_info->kcs_state = KCS_CLEARING_FLAGS;
++}
++
++/* When we have a situtaion where we run out of memory and cannot
++ allocate messages, we just leave them in the BMC and run the system
++ polled until we can allocate some memory. Once we have some
++ memory, we will re-enable the interrupt. */
++static inline void disable_kcs_irq(struct kcs_info *kcs_info)
++{
++ if ((kcs_info->irq) && (!kcs_info->interrupt_disabled)) {
++ disable_irq_nosync(kcs_info->irq);
++ kcs_info->interrupt_disabled = 1;
++ }
++}
++
++static inline void enable_kcs_irq(struct kcs_info *kcs_info)
++{
++ if ((kcs_info->irq) && (kcs_info->interrupt_disabled)) {
++ enable_irq(kcs_info->irq);
++ kcs_info->interrupt_disabled = 0;
++ }
++}
++
++static void handle_flags(struct kcs_info *kcs_info)
++{
++ if (kcs_info->msg_flags & WDT_PRE_TIMEOUT_INT) {
++ /* Watchdog pre-timeout */
++ start_clear_flags(kcs_info);
++ spin_unlock(&(kcs_info->kcs_lock));
++ ipmi_smi_watchdog_pretimeout(kcs_info->intf);
++ spin_lock(&(kcs_info->kcs_lock));
++ } else if (kcs_info->msg_flags & RECEIVE_MSG_AVAIL) {
++ /* Messages available. */
++ kcs_info->curr_msg = ipmi_alloc_smi_msg();
++ if (!kcs_info->curr_msg) {
++ disable_kcs_irq(kcs_info);
++ kcs_info->kcs_state = KCS_NORMAL;
++ return;
++ }
++ enable_kcs_irq(kcs_info);
++
++ kcs_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ kcs_info->curr_msg->data[1] = IPMI_GET_MSG_CMD;
++ kcs_info->curr_msg->data_size = 2;
++
++ start_kcs_transaction(kcs_info->kcs_sm,
++ kcs_info->curr_msg->data,
++ kcs_info->curr_msg->data_size);
++ kcs_info->kcs_state = KCS_GETTING_MESSAGES;
++ } else if (kcs_info->msg_flags & EVENT_MSG_BUFFER_FULL) {
++ /* Events available. */
++ kcs_info->curr_msg = ipmi_alloc_smi_msg();
++ if (!kcs_info->curr_msg) {
++ disable_kcs_irq(kcs_info);
++ kcs_info->kcs_state = KCS_NORMAL;
++ return;
++ }
++ enable_kcs_irq(kcs_info);
++
++ kcs_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ kcs_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD;
++ kcs_info->curr_msg->data_size = 2;
++
++ start_kcs_transaction(kcs_info->kcs_sm,
++ kcs_info->curr_msg->data,
++ kcs_info->curr_msg->data_size);
++ kcs_info->kcs_state = KCS_GETTING_EVENTS;
++ } else {
++ kcs_info->kcs_state = KCS_NORMAL;
++ }
++}
++
++static void handle_transaction_done(struct kcs_info *kcs_info)
++{
++#ifdef DEBUG_TIMING
++ struct timeval t;
++
++ do_gettimeofday(&t);
++ printk("**Done: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++ switch (kcs_info->kcs_state) {
++ case KCS_NORMAL:
++ kcs_info->curr_msg->rsp_size
++ = kcs_get_result(kcs_info->kcs_sm,
++ kcs_info->curr_msg->rsp,
++ IPMI_MAX_MSG_LENGTH);
++
++ deliver_recv_msg(kcs_info, kcs_info->curr_msg);
++ kcs_info->curr_msg = NULL;
++ break;
++
++ case KCS_GETTING_FLAGS:
++ {
++ unsigned char msg[4];
++
++ /* We got the flags from the KCS, now handle them. */
++ kcs_get_result(kcs_info->kcs_sm, msg, 4);
++ if (msg[2] != 0) {
++ /* Error fetching flags, just give up for
++ now. */
++ kcs_info->kcs_state = KCS_NORMAL;
++ } else {
++ kcs_info->msg_flags = msg[3];
++ handle_flags(kcs_info);
++ }
++ break;
++ }
++
++ case KCS_CLEARING_FLAGS:
++ case KCS_CLEARING_FLAGS_THEN_SET_IRQ:
++ {
++ unsigned char msg[3];
++
++ /* We cleared the flags. */
++ kcs_get_result(kcs_info->kcs_sm, msg, 3);
++ if (msg[2] != 0) {
++ /* Error clearing flags */
++ printk("ipmi_kcs_intf: Error clearing flags: %2.2x\n",
++ msg[2]);
++ }
++ if (kcs_info->kcs_state == KCS_CLEARING_FLAGS_THEN_SET_IRQ)
++ start_enable_irq(kcs_info);
++ else
++ kcs_info->kcs_state = KCS_NORMAL;
++ break;
++ }
++
++ case KCS_GETTING_EVENTS:
++ {
++ kcs_info->curr_msg->rsp_size
++ = kcs_get_result(kcs_info->kcs_sm,
++ kcs_info->curr_msg->rsp,
++ IPMI_MAX_MSG_LENGTH);
++
++ if (kcs_info->curr_msg->rsp[2] != 0) {
++ /* Error getting event, probably done. */
++ kcs_info->curr_msg->done(kcs_info->curr_msg);
++
++ /* Take off the event flag. */
++ kcs_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
++ } else {
++ deliver_recv_msg(kcs_info, kcs_info->curr_msg);
++ }
++ kcs_info->curr_msg = NULL;
++ handle_flags(kcs_info);
++ break;
++ }
++
++ case KCS_GETTING_MESSAGES:
++ {
++ kcs_info->curr_msg->rsp_size
++ = kcs_get_result(kcs_info->kcs_sm,
++ kcs_info->curr_msg->rsp,
++ IPMI_MAX_MSG_LENGTH);
++
++ if (kcs_info->curr_msg->rsp[2] != 0) {
++ /* Error getting event, probably done. */
++ kcs_info->curr_msg->done(kcs_info->curr_msg);
++
++ /* Take off the msg flag. */
++ kcs_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
++ } else {
++ deliver_recv_msg(kcs_info, kcs_info->curr_msg);
++ }
++ kcs_info->curr_msg = NULL;
++ handle_flags(kcs_info);
++ break;
++ }
++
++ case KCS_ENABLE_INTERRUPTS1:
++ {
++ unsigned char msg[4];
++
++ /* We got the flags from the KCS, now handle them. */
++ kcs_get_result(kcs_info->kcs_sm, msg, 4);
++ if (msg[2] != 0) {
++ printk(KERN_WARNING
++ "ipmi_kcs: Could not enable interrupts"
++ ", failed get, using polled mode.\n");
++ kcs_info->kcs_state = KCS_NORMAL;
++ } else {
++ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
++ msg[2] = msg[3] | 1; /* enable msg queue int */
++ start_kcs_transaction(kcs_info->kcs_sm, msg,3);
++ kcs_info->kcs_state = KCS_ENABLE_INTERRUPTS2;
++ }
++ break;
++ }
++
++ case KCS_ENABLE_INTERRUPTS2:
++ {
++ unsigned char msg[4];
++
++ /* We got the flags from the KCS, now handle them. */
++ kcs_get_result(kcs_info->kcs_sm, msg, 4);
++ if (msg[2] != 0) {
++ printk(KERN_WARNING
++ "ipmi_kcs: Could not enable interrupts"
++ ", failed set, using polled mode.\n");
++ }
++ kcs_info->kcs_state = KCS_NORMAL;
++ break;
++ }
++ }
++}
++
++/* Called on timeouts and events. Timeouts should pass the elapsed
++ time, interrupts should pass in zero. */
++static enum kcs_result kcs_event_handler(struct kcs_info *kcs_info, int time)
++{
++ enum kcs_result kcs_result;
++
++ restart:
++ /* There used to be a loop here that waited a little while
++ (around 25us) before giving up. That turned out to be
++ pointless, the minimum delays I was seeing were in the 300us
++ range, which is far too long to wait in an interrupt. So
++ we just run until the state machine tells us something
++ happened or it needs a delay. */
++ kcs_result = kcs_event(kcs_info->kcs_sm, time);
++ time = 0;
++ while (kcs_result == KCS_CALL_WITHOUT_DELAY)
++ {
++ kcs_result = kcs_event(kcs_info->kcs_sm, 0);
++ }
++
++ if (kcs_result == KCS_TRANSACTION_COMPLETE)
++ {
++ handle_transaction_done(kcs_info);
++ kcs_result = kcs_event(kcs_info->kcs_sm, 0);
++ }
++ else if (kcs_result == KCS_SM_HOSED)
++ {
++ if (kcs_info->curr_msg != NULL) {
++ /* If we were handling a user message, format
++ a response to send to the upper layer to
++ tell it about the error. */
++ return_hosed_msg(kcs_info);
++ }
++ kcs_result = kcs_event(kcs_info->kcs_sm, 0);
++ kcs_info->kcs_state = KCS_NORMAL;
++ }
++
++ /* We prefer handling attn over new messages. */
++ if (kcs_result == KCS_ATTN)
++ {
++ unsigned char msg[2];
++
++ /* Got a attn, send down a get message flags to see
++ what's causing it. It would be better to handle
++ this in the upper layer, but due to the way
++ interrupts work with the KCS, that's not really
++ possible. */
++ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg[1] = IPMI_GET_MSG_FLAGS_CMD;
++
++ start_kcs_transaction(kcs_info->kcs_sm, msg, 2);
++ kcs_info->kcs_state = KCS_GETTING_FLAGS;
++ goto restart;
++ }
++
++ /* If we are currently idle, try to start the next message. */
++ if (kcs_result == KCS_SM_IDLE) {
++ kcs_result = start_next_msg(kcs_info);
++ if (kcs_result != KCS_SM_IDLE)
++ goto restart;
++ }
++
++ if ((kcs_result == KCS_SM_IDLE) && (kcs_info->req_events)) {
++ /* We are idle and the upper layer requested that I fetch
++ events, so do so. */
++ unsigned char msg[2];
++
++ kcs_info->req_events = 0;
++ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg[1] = IPMI_GET_MSG_FLAGS_CMD;
++
++ start_kcs_transaction(kcs_info->kcs_sm, msg, 2);
++ kcs_info->kcs_state = KCS_GETTING_FLAGS;
++ goto restart;
++ }
++
++ return kcs_result;
++}
++
++static void sender(void *send_info,
++ struct ipmi_smi_msg *msg,
++ int priority)
++{
++ struct kcs_info *kcs_info = (struct kcs_info *) send_info;
++ enum kcs_result result;
++ unsigned long flags;
++#ifdef DEBUG_TIMING
++ struct timeval t;
++#endif
++
++ spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
++#ifdef DEBUG_TIMING
++ do_gettimeofday(&t);
++ printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++
++ if (kcs_info->run_to_completion) {
++ /* If we are running to completion, then throw it in
++ the list and run transactions until everything is
++ clear. Priority doesn't matter here. */
++ list_add_tail(&(msg->link), &(kcs_info->xmit_msgs));
++ result = kcs_event_handler(kcs_info, 0);
++ while (result != KCS_SM_IDLE) {
++ udelay(500);
++ result = kcs_event_handler(kcs_info, 500);
++ }
++ } else if ((kcs_info->kcs_state == KCS_NORMAL)
++ && (kcs_info->curr_msg == NULL))
++ {
++ int rv;
++#ifdef DEBUG_TIMING
++ do_gettimeofday(&t);
++ printk("**Start1: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++ kcs_info->curr_msg = msg;
++ rv = start_kcs_transaction(kcs_info->kcs_sm,
++ kcs_info->curr_msg->data,
++ kcs_info->curr_msg->data_size);
++ /* If we get an error, put it in the queue to try again
++ later. */
++ if (rv) {
++ kcs_info->curr_msg = NULL;
++ goto add_to_list;
++ }
++ } else {
++ add_to_list:
++ if (priority > 0) {
++ list_add_tail(&(msg->link), &(kcs_info->hp_xmit_msgs));
++ } else {
++ list_add_tail(&(msg->link), &(kcs_info->xmit_msgs));
++ }
++ }
++
++ spin_unlock_irqrestore(&(kcs_info->kcs_lock), flags);
++}
++
++static void set_run_to_completion(void *send_info, int i_run_to_completion)
++{
++ struct kcs_info *kcs_info = (struct kcs_info *) send_info;
++ enum kcs_result result;
++ unsigned long flags;
++
++ spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
++
++ kcs_info->run_to_completion = i_run_to_completion;
++ if (i_run_to_completion) {
++ result = kcs_event_handler(kcs_info, 0);
++ while (result != KCS_SM_IDLE) {
++ udelay(500);
++ result = kcs_event_handler(kcs_info, 500);
++ }
++ }
++
++ spin_unlock_irqrestore(&(kcs_info->kcs_lock), flags);
++}
++
++static void request_events(void *send_info)
++{
++ struct kcs_info *kcs_info = (struct kcs_info *) send_info;
++
++ kcs_info->req_events = 1;
++}
++
++static void new_user(void *send_info)
++{
++ MOD_INC_USE_COUNT;
++}
++
++static void user_left(void *send_info)
++{
++ MOD_DEC_USE_COUNT;
++}
++
++/* Call every 10 ms. */
++#define KCS_TIMEOUT_TIME_USEC 10000
++#define KCS_USEC_PER_JIFFY (1000000/HZ)
++#define KCS_TIMEOUT_JIFFIES (KCS_TIMEOUT_TIME_USEC/KCS_USEC_PER_JIFFY)
++#define KCS_SHORT_TIMEOUT_USEC 500 /* .5ms when the SM request a
++ short timeout */
++static int initialized = 0;
++
++static void kcs_timeout(unsigned long data)
++{
++ struct kcs_info *kcs_info = (struct kcs_info *) data;
++ enum kcs_result kcs_result;
++ unsigned long flags;
++ unsigned long jiffies_now;
++ unsigned long time_diff;
++#ifdef DEBUG_TIMING
++ struct timeval t;
++#endif
++
++ if (kcs_info->stop_operation) {
++ kcs_info->timer_stopped = 1;
++ return;
++ }
++
++ spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
++#ifdef DEBUG_TIMING
++ do_gettimeofday(&t);
++ printk("**Timer: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++ jiffies_now = jiffies;
++ time_diff = ((jiffies_now - kcs_info->last_timeout_jiffies)
++ * KCS_USEC_PER_JIFFY);
++ kcs_result = kcs_event_handler(kcs_info, time_diff);
++
++ spin_unlock_irqrestore(&(kcs_info->kcs_lock), flags);
++
++ kcs_info->last_timeout_jiffies = jiffies_now;
++
++ if ((kcs_info->irq) && (! kcs_info->interrupt_disabled)) {
++ /* Running with interrupts, only do long timeouts. */
++ kcs_info->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES;
++ goto do_add_timer;
++ }
++
++ /* If the state machine asks for a short delay, then shorten
++ the timer timeout. */
++#ifdef CONFIG_HIGH_RES_TIMERS
++ if (kcs_result == KCS_CALL_WITH_DELAY) {
++ kcs_info->kcs_timer.sub_expires
++ += usec_to_arch_cycles(KCS_SHORT_TIMEOUT_USEC);
++ while (kcs_info->kcs_timer.sub_expires >= cycles_per_jiffies) {
++ kcs_info->kcs_timer.expires++;
++ kcs_info->kcs_timer.sub_expires -= cycles_per_jiffies;
++ }
++ } else {
++ kcs_info->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES;
++ }
++#else
++ /* If we have a fast clock tick, we take advantage of it. */
++ if (kcs_result == KCS_CALL_WITH_DELAY) {
++ kcs_info->kcs_timer.expires = jiffies + 1;
++ } else {
++ kcs_info->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES;
++ }
++#endif
++
++ do_add_timer:
++ add_timer(&(kcs_info->kcs_timer));
++}
++
++static void kcs_irq_handler(int irq, void *data, struct pt_regs *regs)
++{
++ struct kcs_info *kcs_info = (struct kcs_info *) data;
++ unsigned long flags;
++#ifdef DEBUG_TIMING
++ struct timeval t;
++#endif
++
++ spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
++#ifdef DEBUG_TIMING
++ do_gettimeofday(&t);
++ printk("**Interrupt: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++ kcs_event_handler(kcs_info, 0);
++ spin_unlock_irqrestore(&(kcs_info->kcs_lock), flags);
++}
++
++static struct ipmi_smi_handlers handlers =
++{
++ sender: sender,
++ request_events: request_events,
++ new_user: new_user,
++ user_left: user_left,
++ set_run_to_completion: set_run_to_completion
++};
++
++static unsigned char ipmi_kcs_dev_rev;
++static unsigned char ipmi_kcs_fw_rev_major;
++static unsigned char ipmi_kcs_fw_rev_minor;
++static unsigned char ipmi_version_major;
++static unsigned char ipmi_version_minor;
++
++extern int kcs_dbg;
++static int ipmi_kcs_detect_hardware(int port, struct kcs_data *data)
++{
++ unsigned char msg[2];
++ unsigned char resp[IPMI_MAX_MSG_LENGTH];
++ unsigned long resp_len;
++ enum kcs_result kcs_result;
++
++ /* It's impossible for the KCS status register to be all 1's,
++ but that's what you get from reading a bogus address, so we
++ test that first. */
++ if (inb(port+1) == 0xff)
++ return -ENODEV;
++
++ /* Do a Get Device ID command, since it comes back with some
++ useful info. */
++ msg[0] = IPMI_NETFN_APP_REQUEST << 2;
++ msg[1] = IPMI_GET_DEVICE_ID_CMD;
++ start_kcs_transaction(data, msg, 2);
++
++ kcs_result = kcs_event(data, 0);
++ for (;;)
++ {
++ if (kcs_result == KCS_CALL_WITH_DELAY) {
++ udelay(100);
++ kcs_result = kcs_event(data, 100);
++ }
++ else if (kcs_result == KCS_CALL_WITHOUT_DELAY)
++ {
++ kcs_result = kcs_event(data, 0);
++ }
++ else
++ break;
++ }
++ if (kcs_result == KCS_SM_HOSED) {
++ /* We couldn't get the state machine to run, so whatever's at
++ the port is probably not an IPMI KCS interface. */
++ return -ENODEV;
++ }
++ /* Otherwise, we got some data. */
++ resp_len = kcs_get_result(data, resp, IPMI_MAX_MSG_LENGTH);
++ if (resp_len < 6)
++ /* That's odd, it should be longer. */
++ return -EINVAL;
++
++ if ((resp[1] != IPMI_GET_DEVICE_ID_CMD) || (resp[2] != 0))
++ /* That's odd, it shouldn't be able to fail. */
++ return -EINVAL;
++
++ ipmi_kcs_dev_rev = resp[4] & 0xf;
++ ipmi_kcs_fw_rev_major = resp[5] & 0x7f;
++ ipmi_kcs_fw_rev_minor = resp[6];
++ ipmi_version_major = resp[7] & 0xf;
++ ipmi_version_minor = resp[7] >> 4;
++
++ return 0;
++}
++
++#define MAX_KCS_DRIVERS 4
++static struct kcs_info *kcs_info[MAX_KCS_DRIVERS];
++
++#define DEVICE_NAME "ipmi_kcs"
++
++#define DEFAULT_IO_ADDR 0xca2
++
++static int kcs_addrs[MAX_KCS_DRIVERS] = { 0, -1, -1, -1 };
++static int kcs_irqs[MAX_KCS_DRIVERS] = { 0, 0, 0, 0 };
++
++MODULE_PARM(kcs_addrs, "1-4i");
++MODULE_PARM(kcs_irqs, "1-4i");
++
++/* Returns 0 if initialized, or negative on an error. */
++static int init_one_kcs(int kcs_addr, int irq, struct kcs_info **kcs)
++{
++ int rv;
++ struct kcs_info *new_kcs;
++
++
++ /* The setup set the kcs address negative if it wants to
++ disable the driver. */
++ if (kcs_addr < 0)
++ return -ENODEV;
++
++ new_kcs = kmalloc(kcs_size(), GFP_KERNEL);
++ if (!new_kcs) {
++ printk(KERN_ERR "Unable to initialize KCS, out of memory\n");
++ return -ENOMEM;
++ }
++
++ /* So we know not to free it unless we have allocated one. */
++ new_kcs->kcs_sm = NULL;
++
++ if (kcs_addr == 0) {
++ kcs_addr = DEFAULT_IO_ADDR;
++ }
++
++ new_kcs->addr = kcs_addr;
++
++ if (request_region(kcs_addr, 2, DEVICE_NAME) == NULL) {
++ kfree(new_kcs);
++ printk(KERN_ERR "ipmi_kcs: Unable to get IO at 0x%4.4x\n",
++ kcs_addr);
++ return -EIO;
++ }
++
++ new_kcs->kcs_sm = kmalloc(kcs_size(), GFP_KERNEL);
++ if (!new_kcs->kcs_sm) {
++ printk(KERN_ERR "Unable to initialize KCS, out of memory\n");
++ rv = -ENOMEM;
++ goto out_err;
++ }
++ init_kcs_data(new_kcs->kcs_sm, kcs_addr);
++ spin_lock_init(&(new_kcs->kcs_lock));
++
++ rv = ipmi_kcs_detect_hardware(kcs_addr, new_kcs->kcs_sm);
++ if (rv) {
++ printk(KERN_ERR "ipmi_kcs_intf: Could not detect KCS"
++ " interface at 0x%4.4x\n", kcs_addr);
++ rv = -ENODEV;
++ goto out_err;
++ }
++
++ if (irq != 0) {
++ rv = request_irq(irq,
++ kcs_irq_handler,
++ SA_INTERRUPT,
++ DEVICE_NAME,
++ new_kcs);
++ if (rv) {
++ printk(KERN_WARNING
++ "%s: Unable to claim interrupt %d,"
++ " running polled\n",
++ DEVICE_NAME, irq);
++ irq = 0;
++ }
++ }
++ new_kcs->irq = irq;
++
++ INIT_LIST_HEAD(&(new_kcs->xmit_msgs));
++ INIT_LIST_HEAD(&(new_kcs->hp_xmit_msgs));
++ new_kcs->curr_msg = NULL;
++ new_kcs->req_events = 0;
++ new_kcs->run_to_completion = 0;
++
++ start_clear_flags(new_kcs);
++
++ if (irq) {
++ new_kcs->kcs_state = KCS_CLEARING_FLAGS_THEN_SET_IRQ;
++
++ printk(KERN_INFO "Initializing KCS driver at 0x%x, irq %d\n",
++ kcs_addr, irq);
++
++ } else {
++ printk(KERN_INFO "Initializing KCS driver at 0x%x, no irq\n",
++ kcs_addr);
++ }
++
++ rv = ipmi_register_smi(&handlers,
++ new_kcs,
++ ipmi_version_major,
++ ipmi_version_minor,
++ &(new_kcs->intf));
++ if (rv) {
++ free_irq(irq, new_kcs);
++ printk(KERN_ERR "Unable to register IPMI KCS device: %d\n",
++ rv);
++ goto out_err;
++ }
++
++ new_kcs->interrupt_disabled = 0;
++ new_kcs->timer_stopped = 0;
++ new_kcs->stop_operation = 0;
++ new_kcs->last_timeout_jiffies = jiffies;
++
++ init_timer(&(new_kcs->kcs_timer));
++ new_kcs->kcs_timer.data = (long) new_kcs;
++ new_kcs->kcs_timer.function = kcs_timeout;
++ new_kcs->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES;
++ add_timer(&(new_kcs->kcs_timer));
++
++ *kcs = new_kcs;
++
++ return 0;
++
++ out_err:
++ release_region (kcs_addr, 2);
++ if (new_kcs->kcs_sm)
++ kfree(new_kcs->kcs_sm);
++ kfree(new_kcs);
++ return rv;
++}
++
++static __init int init_ipmi_kcs(void)
++{
++ int rv;
++ int pos;
++ int i;
++
++ if (initialized)
++ return 0;
++ initialized = 1;
++
++ pos = 0;
++ for (i=0; i<MAX_KCS_DRIVERS; i++) {
++ rv = init_one_kcs(kcs_addrs[i], kcs_irqs[i], &(kcs_info[pos]));
++ if (rv == 0) {
++ pos++;
++ }
++ }
++
++ if (kcs_info[0] == NULL) {
++ printk("ipmi_kcs_intf: Unable to find any KCS interfaces\n");
++ return -ENODEV;
++ } else
++ return 0;
++}
++
++#ifdef MODULE
++void __exit cleanup_one_kcs(struct kcs_info *to_clean)
++{
++ int rv;
++
++ if (! to_clean)
++ return;
++
++ if (to_clean->irq != 0)
++ free_irq(to_clean->irq, to_clean);
++
++ release_region (to_clean->addr, 2);
++
++ /* Tell the timer to stop, then wait for it to stop. This avoids
++ problems with race conditions removing the timer here. */
++ to_clean->stop_operation = 1;
++ while (!to_clean->timer_stopped) {
++ schedule_timeout(1);
++ }
++
++ rv = ipmi_unregister_smi(to_clean->intf);
++ if (rv) {
++ printk(KERN_ERR "Unable to unregister IPMI KCS device: %d\n",
++ rv);
++ }
++
++ initialized = 0;
++
++ kfree(to_clean->kcs_sm);
++ kfree(to_clean);
++}
++
++static __exit void cleanup_ipmi_kcs(void)
++{
++ int i;
++
++ if (!initialized)
++ return;
++
++ for (i=0; i<MAX_KCS_DRIVERS; i++) {
++ cleanup_one_kcs(kcs_info[i]);
++ }
++}
++module_exit(cleanup_ipmi_kcs);
++#else
++static int __init ipmi_kcs_setup(char *str)
++{
++ int val, rv = 2, pos;
++ char *s;
++
++
++ pos = 0;
++ while ((pos < 4) && (rv == 2)) {
++ rv = get_option(&str, &val);
++ if (rv == 0) {
++ s = strsep(&str, ",");
++ if (strcmp(s, "off") == 0) {
++ kcs_addrs[pos] = -1;
++ goto got_addr;
++ } else
++ break;
++ } else {
++ kcs_addrs[pos] = val;
++ if (rv == 2) {
++ got_addr:
++ rv = get_option(&str, &val);
++ if (rv)
++ kcs_irqs[pos] = val;
++ }
++ }
++ pos++;
++ }
++
++ return 1;
++}
++__setup("ipmi_kcs=", ipmi_kcs_setup);
++#endif
++
++module_init(init_ipmi_kcs);
++MODULE_LICENSE("GPL");
+diff -urN linux.orig/drivers/char/ipmi/ipmi_kcs_sm.c linux/drivers/char/ipmi/ipmi_kcs_sm.c
+--- linux.orig/drivers/char/ipmi/ipmi_kcs_sm.c Wed Dec 31 18:00:00 1969
++++ linux/drivers/char/ipmi/ipmi_kcs_sm.c Mon Oct 28 16:38:23 2002
+@@ -0,0 +1,449 @@
++/*
++ * ipmi_kcs_sm.c
++ *
++ * State machine for handling IPMI KCS interfaces.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++/*
++ * This state machine is taken from the state machine in the IPMI spec,
++ * pretty much verbatim. If you have questions about the states, see
++ * that document.
++ */
++
++#include <asm/io.h>
++
++#include "ipmi_kcs_sm.h"
++
++/* Set this if you want a printout of why the state machine was hosed
++ when it gets hosed. */
++#define DEBUG_HOSED_REASON
++
++/* Print the state machine state on entry every time. */
++#undef DEBUG_STATE
++
++/* The states the KCS driver may be in. */
++enum kcs_states {
++ KCS_IDLE, /* The KCS interface is currently
++ doing nothing. */
++ KCS_START_OP, /* We are starting an operation. The
++ data is in the output buffer, but
++ nothing has been done to the
++ interface yet. This was added to
++ the state machine in the spec to
++ wait for the initial IBF. */
++ KCS_WAIT_WRITE_START, /* We have written a write cmd to the
++ interface. */
++ KCS_WAIT_WRITE, /* We are writing bytes to the
++ interface. */
++ KCS_WAIT_WRITE_END, /* We have written the write end cmd
++ to the interface, and still need to
++ write the last byte. */
++ KCS_WAIT_READ, /* We are waiting to read data from
++ the interface. */
++ KCS_ERROR0, /* State to transition to the error
++ handler, this was added to the
++ state machine in the spec to be
++ sure IBF was there. */
++ KCS_ERROR1, /* First stage error handler, wait for
++ the interface to respond. */
++ KCS_ERROR2, /* The abort cmd has been written,
++ wait for the interface to
++ respond. */
++ KCS_ERROR3, /* We wrote some data to the
++ interface, wait for it to switch to
++ read mode. */
++ KCS_HOSED /* The hardware failed to follow the
++ state machine. */
++};
++
++#define MAX_KCS_READ_SIZE 80
++#define MAX_KCS_WRITE_SIZE 80
++
++/* Timeouts in microseconds. */
++#define IBF_RETRY_TIMEOUT 1000000
++#define OBF_RETRY_TIMEOUT 1000000
++#define MAX_ERROR_RETRIES 10
++
++#define IPMI_ERR_MSG_TRUNCATED 0xc6
++
++struct kcs_data
++{
++ enum kcs_states state;
++ unsigned int port;
++ unsigned char write_data[MAX_KCS_WRITE_SIZE];
++ int write_pos;
++ int write_count;
++ int orig_write_count;
++ unsigned char read_data[MAX_KCS_READ_SIZE];
++ int read_pos;
++ int truncated;
++
++ unsigned int error_retries;
++ long ibf_timeout;
++ long obf_timeout;
++};
++
++void init_kcs_data(struct kcs_data *kcs, unsigned int port)
++{
++ kcs->state = KCS_IDLE;
++ kcs->port = port;
++ kcs->write_pos = 0;
++ kcs->write_count = 0;
++ kcs->orig_write_count = 0;
++ kcs->read_pos = 0;
++ kcs->error_retries = 0;
++ kcs->truncated = 0;
++ kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
++ kcs->obf_timeout = OBF_RETRY_TIMEOUT;
++}
++
++static inline unsigned char read_status(struct kcs_data *kcs)
++{
++ return inb(kcs->port + 1);
++}
++
++static inline unsigned char read_data(struct kcs_data *kcs)
++{
++ return inb(kcs->port + 0);
++}
++
++static inline void write_cmd(struct kcs_data *kcs, unsigned char data)
++{
++ outb(data, kcs->port + 1);
++}
++
++static inline void write_data(struct kcs_data *kcs, unsigned char data)
++{
++ outb(data, kcs->port + 0);
++}
++
++/* Control codes. */
++#define KCS_GET_STATUS_ABORT 0x60
++#define KCS_WRITE_START 0x61
++#define KCS_WRITE_END 0x62
++#define KCS_READ_BYTE 0x68
++
++/* Status bits. */
++#define GET_STATUS_STATE(status) (((status) >> 6) & 0x03)
++#define KCS_IDLE_STATE 0
++#define KCS_READ_STATE 1
++#define KCS_WRITE_STATE 2
++#define KCS_ERROR_STATE 3
++#define GET_STATUS_ATN(status) ((status) & 0x04)
++#define GET_STATUS_IBF(status) ((status) & 0x02)
++#define GET_STATUS_OBF(status) ((status) & 0x01)
++
++
++static inline void write_next_byte(struct kcs_data *kcs)
++{
++ write_data(kcs, kcs->write_data[kcs->write_pos]);
++ (kcs->write_pos)++;
++ (kcs->write_count)--;
++}
++
++static inline void start_error_recovery(struct kcs_data *kcs, char *reason)
++{
++ (kcs->error_retries)++;
++ if (kcs->error_retries > MAX_ERROR_RETRIES) {
++#ifdef DEBUG_HOSED_REASON
++ printk("ipmi_kcs_sm: kcs hosed: %s\n", reason);
++#endif
++ kcs->state = KCS_HOSED;
++ } else {
++ kcs->state = KCS_ERROR0;
++ }
++}
++
++static inline void read_next_byte(struct kcs_data *kcs)
++{
++ if (kcs->read_pos >= MAX_KCS_READ_SIZE) {
++ /* Throw the data away and mark it truncated. */
++ read_data(kcs);
++ kcs->truncated = 1;
++ } else {
++ kcs->read_data[kcs->read_pos] = read_data(kcs);
++ (kcs->read_pos)++;
++ }
++ write_data(kcs, KCS_READ_BYTE);
++}
++
++static inline int check_ibf(struct kcs_data *kcs,
++ unsigned char status,
++ long time)
++{
++ if (GET_STATUS_IBF(status)) {
++ kcs->ibf_timeout -= time;
++ if (kcs->ibf_timeout < 0) {
++ start_error_recovery(kcs, "IBF not ready in time");
++ return 1;
++ }
++ return 0;
++ }
++ kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
++ return 1;
++}
++
++static inline int check_obf(struct kcs_data *kcs,
++ unsigned char status,
++ long time)
++{
++ if (! GET_STATUS_OBF(status)) {
++ kcs->obf_timeout -= time;
++ if (kcs->obf_timeout < 0) {
++ start_error_recovery(kcs, "OBF not ready in time");
++ return 1;
++ }
++ return 0;
++ }
++ kcs->obf_timeout = OBF_RETRY_TIMEOUT;
++ return 1;
++}
++
++static void clear_obf(struct kcs_data *kcs, unsigned char status)
++{
++ if (GET_STATUS_OBF(status))
++ read_data(kcs);
++}
++
++static void restart_kcs_transaction(struct kcs_data *kcs)
++{
++ kcs->write_count = kcs->orig_write_count;
++ kcs->write_pos = 0;
++ kcs->read_pos = 0;
++ kcs->state = KCS_WAIT_WRITE_START;
++ kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
++ kcs->obf_timeout = OBF_RETRY_TIMEOUT;
++ write_cmd(kcs, KCS_WRITE_START);
++}
++
++int start_kcs_transaction(struct kcs_data *kcs, char *data, unsigned int size)
++{
++ if ((size < 2) || (size > MAX_KCS_WRITE_SIZE)) {
++ return -1;
++ }
++
++ if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED)) {
++ return -2;
++ }
++
++ kcs->error_retries = 0;
++ memcpy(kcs->write_data, data, size);
++ kcs->write_count = size;
++ kcs->orig_write_count = size;
++ kcs->write_pos = 0;
++ kcs->read_pos = 0;
++ kcs->state = KCS_START_OP;
++ kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
++ kcs->obf_timeout = OBF_RETRY_TIMEOUT;
++ return 0;
++}
++
++int kcs_get_result(struct kcs_data *kcs, unsigned char *data, int length)
++{
++ if (length < kcs->read_pos) {
++ kcs->read_pos = length;
++ kcs->truncated = 1;
++ }
++
++ memcpy(data, kcs->read_data, kcs->read_pos);
++
++ if (kcs->truncated) {
++ /* Report a truncated error. We might overwrite
++ another error, but that's too bad, the user needs
++ to know it was truncated. */
++ data[2] = IPMI_ERR_MSG_TRUNCATED;
++ kcs->truncated = 0;
++ }
++
++ return kcs->read_pos;
++}
++
++/* This implements the state machine defined in the IPMI manual, see
++ that for details on how this works. */
++enum kcs_result kcs_event(struct kcs_data *kcs, long time)
++{
++ unsigned char status;
++ unsigned char state;
++
++ status = read_status(kcs);
++
++#ifdef DEBUG_STATE
++ printk(" State = %d, %x\n", kcs->state, status);
++#endif
++ /* All states wait for ibf, so just do it here. */
++ if (!check_ibf(kcs, status, time))
++ return KCS_CALL_WITH_DELAY;
++
++ /* Just about everything looks at the KCS state, so grab that, too. */
++ state = GET_STATUS_STATE(status);
++
++ switch (kcs->state) {
++ case KCS_IDLE:
++ if (GET_STATUS_ATN(status))
++ return KCS_ATTN;
++ else
++ return KCS_SM_IDLE;
++
++ case KCS_START_OP:
++ if (state != KCS_IDLE) {
++ start_error_recovery(kcs,
++ "State machine not idle at start");
++ break;
++ }
++
++ clear_obf(kcs, status);
++ write_cmd(kcs, KCS_WRITE_START);
++ kcs->state = KCS_WAIT_WRITE_START;
++ break;
++
++ case KCS_WAIT_WRITE_START:
++ if (state != KCS_WRITE_STATE) {
++ start_error_recovery(
++ kcs,
++ "Not in write state at write start");
++ break;
++ }
++ read_data(kcs);
++ if (kcs->write_count == 1) {
++ write_cmd(kcs, KCS_WRITE_END);
++ kcs->state = KCS_WAIT_WRITE_END;
++ } else {
++ write_next_byte(kcs);
++ kcs->state = KCS_WAIT_WRITE;
++ }
++ break;
++
++ case KCS_WAIT_WRITE:
++ if (state != KCS_WRITE_STATE) {
++ start_error_recovery(kcs,
++ "Not in write state for write");
++ break;
++ }
++ clear_obf(kcs, status);
++ if (kcs->write_count == 1) {
++ write_cmd(kcs, KCS_WRITE_END);
++ kcs->state = KCS_WAIT_WRITE_END;
++ } else {
++ write_next_byte(kcs);
++ }
++ break;
++
++ case KCS_WAIT_WRITE_END:
++ if (state != KCS_WRITE_STATE) {
++ start_error_recovery(kcs,
++ "Not in write state for write end");
++ break;
++ }
++ clear_obf(kcs, status);
++ write_next_byte(kcs);
++ kcs->state = KCS_WAIT_READ;
++ break;
++
++ case KCS_WAIT_READ:
++ if ((state != KCS_READ_STATE) && (state != KCS_IDLE_STATE)) {
++ start_error_recovery(
++ kcs,
++ "Not in read or idle in read state");
++ break;
++ }
++ if (! check_obf(kcs, status, time))
++ return KCS_CALL_WITH_DELAY;
++
++ if (state == KCS_READ_STATE) {
++ read_next_byte(kcs);
++ } else {
++ read_data(kcs);
++ kcs->orig_write_count = 0;
++ kcs->state = KCS_IDLE;
++ return KCS_TRANSACTION_COMPLETE;
++ }
++ break;
++
++ case KCS_ERROR0:
++ clear_obf(kcs, status);
++ write_cmd(kcs, KCS_GET_STATUS_ABORT);
++ kcs->state = KCS_ERROR1;
++ break;
++
++ case KCS_ERROR1:
++ clear_obf(kcs, status);
++ write_data(kcs, 0);
++ kcs->state = KCS_ERROR2;
++ break;
++
++ case KCS_ERROR2:
++ if (state != KCS_READ_STATE) {
++ start_error_recovery(kcs,
++ "Not in read state for error2");
++ break;
++ }
++ if (! check_obf(kcs, status, time))
++ return KCS_CALL_WITH_DELAY;
++
++ clear_obf(kcs, status);
++ write_data(kcs, KCS_READ_BYTE);
++ kcs->state = KCS_ERROR3;
++ break;
++
++ case KCS_ERROR3:
++ if (state != KCS_IDLE_STATE) {
++ start_error_recovery(kcs,
++ "Not in idle state for error3");
++ break;
++ }
++
++ if (! check_obf(kcs, status, time))
++ return KCS_CALL_WITH_DELAY;
++
++ clear_obf(kcs, status);
++ if (kcs->orig_write_count) {
++ restart_kcs_transaction(kcs);
++ } else {
++ kcs->state = KCS_IDLE;
++ return KCS_TRANSACTION_COMPLETE;
++ }
++ break;
++
++ case KCS_HOSED:
++ return KCS_SM_HOSED;
++ }
++
++ if (kcs->state == KCS_HOSED) {
++ init_kcs_data(kcs, kcs->port);
++ return KCS_SM_HOSED;
++ }
++
++ return KCS_CALL_WITHOUT_DELAY;
++}
++
++int kcs_size(void)
++{
++ return sizeof(struct kcs_data);
++}
+diff -urN linux.orig/drivers/char/ipmi/ipmi_kcs_sm.h linux/drivers/char/ipmi/ipmi_kcs_sm.h
+--- linux.orig/drivers/char/ipmi/ipmi_kcs_sm.h Wed Dec 31 18:00:00 1969
++++ linux/drivers/char/ipmi/ipmi_kcs_sm.h Sun Oct 13 16:25:50 2002
+@@ -0,0 +1,69 @@
++/*
++ * ipmi_kcs_sm.h
++ *
++ * State machine for handling IPMI KCS interfaces.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++struct kcs_data;
++
++void init_kcs_data(struct kcs_data *kcs,
++ unsigned int port);
++
++/* Start a new transaction in the state machine. This will return -2
++ if the state machine is not idle, -1 if the size is invalid (to
++ large or too small), or 0 if the transaction is successfully
++ completed. */
++int start_kcs_transaction(struct kcs_data *kcs, char *data, unsigned int size);
++
++/* Return the results after the transaction. This will return -1 if
++ the buffer is too small, zero if no transaction is present, or the
++ actual length of the result data. */
++int kcs_get_result(struct kcs_data *kcs, unsigned char *data, int length);
++
++enum kcs_result
++{
++ KCS_CALL_WITHOUT_DELAY, /* Call the driver again immediately */
++ KCS_CALL_WITH_DELAY, /* Delay some before calling again. */
++ KCS_TRANSACTION_COMPLETE, /* A transaction is finished. */
++ KCS_SM_IDLE, /* The SM is in idle state. */
++ KCS_SM_HOSED, /* The hardware violated the state machine. */
++ KCS_ATTN /* The hardware is asserting attn and the
++ state machine is idle. */
++};
++
++/* Call this periodically (for a polled interface) or upon receiving
++ an interrupt (for a interrupt-driven interface). If interrupt
++ driven, you should probably poll this periodically when not in idle
++ state. This should be called with the time that passed since the
++ last call, if it is significant. Time is in microseconds. */
++enum kcs_result kcs_event(struct kcs_data *kcs, long time);
++
++/* Return the size of the KCS structure in bytes. */
++int kcs_size(void);
+diff -urN linux.orig/drivers/char/ipmi/ipmi_msghandler.c linux/drivers/char/ipmi/ipmi_msghandler.c
+--- linux.orig/drivers/char/ipmi/ipmi_msghandler.c Wed Dec 31 18:00:00 1969
++++ linux/drivers/char/ipmi/ipmi_msghandler.c Wed Oct 30 13:51:55 2002
+@@ -0,0 +1,1797 @@
++/*
++ * ipmi_msghandler.c
++ *
++ * Incoming and outgoing message routing for an IPMI interface.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <asm/system.h>
++#include <linux/sched.h>
++#include <linux/poll.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/ipmi.h>
++#include <linux/ipmi_smi.h>
++#include <linux/notifier.h>
++#include <linux/init.h>
++
++struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
++static int ipmi_init_msghandler(void);
++
++static int initialized = 0;
++
++#define MAX_EVENTS_IN_QUEUE 25
++
++struct ipmi_user
++{
++ struct list_head link;
++
++ /* The upper layer that handles receive messages. */
++ struct ipmi_user_hndl *handler;
++ void *handler_data;
++
++ /* The interface this user is bound to. */
++ ipmi_smi_t intf;
++
++ /* Does this interface receive IPMI events? */
++ int gets_events;
++};
++
++struct cmd_rcvr
++{
++ struct list_head link;
++
++ ipmi_user_t user;
++ unsigned char netfn;
++ unsigned char cmd;
++};
++
++#define IPMI_IPMB_NUM_SEQ 64
++struct ipmi_smi
++{
++ /* The list of upper layers that are using me. We read-lock
++ this when delivering messages to the upper layer to keep
++ the user from going away while we are processing the
++ message. This means that you cannot add or delete a user
++ from the receive callback. */
++ rwlock_t users_lock;
++ struct list_head users;
++
++ /* The IPMI version of the BMC on the other end. */
++ unsigned char version_major;
++ unsigned char version_minor;
++
++ /* This is the lower-layer's sender routine. */
++ struct ipmi_smi_handlers *handlers;
++ void *send_info;
++
++ /* A table of sequence numbers for this interface. We use the
++ sequence numbers for IPMB messages that go out of the
++ interface to match them up with their responses. A routine
++ is called periodically to time the items in this list. */
++ spinlock_t seq_lock;
++ struct {
++ unsigned long timeout;
++ int inuse;
++ struct ipmi_recv_msg *recv_msg;
++ } seq_table[IPMI_IPMB_NUM_SEQ];
++ int curr_seq;
++
++ /* Messages that were delayed for some reason (out of memory,
++ for instance), will go in here to be processed later in a
++ periodic timer interrupt. */
++ spinlock_t waiting_msgs_lock;
++ struct list_head waiting_msgs;
++
++ /* The list of command receivers that are registered for commands
++ on this interface. */
++ rwlock_t cmd_rcvr_lock;
++ struct list_head cmd_rcvrs;
++
++ /* Events that were queues because no one was there to receive
++ them. */
++ spinlock_t events_lock; /* For dealing with event stuff. */
++ struct list_head waiting_events;
++ unsigned int waiting_events_count; /* How many events in queue? */
++
++ /* This will be non-null if someone registers to receive all
++ IPMI commands (this is for interface emulation). There
++ may not be any things in the cmd_rcvrs list above when
++ this is registered. */
++ ipmi_user_t all_cmd_rcvr;
++
++ /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR,
++ but may be changed by the user. */
++ unsigned char my_address;
++
++ /* My LUN. This should generally stay the SMS LUN, but just in
++ case... */
++ unsigned char my_lun;
++};
++
++int
++ipmi_register_all_cmd_rcvr(ipmi_user_t user)
++{
++ int flags;
++ int rv = -EBUSY;
++
++ write_lock_irqsave(&(user->intf->users_lock), flags);
++ write_lock(&(user->intf->cmd_rcvr_lock));
++ if ((user->intf->all_cmd_rcvr == NULL)
++ && (list_empty(&(user->intf->cmd_rcvrs))))
++ {
++ user->intf->all_cmd_rcvr = user;
++ rv = 0;
++ }
++ write_unlock(&(user->intf->cmd_rcvr_lock));
++ write_unlock_irqrestore(&(user->intf->users_lock), flags);
++ return rv;
++}
++
++int
++ipmi_unregister_all_cmd_rcvr(ipmi_user_t user)
++{
++ int flags;
++ int rv = -EINVAL;
++
++ write_lock_irqsave(&(user->intf->users_lock), flags);
++ write_lock(&(user->intf->cmd_rcvr_lock));
++ if (user->intf->all_cmd_rcvr == user)
++ {
++ user->intf->all_cmd_rcvr = NULL;
++ rv = 0;
++ }
++ write_unlock(&(user->intf->cmd_rcvr_lock));
++ write_unlock_irqrestore(&(user->intf->users_lock), flags);
++ return rv;
++}
++
++
++#define MAX_IPMI_INTERFACES 4
++static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES];
++/* The locking for these for a write lock is done by two locks, first
++ the "outside" lock then the normal lock. This way, the interfaces
++ lock can be converted to a read lock without allowing a new write
++ locker to come in. Note that at interrupt level, this can only be
++ claimed read, so there is no reason for read lock to save
++ interrupts. Write locks must still save interrupts because they
++ can block an interrupt. */
++static rwlock_t interfaces_lock = RW_LOCK_UNLOCKED;
++static spinlock_t interfaces_outside_lock = SPIN_LOCK_UNLOCKED;
++
++static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers);
++static rwlock_t smi_watcher_lock = RW_LOCK_UNLOCKED;
++
++int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
++{
++ int i;
++
++ read_lock(&interfaces_lock);
++ write_lock(&smi_watcher_lock);
++ list_add(&(watcher->link), &smi_watchers);
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ if (ipmi_interfaces[i] != NULL) {
++ watcher->new_smi(i);
++ }
++ }
++ write_unlock(&smi_watcher_lock);
++ read_unlock(&interfaces_lock);
++ return 0;
++}
++
++int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher)
++{
++ write_lock(&smi_watcher_lock);
++ list_del(&(watcher->link));
++ write_unlock(&smi_watcher_lock);
++ return 0;
++}
++
++int
++ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2)
++{
++ if (addr1->addr_type != addr2->addr_type)
++ return 0;
++
++ if (addr1->channel != addr2->channel)
++ return 0;
++
++ if (addr1->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {
++ struct ipmi_system_interface_addr *smi_addr1
++ = (struct ipmi_system_interface_addr *) addr1;
++ struct ipmi_system_interface_addr *smi_addr2
++ = (struct ipmi_system_interface_addr *) addr2;
++ return (smi_addr1->lun == smi_addr2->lun);
++ }
++
++ if ((addr1->addr_type == IPMI_IPMB_ADDR_TYPE)
++ || (addr1->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
++ {
++ struct ipmi_ipmb_addr *ipmb_addr1
++ = (struct ipmi_ipmb_addr *) addr1;
++ struct ipmi_ipmb_addr *ipmb_addr2
++ = (struct ipmi_ipmb_addr *) addr2;
++
++ return ((ipmb_addr1->slave_addr == ipmb_addr2->slave_addr)
++ && (ipmb_addr1->lun == ipmb_addr2->lun));
++ }
++
++ return 1;
++}
++
++int ipmi_validate_addr(struct ipmi_addr *addr, int len)
++{
++ if (len < sizeof(struct ipmi_system_interface_addr)) {
++ return -EINVAL;
++ }
++
++ if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {
++ if (addr->channel != IPMI_BMC_CHANNEL)
++ return -EINVAL;
++ return 0;
++ }
++
++ if ((addr->channel == IPMI_BMC_CHANNEL)
++ || (addr->channel >= IPMI_NUM_CHANNELS)
++ || (addr->channel < 0))
++ return -EINVAL;
++
++ if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)
++ || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
++ {
++ if (len < sizeof(struct ipmi_ipmb_addr)) {
++ return -EINVAL;
++ }
++ return 0;
++ }
++
++ return -EINVAL;
++}
++
++unsigned int ipmi_addr_length(int addr_type)
++{
++ if (addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
++ return sizeof(struct ipmi_system_interface_addr);
++
++ if ((addr_type == IPMI_IPMB_ADDR_TYPE)
++ || (addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
++ {
++ return sizeof(struct ipmi_ipmb_addr);
++ }
++
++ return 0;
++}
++
++static void deliver_response(struct ipmi_recv_msg *msg)
++{
++ msg->user->handler->ipmi_recv_hndl(msg, msg->user->handler_data);
++}
++
++/* Find the next sequence number not being used and add the given
++ message with the given timeout to the sequence table. */
++static int intf_next_seq(ipmi_smi_t intf,
++ struct ipmi_recv_msg *recv_msg,
++ unsigned long timeout,
++ unsigned char *seq)
++{
++ int rv = 0;
++ unsigned long flags;
++ unsigned int i;
++
++ spin_lock_irqsave(&(intf->seq_lock), flags);
++ for (i=intf->curr_seq;
++ i!=(intf->curr_seq-1);
++ i=(i+1)%IPMI_IPMB_NUM_SEQ)
++ {
++ if (! intf->seq_table[i].inuse)
++ break;
++ }
++
++ if (! intf->seq_table[i].inuse) {
++ intf->seq_table[i].recv_msg = recv_msg;
++ intf->seq_table[i].timeout = timeout;
++ intf->seq_table[i].inuse = 1;
++ *seq = i;
++ intf->curr_seq = (i+1)%IPMI_IPMB_NUM_SEQ;
++ } else {
++ rv = -EAGAIN;
++ }
++
++ spin_unlock_irqrestore(&(intf->seq_lock), flags);
++
++ return rv;
++}
++
++/* Return the receive message for the given sequence number and
++ release the sequence number so it can be reused. Some other data
++ is passed in to be sure the message matches up correctly (to help
++ guard against message coming in after their timeout and the
++ sequence number being reused). */
++static int intf_find_seq(ipmi_smi_t intf,
++ unsigned char seq,
++ short channel,
++ unsigned char cmd,
++ unsigned char netfn,
++ struct ipmi_addr *addr,
++ struct ipmi_recv_msg **recv_msg)
++{
++ int rv = -ENODEV;
++ unsigned long flags;
++
++ if (seq >= IPMI_IPMB_NUM_SEQ)
++ return -EINVAL;
++
++ spin_lock_irqsave(&(intf->seq_lock), flags);
++ if (intf->seq_table[seq].inuse) {
++ struct ipmi_recv_msg *msg = intf->seq_table[seq].recv_msg;
++
++ if ((msg->addr.channel == channel)
++ && (msg->msg.cmd == cmd)
++ && (msg->msg.netfn == netfn)
++ && (ipmi_addr_equal(addr, &(msg->addr))))
++ {
++ *recv_msg = msg;
++ intf->seq_table[seq].inuse = 0;
++ rv = 0;
++ }
++ }
++ spin_unlock_irqrestore(&(intf->seq_lock), flags);
++
++ return rv;
++}
++
++
++int ipmi_create_user(unsigned int if_num,
++ struct ipmi_user_hndl *handler,
++ void *handler_data,
++ ipmi_user_t *user)
++{
++ unsigned long flags;
++ ipmi_user_t new_user;
++ int rv = 0;
++
++ if (handler == NULL)
++ return -EINVAL;
++
++ MOD_INC_USE_COUNT;
++
++ /* Make sure the driver is actually initialized, this handles
++ problems with initialization order. */
++ if (!initialized) {
++ rv = ipmi_init_msghandler();
++ if (rv) {
++ MOD_DEC_USE_COUNT;
++ return rv;
++ }
++ /* The init code doesn't return an error if it was turned
++ off, but it won't initialize. Check that. */
++ if (!initialized) {
++ MOD_DEC_USE_COUNT;
++ return -ENODEV;
++ }
++ }
++
++ new_user = kmalloc(sizeof(*new_user), GFP_KERNEL);
++ if (! new_user) {
++ MOD_DEC_USE_COUNT;
++ return -ENOMEM;
++ }
++
++ read_lock(&interfaces_lock);
++ if ((if_num > MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)
++ {
++ rv = -EINVAL;
++ goto out_unlock;
++ }
++
++ new_user->handler = handler;
++ new_user->handler_data = handler_data;
++ new_user->intf = ipmi_interfaces[if_num];
++ new_user->gets_events = 0;
++
++ write_lock_irqsave(&(new_user->intf->users_lock), flags);
++ list_add_tail(&(new_user->link), &(new_user->intf->users));
++ write_unlock_irqrestore(&(new_user->intf->users_lock), flags);
++
++ out_unlock:
++ if (rv) {
++ MOD_DEC_USE_COUNT;
++ kfree(new_user);
++ } else {
++ new_user->intf->handlers->new_user(new_user->intf->send_info);
++ *user = new_user;
++ }
++
++ read_unlock(&interfaces_lock);
++ return rv;
++}
++
++static int ipmi_destroy_user_nolock(ipmi_user_t user)
++{
++ int rv = -ENODEV;
++ ipmi_user_t t_user;
++ struct list_head *entry, *entry2;
++ int i;
++ unsigned long flags;
++
++ /* Find the user and delete them from the list. */
++ list_for_each(entry, &(user->intf->users)) {
++ t_user = list_entry(entry, struct ipmi_user, link);
++ if (t_user == user) {
++ list_del(entry);
++ rv = 0;
++ break;
++ }
++ }
++
++ if (rv) {
++ goto out_unlock;
++ }
++
++ /* Remove the user from the interfaces sequence table. */
++ spin_lock_irqsave(&(user->intf->seq_lock), flags);
++ for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) {
++ if (user->intf->seq_table[i].inuse
++ && (user->intf->seq_table[i].recv_msg->user == user))
++ {
++ user->intf->seq_table[i].inuse = 0;
++ }
++ }
++ spin_unlock_irqrestore(&(user->intf->seq_lock), flags);
++
++ /* Remove the user from the command receiver's table. */
++ write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
++ list_for_each_safe(entry, entry2, &(user->intf->cmd_rcvrs)) {
++ struct cmd_rcvr *rcvr;
++ rcvr = list_entry(entry, struct cmd_rcvr, link);
++ if (rcvr->user == user) {
++ list_del(entry);
++ kfree(rcvr);
++ }
++ }
++ write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
++
++ kfree(user);
++
++ out_unlock:
++
++ return rv;
++}
++
++int ipmi_destroy_user(ipmi_user_t user)
++{
++ int rv;
++ ipmi_smi_t intf = user->intf;
++ unsigned long flags;
++
++ read_lock(&interfaces_lock);
++ write_lock_irqsave(&(intf->users_lock), flags);
++ rv = ipmi_destroy_user_nolock(user);
++ if (!rv) {
++ intf->handlers->user_left(intf->send_info);
++ MOD_DEC_USE_COUNT;
++ }
++
++ write_unlock_irqrestore(&(intf->users_lock), flags);
++ read_unlock(&interfaces_lock);
++ return rv;
++}
++
++void ipmi_get_version(ipmi_user_t user,
++ unsigned char *major,
++ unsigned char *minor)
++{
++ *major = user->intf->version_major;
++ *minor = user->intf->version_minor;
++}
++
++void ipmi_set_my_address(ipmi_user_t user,
++ unsigned char address)
++{
++ user->intf->my_address = address;
++}
++
++unsigned char ipmi_get_my_address(ipmi_user_t user)
++{
++ return user->intf->my_address;
++}
++
++void ipmi_set_my_LUN(ipmi_user_t user,
++ unsigned char LUN)
++{
++ user->intf->my_lun = LUN & 0x3;
++}
++
++unsigned char ipmi_get_my_LUN(ipmi_user_t user)
++{
++ return user->intf->my_lun;
++}
++
++int ipmi_set_gets_events(ipmi_user_t user, int val)
++{
++ unsigned long flags;
++ struct list_head *e, *e2;
++ struct ipmi_recv_msg *msg;
++
++ read_lock(&(user->intf->users_lock));
++ spin_lock_irqsave(&(user->intf->events_lock), flags);
++ user->gets_events = val;
++
++ if (val) {
++ /* Deliver any queued events. */
++ list_for_each_safe(e, e2, &(user->intf->waiting_events)) {
++ msg = list_entry(e, struct ipmi_recv_msg, link);
++ list_del(e);
++ msg->user = user;
++ deliver_response(msg);
++ }
++ }
++
++ spin_unlock_irqrestore(&(user->intf->events_lock), flags);
++ read_unlock(&(user->intf->users_lock));
++
++ return 0;
++}
++
++int ipmi_register_for_cmd(ipmi_user_t user,
++ unsigned char netfn,
++ unsigned char cmd)
++{
++ struct list_head *entry;
++ unsigned long flags;
++ struct cmd_rcvr *rcvr;
++ int rv = 0;
++
++
++ rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL);
++ if (! rcvr)
++ return -ENOMEM;
++
++ read_lock(&(user->intf->users_lock));
++ write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
++ if (user->intf->all_cmd_rcvr != NULL) {
++ rv = -EBUSY;
++ goto out_unlock;
++ }
++
++ /* Make sure the command/netfn is not already registered. */
++ list_for_each(entry, &(user->intf->cmd_rcvrs)) {
++ rcvr = list_entry(entry, struct cmd_rcvr, link);
++ if ((rcvr->netfn == netfn) || (rcvr->cmd == cmd)) {
++ rv = -EBUSY;
++ break;
++ }
++ }
++
++ if (! rv) {
++ rcvr->cmd = cmd;
++ rcvr->netfn = netfn;
++ rcvr->user = user;
++ list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs));
++ }
++ out_unlock:
++ write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
++ read_unlock(&(user->intf->users_lock));
++
++ if (rv)
++ kfree(rcvr);
++
++ return rv;
++}
++
++int ipmi_unregister_for_cmd(ipmi_user_t user,
++ unsigned char netfn,
++ unsigned char cmd)
++{
++ struct list_head *entry;
++ unsigned long flags;
++ struct cmd_rcvr *rcvr;
++ int rv = -ENOENT;
++
++ read_lock(&(user->intf->users_lock));
++ write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
++ /* Make sure the command/netfn is not already registered. */
++ list_for_each(entry, &(user->intf->cmd_rcvrs)) {
++ rcvr = list_entry(entry, struct cmd_rcvr, link);
++ if ((rcvr->netfn == netfn) || (rcvr->cmd == cmd)) {
++ rv = 0;
++ list_del(entry);
++ kfree(rcvr);
++ break;
++ }
++ }
++ write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
++ read_unlock(&(user->intf->users_lock));
++
++ return rv;
++}
++
++static unsigned char
++ipmb_checksum(unsigned char *data, int size)
++{
++ unsigned char csum = 0;
++
++ for (; size > 0; size--, data++)
++ csum += *data;
++
++ return -csum;
++}
++
++/* Separate from ipmi_request so that the user does not have to be
++ supplied in certain circumstances (mainly at panic time). If
++ messages are supplied, they will be freed, even if an error
++ occurs. */
++static inline int i_ipmi_request(ipmi_user_t user,
++ ipmi_smi_t intf,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ void *supplied_smi,
++ struct ipmi_recv_msg *supplied_recv,
++ int priority,
++ unsigned char source_address,
++ unsigned char source_lun)
++{
++ int rv = 0;
++ struct ipmi_smi_msg *smi_msg;
++ struct ipmi_recv_msg *recv_msg;
++
++
++ if (supplied_recv) {
++ recv_msg = supplied_recv;
++ } else {
++ recv_msg = ipmi_alloc_recv_msg();
++ if (recv_msg == NULL) {
++ return -ENOMEM;
++ }
++ }
++
++ if (supplied_smi) {
++ smi_msg = (struct ipmi_smi_msg *) supplied_smi;
++ } else {
++ smi_msg = ipmi_alloc_smi_msg();
++ if (smi_msg == NULL) {
++ ipmi_free_recv_msg(recv_msg);
++ return -ENOMEM;
++ }
++ }
++
++ if (addr->channel > IPMI_NUM_CHANNELS) {
++ rv = -EINVAL;
++ goto out_err;
++ }
++
++ if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {
++ struct ipmi_system_interface_addr *smi_addr;
++
++ smi_addr = (struct ipmi_system_interface_addr *) addr;
++ if (smi_addr->lun > 3)
++ return -EINVAL;
++
++ if ((msg->netfn == IPMI_NETFN_APP_REQUEST)
++ && ((msg->cmd == IPMI_SEND_MSG_CMD)
++ || (msg->cmd == IPMI_GET_MSG_CMD)
++ || (msg->cmd == IPMI_READ_EVENT_MSG_BUFFER_CMD)))
++ {
++ /* We don't let the user do these, since we manage
++ the sequence numbers. */
++ rv = -EINVAL;
++ goto out_err;
++ }
++
++ if ((msg->data_len + 2) > IPMI_MAX_MSG_LENGTH) {
++ rv = -EMSGSIZE;
++ goto out_err;
++ }
++
++ recv_msg->user = user;
++ recv_msg->addr = *addr;
++ recv_msg->msgid = msgid;
++ recv_msg->msg = *msg;
++
++ smi_msg->data[0] = (msg->netfn << 2) | (smi_addr->lun & 0x3);
++ smi_msg->data[1] = msg->cmd;
++ smi_msg->msgid = msgid;
++ smi_msg->user_data = recv_msg;
++ if (msg->data_len > 0)
++ memcpy(&(smi_msg->data[2]), msg->data, msg->data_len);
++ smi_msg->data_size = msg->data_len + 2;
++ } else if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)
++ || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
++ {
++ struct ipmi_ipmb_addr *ipmb_addr;
++ unsigned char ipmb_seq;
++ int i;
++
++ if (addr == NULL) {
++ rv = -EINVAL;
++ goto out_err;
++ }
++
++ if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE) {
++ /* Broadcasts add a zero at the beginning of the
++ message, but otherwise is the same as an IPMB
++ address. */
++ smi_msg->data[3] = 0;
++ addr->addr_type = IPMI_IPMB_ADDR_TYPE;
++ i = 1;
++ } else {
++ i = 0;
++ }
++
++ /* 9 for the header and 1 for the checksum, plus
++ possibly one for the broadcast. */
++ if ((msg->data_len + 10 + i) > IPMI_MAX_MSG_LENGTH) {
++ rv = -EMSGSIZE;
++ goto out_err;
++ }
++
++ ipmb_addr = (struct ipmi_ipmb_addr *) addr;
++ if (ipmb_addr->lun > 3)
++ return -EINVAL;
++
++ memcpy(&(recv_msg->addr), ipmb_addr, sizeof(*ipmb_addr));
++
++ recv_msg->user = user;
++ recv_msg->msgid = msgid;
++ recv_msg->msg = *msg;
++
++ if (recv_msg->msg.netfn & 0x1) {
++ /* It's a response, so use the user's sequence. */
++ ipmb_seq = msgid;
++ } else {
++ /* It's a command, so get a sequence for it. */
++ /* Create a sequence number with a 5 second timeout. */
++ /* FIXME - magic number for the timeout. */
++ rv = intf_next_seq(intf,
++ recv_msg,
++ 5000,
++ &ipmb_seq);
++ if (rv) {
++ /* We have used up all the sequence numbers,
++ probably, so abort. */
++ ipmi_free_recv_msg(recv_msg);
++ smi_msg->done(smi_msg);
++ goto out_err;
++ }
++ }
++
++ /* Format the IPMB header data. */
++ smi_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ smi_msg->data[1] = IPMI_SEND_MSG_CMD;
++ smi_msg->data[2] = addr->channel;
++ smi_msg->data[i+3] = ipmb_addr->slave_addr;
++ smi_msg->data[i+4] = (msg->netfn << 2) | (ipmb_addr->lun & 0x3);
++ smi_msg->data[i+5] = ipmb_checksum(&(smi_msg->data[i+3]), 2);
++ smi_msg->data[i+6] = source_address;
++ smi_msg->data[i+7] = (ipmb_seq << 2) | source_lun;
++ smi_msg->data[i+8] = msg->cmd;
++
++ /* Now tack on the data to the message. */
++ if (msg->data_len > 0)
++ memcpy(&(smi_msg->data[i+9]), msg->data, msg->data_len);
++ smi_msg->data_size = msg->data_len + 9;
++
++ /* Now calculate the checksum and tack it on. */
++ smi_msg->data[i+smi_msg->data_size]
++ = ipmb_checksum(&(smi_msg->data[i+6]), smi_msg->data_size-6);
++
++ /* Add on the checksum size and the offset from the
++ broadcast. */
++ smi_msg->data_size += 1 + i;
++
++ smi_msg->msgid = msgid;
++ } else {
++ /* Unknown address type. */
++ rv = -EINVAL;
++ goto out_err;
++ }
++
++ intf->handlers->sender(intf->send_info, smi_msg, priority);
++
++ return 0;
++
++ out_err:
++ smi_msg->done(smi_msg);
++ recv_msg->done(recv_msg);
++ return rv;
++}
++
++int ipmi_request(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ int priority)
++{
++ return i_ipmi_request(user,
++ user->intf,
++ addr,
++ msgid,
++ msg,
++ NULL, NULL,
++ priority,
++ user->intf->my_address,
++ user->intf->my_lun);
++}
++
++int ipmi_request_supply_msgs(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ void *supplied_smi,
++ struct ipmi_recv_msg *supplied_recv,
++ int priority)
++{
++ return i_ipmi_request(user,
++ user->intf,
++ addr,
++ msgid,
++ msg,
++ supplied_smi,
++ supplied_recv,
++ priority,
++ user->intf->my_address,
++ user->intf->my_lun);
++}
++
++int ipmi_request_with_source(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ int priority,
++ unsigned char source_address,
++ unsigned char source_lun)
++{
++ return i_ipmi_request(user,
++ user->intf,
++ addr,
++ msgid,
++ msg,
++ NULL, NULL,
++ priority,
++ source_address,
++ source_lun);
++}
++
++int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
++ void *send_info,
++ unsigned char version_major,
++ unsigned char version_minor,
++ ipmi_smi_t *intf)
++{
++ int i, j;
++ int rv;
++ unsigned long flags;
++ ipmi_smi_t new_intf;
++ struct list_head *entry;
++
++
++ /* Make sure the driver is actually initialized, this handles
++ problems with initialization order. */
++ if (!initialized) {
++ rv = ipmi_init_msghandler();
++ if (rv)
++ return rv;
++ /* The init code doesn't return an error if it was turned
++ off, but it won't initialize. Check that. */
++ if (!initialized)
++ return -ENODEV;
++ }
++
++ new_intf = kmalloc(sizeof(*new_intf), GFP_KERNEL);
++ if (!new_intf)
++ return -ENOMEM;
++
++ rv = -ENOMEM;
++
++ spin_lock_irqsave(&interfaces_outside_lock, flags);
++ write_lock(&interfaces_lock);
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ if (ipmi_interfaces[i] == NULL) {
++ new_intf->version_major = version_major;
++ new_intf->version_minor = version_minor;
++ new_intf->my_address = IPMI_BMC_SLAVE_ADDR;
++ new_intf->my_lun = 2; /* the SMS LUN. */
++ rwlock_init(&(new_intf->users_lock));
++ INIT_LIST_HEAD(&(new_intf->users));
++ new_intf->handlers = handlers;
++ new_intf->send_info = send_info;
++ spin_lock_init(&(new_intf->seq_lock));
++ for (j=0; j<IPMI_IPMB_NUM_SEQ; j++)
++ new_intf->seq_table[j].inuse = 0;
++ new_intf->curr_seq = 0;
++ spin_lock_init(&(new_intf->waiting_msgs_lock));
++ INIT_LIST_HEAD(&(new_intf->waiting_msgs));
++ spin_lock_init(&(new_intf->events_lock));
++ INIT_LIST_HEAD(&(new_intf->waiting_events));
++ new_intf->waiting_events_count = 0;
++ rwlock_init(&(new_intf->cmd_rcvr_lock));
++ INIT_LIST_HEAD(&(new_intf->cmd_rcvrs));
++ new_intf->all_cmd_rcvr = NULL;
++ MOD_INC_USE_COUNT;
++
++ ipmi_interfaces[i] = new_intf;
++
++ rv = 0;
++ *intf = new_intf;
++ break;
++ }
++ }
++
++ /* This unusual lock combination allows us to convert the
++ interfaces lock to a read lock atomically. This way, we
++ can call the callbacks with the new interface without
++ having to worry about the interface going away, but still
++ letting them register and unregister users. */
++ write_unlock(&interfaces_lock);
++ read_lock(&interfaces_lock);
++ spin_unlock_irqrestore(&interfaces_outside_lock, flags);
++
++ if (rv == 0) {
++ /* Call all the watcher interfaces to tell them that a
++ new interface is available. */
++ read_lock(&smi_watcher_lock);
++ list_for_each(entry, &smi_watchers) {
++ struct ipmi_smi_watcher *w;
++ w = list_entry(entry, struct ipmi_smi_watcher, link);
++ w->new_smi(i);
++ }
++ read_unlock(&smi_watcher_lock);
++ }
++
++ read_unlock(&interfaces_lock);
++
++ if (rv)
++ kfree(new_intf);
++
++ return rv;
++}
++
++static void free_recv_msg_list(struct list_head *q)
++{
++ struct list_head *entry, *entry2;
++ struct ipmi_recv_msg *msg;
++
++ list_for_each_safe(entry, entry2, q) {
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ list_del(entry);
++ ipmi_free_recv_msg(msg);
++ }
++}
++
++static void free_cmd_rcvr_list(struct list_head *q)
++{
++ struct list_head *entry, *entry2;
++ struct cmd_rcvr *rcvr;
++
++ list_for_each_safe(entry, entry2, q) {
++ rcvr = list_entry(entry, struct cmd_rcvr, link);
++ list_del(entry);
++ kfree(rcvr);
++ }
++}
++
++static void clean_up_interface_data(ipmi_smi_t intf)
++{
++ int i;
++
++ free_recv_msg_list(&(intf->waiting_msgs));
++ free_recv_msg_list(&(intf->waiting_events));
++ free_cmd_rcvr_list(&(intf->cmd_rcvrs));
++
++ for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) {
++ if ((intf->seq_table[i].inuse)
++ && (intf->seq_table[i].recv_msg))
++ {
++ ipmi_free_recv_msg(intf->seq_table[i].recv_msg);
++ }
++ }
++}
++
++int ipmi_unregister_smi(ipmi_smi_t intf)
++{
++ int rv = -ENODEV;
++ unsigned long flags;
++ int i;
++ struct list_head *entry;
++
++ spin_lock_irqsave(&interfaces_outside_lock, flags);
++ write_lock(&interfaces_lock);
++
++ write_lock(&(intf->users_lock));
++ if (list_empty(&(intf->users)))
++ {
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ if (ipmi_interfaces[i] == intf) {
++ clean_up_interface_data(intf);
++ ipmi_interfaces[i] = NULL;
++ write_unlock(&(intf->users_lock));
++ kfree(intf);
++ MOD_DEC_USE_COUNT;
++ rv = 0;
++ goto out_call_watcher;
++ }
++ }
++ } else {
++ rv = -EBUSY;
++ }
++ write_unlock(&(intf->users_lock));
++ spin_unlock_irqrestore(&interfaces_outside_lock, flags);
++
++ return rv;
++
++ out_call_watcher:
++ /* This unusual lock combination allows us to convert the
++ interfaces lock to a read lock atomically. This way, we
++ can call the callbacks with the new interface without
++ having to worry about the interface going away, but still
++ letting them register and unregister users. */
++ write_unlock(&interfaces_lock);
++ read_lock(&interfaces_lock);
++ spin_unlock_irqrestore(&interfaces_outside_lock, flags);
++
++ /* Call all the watcher interfaces to tell them that
++ an interface is gone. */
++ read_lock(&smi_watcher_lock);
++ list_for_each(entry, &smi_watchers) {
++ struct ipmi_smi_watcher *w;
++ w = list_entry(entry,
++ struct ipmi_smi_watcher,
++ link);
++ w->smi_gone(i);
++ }
++ read_unlock(&smi_watcher_lock);
++ read_unlock(&interfaces_lock);
++ return 0;
++}
++
++static int handle_get_msg_rsp(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ struct ipmi_ipmb_addr ipmb_addr;
++ struct ipmi_recv_msg *recv_msg;
++
++
++ if (msg->rsp[2] != 0) {
++ /* An error getting the response, just ignore it. */
++ return 0;
++ }
++
++ ipmb_addr.addr_type = IPMI_IPMB_ADDR_TYPE;
++ ipmb_addr.slave_addr = msg->rsp[6];
++ ipmb_addr.lun = msg->rsp[7] & 3;
++
++ /* It's a response from a remote entity. Look up the sequence
++ number and handle the response. */
++ if (intf_find_seq(intf,
++ msg->rsp[7] >> 2,
++ msg->rsp[3],
++ msg->rsp[8],
++ (msg->rsp[4] >> 2) & (~1),
++ (struct ipmi_addr *) &(ipmb_addr),
++ &recv_msg))
++ {
++ /* We were unable to find the sequence number,
++ so just nuke the message. */
++ return 0;
++ }
++
++ memcpy(recv_msg->msg_data,
++ &(msg->rsp[9]),
++ msg->rsp_size - 9);
++ /* THe other fields matched, so no need to set them, except
++ for netfn, which needs to be the response that was
++ returned, not the request value. */
++ recv_msg->msg.netfn = msg->rsp[4] >> 2;
++ recv_msg->msg.data = recv_msg->msg_data;
++ recv_msg->msg.data_len = msg->rsp_size - 9;
++ recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
++ deliver_response(recv_msg);
++
++ return 0;
++}
++
++static int handle_get_msg_cmd(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ struct list_head *entry;
++ struct cmd_rcvr *rcvr;
++ int rv = 0;
++ unsigned char netfn;
++ unsigned char cmd;
++ ipmi_user_t user = NULL;
++ struct ipmi_ipmb_addr *ipmb_addr;
++ struct ipmi_recv_msg *recv_msg;
++
++ if (msg->rsp[2] != 0) {
++ /* An error getting the response, just ignore it. */
++ return 0;
++ }
++
++ netfn = msg->rsp[4] >> 2;
++ cmd = msg->rsp[8];
++
++ read_lock(&(intf->cmd_rcvr_lock));
++
++ if (intf->all_cmd_rcvr) {
++ user = intf->all_cmd_rcvr;
++ } else {
++ /* Find the command/netfn. */
++ list_for_each(entry, &(intf->cmd_rcvrs)) {
++ rcvr = list_entry(entry, struct cmd_rcvr, link);
++ if ((rcvr->netfn == netfn) || (rcvr->cmd == cmd)) {
++ user = rcvr->user;
++ break;
++ }
++ }
++ }
++ read_unlock(&(intf->cmd_rcvr_lock));
++
++ if (user == NULL) {
++ /* We didn't find a user, deliver an error response. */
++ msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg->data[1] = IPMI_SEND_MSG_CMD;
++ msg->data[2] = msg->rsp[3];
++ msg->data[3] = msg->rsp[6];
++ msg->data[4] = msg->rsp[4];
++ msg->data[5] = ipmb_checksum(&(msg->data[3]), 2);
++ msg->data[6] = intf->my_address;
++ msg->data[7] = msg->rsp[7]; /* rqseq/lun */
++ msg->data[8] = msg->rsp[8]; /* cmd */
++ msg->data[9] = IPMI_INVALID_CMD_COMPLETION_CODE;
++ msg->data[10] = ipmb_checksum(&(msg->data[6]), 4);
++ msg->data_size = 11;
++
++ intf->handlers->sender(intf->send_info, msg, 0);
++
++ rv = -1; /* We used the message, so return the value that
++ causes it to not be freed or queued. */
++ } else {
++ /* Deliver the message to the user. */
++ recv_msg = ipmi_alloc_recv_msg();
++ if (! recv_msg) {
++ /* We couldn't allocate memory for the
++ message, so requeue it for handling
++ later. */
++ rv = 1;
++ } else {
++ ipmb_addr = (struct ipmi_ipmb_addr *) &recv_msg->addr;
++ ipmb_addr->addr_type = IPMI_IPMB_ADDR_TYPE;
++ ipmb_addr->slave_addr = msg->rsp[6];
++ ipmb_addr->lun = msg->rsp[7] & 3;
++ ipmb_addr->channel = msg->rsp[3];
++
++ recv_msg->user = user;
++ recv_msg->recv_type = IPMI_CMD_RECV_TYPE;
++ recv_msg->msgid = msg->rsp[7] >> 2;
++ recv_msg->msg.netfn = msg->rsp[4] >> 2;
++ recv_msg->msg.cmd = msg->rsp[8];
++ recv_msg->msg.data = recv_msg->msg_data;
++ recv_msg->msg.data_len = msg->rsp_size - 9;
++ memcpy(recv_msg->msg_data,
++ &(msg->rsp[9]),
++ msg->rsp_size - 9);
++ deliver_response(recv_msg);
++ }
++ }
++
++ return rv;
++}
++
++static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg,
++ struct ipmi_smi_msg *msg)
++{
++ struct ipmi_system_interface_addr *smi_addr;
++
++ recv_msg->msgid = 0;
++ smi_addr = (struct ipmi_system_interface_addr *) &(recv_msg->addr);
++ smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr->channel = IPMI_BMC_CHANNEL;
++ smi_addr->lun = msg->rsp[0] & 3;
++ recv_msg->recv_type = IPMI_ASYNC_EVENT_RECV_TYPE;
++ recv_msg->msg.netfn = msg->rsp[0] >> 2;
++ recv_msg->msg.cmd = msg->rsp[1];
++ memcpy(recv_msg->msg_data, &(msg->rsp[3]), msg->rsp_size - 3);
++ recv_msg->msg.data = recv_msg->msg_data;
++ recv_msg->msg.data_len = msg->rsp_size - 3;
++}
++
++/* This will be called with the intf->users_lock read-locked, so no need
++ to do that here. */
++static int handle_read_event_rsp(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ struct ipmi_recv_msg *recv_msg;
++ struct list_head msgs;
++ struct list_head *entry, *entry2;
++ ipmi_user_t user;
++ int rv = 0;
++ int deliver_count = 0;
++ unsigned long flags;
++
++ if (msg->rsp_size < 19) {
++ /* Message is too small to be an IPMB event. */
++ return 0;
++ }
++
++ if (msg->rsp[2] != 0) {
++ /* An error getting the event, just ignore it. */
++ return 0;
++ }
++
++ INIT_LIST_HEAD(&msgs);
++
++ spin_lock_irqsave(&(intf->events_lock), flags);
++
++ /* Allocate and fill in one message for every user that is getting
++ events. */
++ list_for_each(entry, &(intf->users)) {
++ user = list_entry(entry, struct ipmi_user, link);
++
++ if (! user->gets_events)
++ continue;
++
++ recv_msg = ipmi_alloc_recv_msg();
++ if (! recv_msg) {
++ list_for_each_safe(entry, entry2, &msgs) {
++ recv_msg = list_entry(entry,
++ struct ipmi_recv_msg,
++ link);
++ list_del(entry);
++ ipmi_free_recv_msg(recv_msg);
++ }
++ /* We couldn't allocate memory for the
++ message, so requeue it for handling
++ later. */
++ rv = 1;
++ goto out;
++ }
++
++ deliver_count++;
++
++ copy_event_into_recv_msg(recv_msg, msg);
++ recv_msg->user = user;
++ list_add_tail(&(recv_msg->link), &msgs);
++ }
++
++ if (deliver_count) {
++ /* Now deliver all the messages. */
++ list_for_each_safe(entry, entry2, &msgs) {
++ recv_msg = list_entry(entry,
++ struct ipmi_recv_msg,
++ link);
++ list_del(entry);
++ deliver_response(recv_msg);
++ }
++ } else if (intf->waiting_events_count < MAX_EVENTS_IN_QUEUE) {
++ /* No one to receive the message, put it in queue if there's
++ not already too many things in the queue. */
++ recv_msg = ipmi_alloc_recv_msg();
++ if (! recv_msg) {
++ /* We couldn't allocate memory for the
++ message, so requeue it for handling
++ later. */
++ rv = 1;
++ goto out;
++ }
++
++ copy_event_into_recv_msg(recv_msg, msg);
++ list_add_tail(&(recv_msg->link), &(intf->waiting_events));
++ } else {
++ /* There's too many things in the queue, discard this
++ message. */
++ printk(KERN_WARNING "ipmi: Event queue full, discarding an"
++ " incoming event\n");
++ }
++
++ out:
++ spin_unlock_irqrestore(&(intf->events_lock), flags);
++
++ return rv;
++}
++
++static int handle_bmc_rsp(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ struct ipmi_recv_msg *recv_msg;
++ int found = 0;
++ struct list_head *entry;
++
++ recv_msg = (struct ipmi_recv_msg *) msg->user_data;
++
++ /* Make sure the user still exists. */
++ list_for_each(entry, &(intf->users)) {
++ if (list_entry(entry, struct ipmi_user, link)
++ == recv_msg->user)
++ {
++ /* Found it, so we can deliver it */
++ found = 1;
++ break;
++ }
++ }
++
++ if (!found) {
++ /* The user for the message went away, so give up. */
++ ipmi_free_recv_msg(recv_msg);
++ } else {
++ struct ipmi_system_interface_addr *smi_addr;
++
++ recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
++ recv_msg->msgid = msg->msgid;
++ smi_addr = ((struct ipmi_system_interface_addr *)
++ &(recv_msg->addr));
++ smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr->channel = IPMI_BMC_CHANNEL;
++ smi_addr->lun = msg->rsp[0] & 3;
++ recv_msg->msg.netfn = msg->rsp[0] >> 2;
++ recv_msg->msg.cmd = msg->rsp[1];
++ memcpy(recv_msg->msg_data,
++ &(msg->rsp[2]),
++ msg->rsp_size - 2);
++ recv_msg->msg.data = recv_msg->msg_data;
++ recv_msg->msg.data_len = msg->rsp_size - 2;
++ deliver_response(recv_msg);
++ }
++
++ return 0;
++}
++
++/* Handle a new message. Return 1 if the message should be requeued,
++ 0 if the message should be freed, or -1 if the message should not
++ be freed or requeued. */
++static int handle_new_recv_msg(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ int requeue;
++
++ if (msg->rsp_size < 2) {
++ /* Message is too small to be correct. */
++ requeue = 0;
++ } else if (msg->rsp[1] == IPMI_GET_MSG_CMD) {
++ /* It's from the receive queue. */
++ if (msg->rsp_size < 11) {
++ /* It's too small to be valid, just ignore it. */
++ requeue = 0;
++ } else if (msg->rsp[4] & 0x04) {
++ /* It's a response, so find the requesting message
++ and send it up. */
++ requeue = handle_get_msg_rsp(intf, msg);
++ } else {
++ /* It's a command to the SMS from some other
++ entity. Handle that. */
++ requeue = handle_get_msg_cmd(intf, msg);
++ }
++ } else if (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD) {
++ /* It's an asyncronous event. */
++ requeue = handle_read_event_rsp(intf, msg);
++ } else {
++ /* It's a response from the local BMC. */
++ requeue = handle_bmc_rsp(intf, msg);
++ }
++
++ return requeue;
++}
++
++/* Handle a new message from the lower layer. */
++void ipmi_smi_msg_received(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ unsigned long flags;
++ int rv;
++
++
++ if ((msg->data_size >= 2) && (msg->data[1] == IPMI_SEND_MSG_CMD)) {
++ /* This is the local response to a send, we just
++ ignore these. */
++ msg->done(msg);
++ return;
++ }
++
++ /* Lock the user lock so the user can't go away while we are
++ working on it. */
++ read_lock(&(intf->users_lock));
++
++ /* To preserve message order, if the list is not empty, we
++ tack this message onto the end of the list. */
++ spin_lock_irqsave(&(intf->waiting_msgs_lock), flags);
++ if (!list_empty(&(intf->waiting_msgs))) {
++ list_add_tail(&(msg->link), &(intf->waiting_msgs));
++ spin_unlock(&(intf->waiting_msgs_lock));
++ return;
++ }
++ spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
++
++ rv = handle_new_recv_msg(intf, msg);
++ if (rv > 0) {
++ /* Could not handle the message now, just add it to a
++ list to handle later. */
++ spin_lock(&(intf->waiting_msgs_lock));
++ list_add_tail(&(msg->link), &(intf->waiting_msgs));
++ spin_unlock(&(intf->waiting_msgs_lock));
++ } else if (rv == 0) {
++ msg->done(msg);
++ }
++
++ read_unlock(&(intf->users_lock));
++}
++
++void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf)
++{
++ struct list_head *entry;
++ ipmi_user_t user;
++
++ read_lock(&(intf->users_lock));
++ list_for_each(entry, &(intf->users)) {
++ user = list_entry(entry, struct ipmi_user, link);
++
++ if (! user->handler->ipmi_watchdog_pretimeout)
++ continue;
++
++ user->handler->ipmi_watchdog_pretimeout(user->handler_data);
++ }
++ read_unlock(&(intf->users_lock));
++}
++
++static void
++handle_msg_timeout(struct ipmi_recv_msg *msg)
++{
++ msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
++ msg->msg_data[0] = IPMI_TIMEOUT_COMPLETION_CODE;
++ msg->msg.netfn |= 1; /* Convert to a response. */
++ msg->msg.data_len = 1;
++ msg->msg.data = msg->msg_data;
++ deliver_response(msg);
++}
++
++static void
++ipmi_timeout_handler(long timeout_period)
++{
++ ipmi_smi_t intf;
++ struct list_head timeouts;
++ struct ipmi_recv_msg *msg;
++ struct ipmi_smi_msg *smi_msg;
++ unsigned long flags;
++ struct list_head *entry, *entry2;
++ int i, j;
++
++ INIT_LIST_HEAD(&timeouts);
++
++ read_lock(&interfaces_lock);
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ intf = ipmi_interfaces[i];
++ if (intf == NULL)
++ continue;
++
++ read_lock(&(intf->users_lock));
++
++ /* See if any waiting messages need to be processed. */
++ spin_lock_irqsave(&(intf->waiting_msgs_lock), flags);
++ list_for_each_safe(entry, entry2, &(intf->waiting_msgs)) {
++ smi_msg = list_entry(entry, struct ipmi_smi_msg, link);
++ if (! handle_new_recv_msg(intf, smi_msg)) {
++ list_del(entry);
++ smi_msg->done(smi_msg);
++ } else {
++ /* To preserve message order, quit if we
++ can't handle a message. */
++ break;
++ }
++ }
++ spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
++
++ /* Go through the seq table and find any messages that
++ have timed out, putting them in the timeouts
++ list. */
++ spin_lock_irqsave(&(intf->seq_lock), flags);
++ for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) {
++ if (intf->seq_table[j].inuse) {
++ intf->seq_table[j].timeout -= timeout_period;
++ if (intf->seq_table[j].timeout <= 0) {
++ intf->seq_table[j].inuse = 0;
++ msg = intf->seq_table[j].recv_msg;
++ list_add_tail(&(msg->link), &timeouts);
++ }
++ }
++ }
++ spin_unlock_irqrestore(&(intf->seq_lock), flags);
++
++ list_for_each_safe(entry, entry2, &timeouts) {
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ handle_msg_timeout(msg);
++ }
++
++ read_unlock(&(intf->users_lock));
++ }
++
++ read_unlock(&interfaces_lock);
++}
++
++static void ipmi_request_event(void)
++{
++ ipmi_smi_t intf;
++ int i;
++
++ read_lock(&interfaces_lock);
++
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ intf = ipmi_interfaces[i];
++ if (intf == NULL)
++ continue;
++
++ intf->handlers->request_events(intf->send_info);
++ }
++
++ read_unlock(&interfaces_lock);
++}
++
++static struct timer_list ipmi_timer;
++
++/* Call every 100 ms. */
++#define IPMI_TIMEOUT_TIME 100
++#define IPMI_TIMEOUT_JIFFIES (IPMI_TIMEOUT_TIME/(1000/HZ))
++
++/* Request events from the queue every second. Hopefully, in the
++ future, IPMI will add a way to know immediately if an event is
++ in the queue. */
++#define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME))
++
++static volatile int stop_operation = 0;
++static volatile int timer_stopped = 0;
++static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
++
++static void ipmi_timeout(unsigned long data)
++{
++ if (stop_operation) {
++ timer_stopped = 1;
++ return;
++ }
++
++ ticks_to_req_ev--;
++ if (ticks_to_req_ev == 0) {
++ ipmi_request_event();
++ ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
++ }
++
++ ipmi_timeout_handler(IPMI_TIMEOUT_TIME);
++
++ ipmi_timer.expires += IPMI_TIMEOUT_JIFFIES;
++ add_timer(&ipmi_timer);
++}
++
++
++/* FIXME - convert these to slabs. */
++static void free_smi_msg(struct ipmi_smi_msg *msg)
++{
++ kfree(msg);
++}
++
++struct ipmi_smi_msg *ipmi_alloc_smi_msg(void)
++{
++ struct ipmi_smi_msg *rv;
++ rv = kmalloc(sizeof(struct ipmi_smi_msg), GFP_ATOMIC);
++ if (rv)
++ rv->done = free_smi_msg;
++ return rv;
++}
++
++static void free_recv_msg(struct ipmi_recv_msg *msg)
++{
++ kfree(msg);
++}
++
++struct ipmi_recv_msg *ipmi_alloc_recv_msg(void)
++{
++ struct ipmi_recv_msg *rv;
++
++ rv = kmalloc(sizeof(struct ipmi_recv_msg), GFP_ATOMIC);
++ if (rv)
++ rv->done = free_recv_msg;
++ return rv;
++}
++
++#ifdef CONFIG_IPMI_PANIC_EVENT
++
++static void dummy_smi_done_handler(struct ipmi_smi_msg *msg)
++{
++}
++
++static void dummy_recv_done_handler(struct ipmi_recv_msg *msg)
++{
++}
++
++static void send_panic_events(void)
++{
++ struct ipmi_msg msg;
++ ipmi_smi_t intf;
++ unsigned char data[8];
++ int i;
++ struct ipmi_system_interface_addr addr;
++ struct ipmi_smi_msg smi_msg;
++ struct ipmi_recv_msg recv_msg;
++
++ addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ addr.channel = IPMI_BMC_CHANNEL;
++
++ /* Fill in an event telling that we have failed. */
++ msg.netfn = 0x04; /* Sensor or Event. */
++ msg.cmd = 2; /* Platform event command. */
++ msg.data = data;
++ msg.data_len = 8;
++ data[0] = 0x21; /* Kernel generator ID, IPMI table 5-4 */
++ data[1] = 0x03; /* This is for IPMI 1.0. */
++ data[2] = 0x20; /* OS Critical Stop, IPMI table 36-3 */
++ data[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
++ data[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
++
++ /* These used to have the first three bytes of the panic string,
++ but not only is that not terribly useful, it's not available
++ any more. */
++ data[3] = 0;
++ data[6] = 0;
++ data[7] = 0;
++
++ smi_msg.done = dummy_smi_done_handler;
++ recv_msg.done = dummy_recv_done_handler;
++
++ /* For every registered interface, send the event. */
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ intf = ipmi_interfaces[i];
++ if (intf == NULL)
++ continue;
++
++ intf->handlers->set_run_to_completion(intf->send_info, 1);
++ i_ipmi_request(NULL,
++ intf,
++ (struct ipmi_addr *) &addr,
++ 0,
++ &msg,
++ &smi_msg,
++ &recv_msg,
++ 0,
++ intf->my_address,
++ intf->my_lun);
++ }
++}
++#endif /* CONFIG_IPMI_PANIC_EVENT */
++
++static int has_paniced = 0;
++
++static int panic_event(struct notifier_block *this,
++ unsigned long event,
++ void *ptr)
++{
++ int i;
++ ipmi_smi_t intf;
++
++ if (has_paniced)
++ return NOTIFY_DONE;
++ has_paniced = 1;
++
++ /* For every registered interface, set it to run to completion. */
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ intf = ipmi_interfaces[i];
++ if (intf == NULL)
++ continue;
++
++ intf->handlers->set_run_to_completion(intf->send_info, 1);
++ }
++
++#ifdef CONFIG_IPMI_PANIC_EVENT
++ send_panic_events();
++#endif
++
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block panic_block = {
++ panic_event,
++ NULL,
++ 200 /* priority: INT_MAX >= x >= 0 */
++};
++
++
++static int ipmi_init_msghandler(void)
++{
++ int i;
++
++ if (initialized)
++ return 0;
++
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ ipmi_interfaces[i] = NULL;
++ }
++
++ init_timer(&ipmi_timer);
++ ipmi_timer.data = 0;
++ ipmi_timer.function = ipmi_timeout;
++ ipmi_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES;
++ add_timer(&ipmi_timer);
++
++ notifier_chain_register(&panic_notifier_list, &panic_block);
++
++ initialized = 1;
++
++ printk(KERN_INFO "ipmi: message handler initialized\n");
++
++ return 0;
++}
++
++static __exit void cleanup_ipmi(void)
++{
++ if (!initialized)
++ return;
++
++ notifier_chain_unregister(&panic_notifier_list, &panic_block);
++
++ /* This can't be called if any interfaces exist, so no worry about
++ shutting down the interfaces. */
++
++ /* Tell the timer to stop, then wait for it to stop. This avoids
++ problems with race conditions removing the timer here. */
++ stop_operation = 1;
++ while (!timer_stopped) {
++ schedule_timeout(1);
++ }
++
++ initialized = 0;
++}
++module_exit(cleanup_ipmi);
++
++module_init(ipmi_init_msghandler);
++MODULE_LICENSE("GPL");
++
++EXPORT_SYMBOL(ipmi_alloc_recv_msg);
++EXPORT_SYMBOL(ipmi_create_user);
++EXPORT_SYMBOL(ipmi_destroy_user);
++EXPORT_SYMBOL(ipmi_get_version);
++EXPORT_SYMBOL(ipmi_request);
++EXPORT_SYMBOL(ipmi_request_supply_msgs);
++EXPORT_SYMBOL(ipmi_request_with_source);
++EXPORT_SYMBOL(ipmi_register_smi);
++EXPORT_SYMBOL(ipmi_unregister_smi);
++EXPORT_SYMBOL(ipmi_register_for_cmd);
++EXPORT_SYMBOL(ipmi_unregister_for_cmd);
++EXPORT_SYMBOL(ipmi_smi_msg_received);
++EXPORT_SYMBOL(ipmi_smi_watchdog_pretimeout);
++EXPORT_SYMBOL(ipmi_alloc_smi_msg);
++EXPORT_SYMBOL(ipmi_register_all_cmd_rcvr);
++EXPORT_SYMBOL(ipmi_unregister_all_cmd_rcvr);
++EXPORT_SYMBOL(ipmi_addr_length);
++EXPORT_SYMBOL(ipmi_validate_addr);
++EXPORT_SYMBOL(ipmi_set_gets_events);
++EXPORT_SYMBOL(ipmi_addr_equal);
++EXPORT_SYMBOL(ipmi_smi_watcher_register);
++EXPORT_SYMBOL(ipmi_smi_watcher_unregister);
++EXPORT_SYMBOL(ipmi_set_my_address);
++EXPORT_SYMBOL(ipmi_get_my_address);
++EXPORT_SYMBOL(ipmi_set_my_LUN);
++EXPORT_SYMBOL(ipmi_get_my_LUN);
+diff -urN linux.orig/drivers/char/ipmi/ipmi_watchdog.c linux/drivers/char/ipmi/ipmi_watchdog.c
+--- linux.orig/drivers/char/ipmi/ipmi_watchdog.c Wed Dec 31 18:00:00 1969
++++ linux/drivers/char/ipmi/ipmi_watchdog.c Mon Oct 28 16:34:03 2002
+@@ -0,0 +1,863 @@
++/*
++ * ipmi_watchdog.c
++ *
++ * A watchdog timer based upon the IPMI interface.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/ipmi.h>
++#include <linux/ipmi_smi.h>
++#include <linux/watchdog.h>
++#include <linux/miscdevice.h>
++#include <linux/init.h>
++#include <linux/spinlock.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <linux/notifier.h>
++#include <linux/nmi.h>
++#include <linux/reboot.h>
++
++/*
++ * The IPMI command/response information for the watchdog timer.
++ */
++
++/* values for byte 1 of the set command, byte 2 of the get response. */
++#define WDOG_DONT_LOG (1 << 7)
++#define WDOG_DONT_STOP_ON_SET (1 << 6)
++#define WDOG_SET_TIMER_USE(byte, use) \
++ byte = ((byte) & 0xf8) | ((use) & 0x7)
++#define WDOG_GET_TIMER_USE(byte) ((byte) & 0x7)
++#define WDOG_TIMER_USE_BIOS_FRB2 1
++#define WDOG_TIMER_USE_BIOS_POST 2
++#define WDOG_TIMER_USE_OS_LOAD 3
++#define WDOG_TIMER_USE_SMS_OS 4
++#define WDOG_TIMER_USE_OEM 5
++
++/* values for byte 2 of the set command, byte 3 of the get response. */
++#define WDOG_SET_PRETIMEOUT_ACT(byte, use) \
++ byte = ((byte) & 0x8f) | (((use) & 0x7) << 4)
++#define WDOG_GET_PRETIMEOUT_ACT(byte) (((byte) >> 4) & 0x7)
++#define WDOG_PRETIMEOUT_NONE 0
++#define WDOG_PRETIMEOUT_SMI 1
++#define WDOG_PRETIMEOUT_NMI 2
++#define WDOG_PRETIMEOUT_MSG_INT 3
++
++#define WDOG_SET_TIMEOUT_ACT(byte, use) \
++ byte = ((byte) & 0xf8) | ((use) & 0x7)
++#define WDOG_GET_TIMEOUT_ACT(byte) ((byte) & 0x7)
++#define WDOG_TIMEOUT_NONE 0
++#define WDOG_TIMEOUT_RESET 1
++#define WDOG_TIMEOUT_POWER_DOWN 2
++#define WDOG_TIMEOUT_POWER_CYCLE 3
++
++/* Byte 3 of the get command, byte 4 of the get response is the
++ pre-timeout in seconds. */
++
++/* Bits for setting byte 4 of the set command, byte 5 of the get response. */
++#define WDOG_EXPIRE_CLEAR_BIOS_FRB2 (1 << 1)
++#define WDOG_EXPIRE_CLEAR_BIOS_POST (1 << 2)
++#define WDOG_EXPIRE_CLEAR_OS_LOAD (1 << 3)
++#define WDOG_EXPIRE_CLEAR_SMS_OS (1 << 4)
++#define WDOG_EXPIRE_CLEAR_OEM (1 << 5)
++
++/* Setting/getting the watchdog timer value. This is for bytes 5 and
++ 6 (the timeout time) of the set command, and bytes 6 and 7 (the
++ timeout time) and 8 and 9 (the current countdown value) of the
++ response. The timeout value is given in seconds (in the command it
++ is 100ms intervals). */
++#define WDOG_SET_TIMEOUT(byte1, byte2, val) \
++ (byte1) = (((val) * 10) & 0xff), (byte2) = (((val) * 10) >> 8)
++#define WDOG_GET_TIMEOUT(byte1, byte2) \
++ (((byte1) | ((byte2) << 8)) / 10)
++
++#define IPMI_WDOG_RESET_TIMER 0x22
++#define IPMI_WDOG_SET_TIMER 0x24
++#define IPMI_WDOG_GET_TIMER 0x25
++
++/* These are here until the real ones get into the watchdog.h interface. */
++#ifndef WDIOC_GETTIMEOUT
++#define WDIOC_GETTIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 20, int)
++#endif
++#ifndef WDIOC_SET_PRETIMEOUT
++#define WDIOC_SET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 21, int)
++#endif
++#ifndef WDIOC_GET_PRETIMEOUT
++#define WDIOC_GET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 22, int)
++#endif
++
++static ipmi_user_t watchdog_user = NULL;
++
++/* Default the timeout to 10 seconds. */
++static int timeout = 10;
++
++/* The pre-timeout is disabled by default. */
++static int pretimeout = 0;
++
++/* Default action is to reset the board on a timeout. */
++static unsigned char action_val = WDOG_TIMEOUT_RESET;
++
++static char *action = "reset";
++
++static unsigned char preaction_val = WDOG_PRETIMEOUT_NONE;
++
++static char *preaction = "none";
++
++MODULE_PARM(timeout, "i");
++MODULE_PARM(pretimeout, "i");
++MODULE_PARM(action, "s");
++MODULE_PARM(preaction, "s");
++
++/* Default state of the timer. */
++static unsigned char ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
++
++/* If shutting down via IPMI, we ignore the heartbeat. */
++static int ipmi_ignore_heartbeat = 0;
++
++/* Is someone using the watchdog? Only one user is allowed. */
++static int ipmi_wdog_open = 0;
++
++/* If true, the driver will start running as soon as it is configured
++ and ready. */
++static int start_now = 0;
++
++/* If set to 1, the heartbeat command will set the state to reset and
++ start the timer. The timer doesn't normally run when the driver is
++ first opened until the heartbeat is set the first time, this
++ variable is used to accomplish this. */
++static int ipmi_start_timer_on_heartbeat = 0;
++
++/* IPMI version of the BMC. */
++static unsigned char ipmi_version_major;
++static unsigned char ipmi_version_minor;
++
++
++static int ipmi_heartbeat(void);
++
++
++/* We use a semaphore to make sure that only one thing can send a set
++ timeout at one time, because we only have one copy of the data.
++ The semaphore is claimed when the set_timeout is sent and freed
++ when both messages are free. */
++static atomic_t set_timeout_tofree = ATOMIC_INIT(0);
++static DECLARE_MUTEX(set_timeout_lock);
++static void set_timeout_free_smi(struct ipmi_smi_msg *msg)
++{
++ if (atomic_dec_and_test(&set_timeout_tofree))
++ up(&set_timeout_lock);
++}
++static void set_timeout_free_recv(struct ipmi_recv_msg *msg)
++{
++ if (atomic_dec_and_test(&set_timeout_tofree))
++ up(&set_timeout_lock);
++}
++static struct ipmi_smi_msg set_timeout_smi_msg =
++{
++ .done = set_timeout_free_smi
++};
++static struct ipmi_recv_msg set_timeout_recv_msg =
++{
++ .done = set_timeout_free_recv
++};
++
++static int ipmi_set_timeout(void)
++{
++ struct ipmi_msg msg;
++ unsigned char data[6];
++ int rv;
++ struct ipmi_system_interface_addr addr;
++ int send_heartbeat_now = 0;
++
++
++ /* We can only send one of these at a time. */
++ down(&set_timeout_lock);
++
++ atomic_set(&set_timeout_tofree, 2);
++
++ data[0] = 0;
++ WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);
++
++ if ((ipmi_version_major > 1)
++ || ((ipmi_version_major == 1) && (ipmi_version_minor >= 5)))
++ {
++ /* This is an IPMI 1.5-only feature. */
++ data[0] |= WDOG_DONT_STOP_ON_SET;
++ } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
++ /* In ipmi 1.0, setting the timer stops the watchdog, we
++ need to start it back up again. */
++ send_heartbeat_now = 1;
++ }
++
++ data[1] = 0;
++ WDOG_SET_TIMEOUT_ACT(data[1], ipmi_watchdog_state);
++ if (pretimeout > 0) {
++ WDOG_SET_PRETIMEOUT_ACT(data[1], preaction_val);
++ data[2] = pretimeout;
++ } else {
++ WDOG_SET_PRETIMEOUT_ACT(data[1], WDOG_PRETIMEOUT_NONE);
++ data[2] = 0; /* No pretimeout. */
++ }
++ data[3] = 0;
++ WDOG_SET_TIMEOUT(data[4], data[5], timeout);
++
++ addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ addr.channel = IPMI_BMC_CHANNEL;
++ addr.lun = 0;
++
++ msg.netfn = 0x06;
++ msg.cmd = IPMI_WDOG_SET_TIMER;
++ msg.data = data;
++ msg.data_len = sizeof(data);
++ rv = ipmi_request_supply_msgs(watchdog_user,
++ (struct ipmi_addr *) &addr,
++ 0,
++ &msg,
++ &set_timeout_smi_msg,
++ &set_timeout_recv_msg,
++ 1);
++ if (rv) {
++ up(&set_timeout_lock);
++ printk(KERN_WARNING "IPMI Watchdog, set timeout error: %d\n",
++ rv);
++ } else {
++ if (send_heartbeat_now)
++ rv = ipmi_heartbeat();
++ }
++
++ return rv;
++}
++
++/* Do a delayed shutdown, with the delay in milliseconds. If power_off is
++ false, do a reset. If power_off is true, do a power down. This is
++ primarily for the IMB code's shutdown. */
++void ipmi_delayed_shutdown(long delay, int power_off)
++{
++ ipmi_ignore_heartbeat = 1;
++ if (power_off)
++ ipmi_watchdog_state = WDOG_TIMEOUT_POWER_DOWN;
++ else
++ ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
++ timeout = delay;
++ ipmi_set_timeout();
++}
++
++/* We use a semaphore to make sure that only one thing can send a
++ heartbeat at one time, because we only have one copy of the data.
++ The semaphore is claimed when the set_timeout is sent and freed
++ when both messages are free. */
++static atomic_t heartbeat_tofree = ATOMIC_INIT(0);
++static DECLARE_MUTEX(heartbeat_lock);
++static DECLARE_MUTEX_LOCKED(heartbeat_wait_lock);
++static void heartbeat_free_smi(struct ipmi_smi_msg *msg)
++{
++ if (atomic_dec_and_test(&heartbeat_tofree))
++ up(&heartbeat_wait_lock);
++}
++static void heartbeat_free_recv(struct ipmi_recv_msg *msg)
++{
++ if (atomic_dec_and_test(&heartbeat_tofree))
++ up(&heartbeat_wait_lock);
++}
++static struct ipmi_smi_msg heartbeat_smi_msg =
++{
++ .done = heartbeat_free_smi
++};
++static struct ipmi_recv_msg heartbeat_recv_msg =
++{
++ .done = heartbeat_free_recv
++};
++
++static int ipmi_heartbeat(void)
++{
++ struct ipmi_msg msg;
++ int rv;
++ struct ipmi_system_interface_addr addr;
++
++ if (ipmi_ignore_heartbeat) {
++ return 0;
++ }
++
++ if (ipmi_start_timer_on_heartbeat) {
++ ipmi_start_timer_on_heartbeat = 0;
++ ipmi_watchdog_state = action_val;
++ return ipmi_set_timeout();
++ }
++
++ down(&heartbeat_lock);
++
++ atomic_set(&heartbeat_tofree, 2);
++
++ /* Don't reset the timer if we have the timer turned off, that
++ re-enables the watchdog. */
++ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) {
++ up(&heartbeat_lock);
++ return 0;
++ }
++
++ addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ addr.channel = IPMI_BMC_CHANNEL;
++ addr.lun = 0;
++
++ msg.netfn = 0x06;
++ msg.cmd = IPMI_WDOG_RESET_TIMER;
++ msg.data = NULL;
++ msg.data_len = 0;
++ rv = ipmi_request_supply_msgs(watchdog_user,
++ (struct ipmi_addr *) &addr,
++ 0,
++ &msg,
++ &heartbeat_smi_msg,
++ &heartbeat_recv_msg,
++ 1);
++ if (rv) {
++ up(&heartbeat_lock);
++ printk(KERN_WARNING "IPMI Watchdog, heartbeat failure: %d\n",
++ rv);
++ return rv;
++ }
++
++ /* Wait for the heartbeat to be sent. */
++ down(&heartbeat_wait_lock);
++
++ if (heartbeat_recv_msg.msg.data[0] != 0) {
++ /* Got an error in the heartbeat response. It was already
++ reported in ipmi_wdog_msg_handler, but we should return
++ an error here. */
++ rv = -EINVAL;
++ }
++
++ up(&heartbeat_lock);
++
++ return rv;
++}
++
++static struct watchdog_info ident=
++{
++ 0, /* WDIOF_SETTIMEOUT, */
++ 1,
++ "IPMI"
++};
++
++static int ipmi_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ int i;
++ int val;
++
++ switch(cmd) {
++ case WDIOC_GETSUPPORT:
++ i = copy_to_user((void*)arg, &ident, sizeof(ident));
++ return i ? -EFAULT : 0;
++
++ case WDIOC_SETTIMEOUT:
++ i = copy_from_user(&val, (void *) arg, sizeof(int));
++ if (i)
++ return -EFAULT;
++ timeout = val;
++ return ipmi_set_timeout();
++
++ case WDIOC_GETTIMEOUT:
++ i = copy_to_user((void *) arg,
++ &timeout,
++ sizeof(timeout));
++ if (i)
++ return -EFAULT;
++ return 0;
++
++ case WDIOC_SET_PRETIMEOUT:
++ i = copy_from_user(&val, (void *) arg, sizeof(int));
++ if (i)
++ return -EFAULT;
++ pretimeout = val;
++ return ipmi_set_timeout();
++
++ case WDIOC_GET_PRETIMEOUT:
++ i = copy_to_user((void *) arg,
++ &pretimeout,
++ sizeof(pretimeout));
++ if (i)
++ return -EFAULT;
++ return 0;
++
++ case WDIOC_KEEPALIVE:
++ return ipmi_heartbeat();
++
++ case WDIOC_SETOPTIONS:
++ i = copy_from_user(&val, (void *) arg, sizeof(int));
++ if (i)
++ return -EFAULT;
++ if (val & WDIOS_DISABLECARD)
++ {
++ ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
++ ipmi_set_timeout();
++ ipmi_start_timer_on_heartbeat = 0;
++ }
++
++ if (val & WDIOS_ENABLECARD)
++ {
++ ipmi_watchdog_state = action_val;
++ ipmi_set_timeout();
++ }
++ return 0;
++
++ case WDIOC_GETSTATUS:
++ val = 0;
++ return copy_to_user((void *) arg, &val, sizeof(val));
++
++ default:
++ return -ENOIOCTLCMD;
++ }
++}
++
++static ssize_t ipmi_write(struct file *file,
++ const char *buf,
++ size_t len,
++ loff_t *ppos)
++{
++ int rv;
++
++ /* Can't seek (pwrite) on this device */
++ if (ppos != &file->f_pos)
++ return -ESPIPE;
++
++ if (len) {
++ rv = ipmi_heartbeat();
++ if (rv)
++ return rv;
++ return 1;
++ }
++ return 0;
++}
++
++static ssize_t ipmi_read(struct file *file,
++ char *buf,
++ size_t count,
++ loff_t *ppos)
++{
++ /* Can't seek (pread) on this device */
++ if (ppos != &file->f_pos)
++ return -ESPIPE;
++
++ /* Also can't read it. */
++ return -EINVAL;
++}
++
++static int ipmi_open(struct inode *ino, struct file *filep)
++{
++ switch (minor(ino->i_rdev))
++ {
++ case WATCHDOG_MINOR:
++ if (ipmi_wdog_open)
++ return -EBUSY;
++
++ MOD_INC_USE_COUNT;
++ ipmi_wdog_open = 1;
++
++ /* Don't start the timer now, let it start on the
++ first heartbeat. */
++ ipmi_start_timer_on_heartbeat = 1;
++ return(0);
++
++ default:
++ return (-ENODEV);
++ }
++}
++
++static int ipmi_close(struct inode *ino, struct file *filep)
++{
++ if (minor(ino->i_rdev)==WATCHDOG_MINOR)
++ {
++#ifndef CONFIG_WATCHDOG_NOWAYOUT
++ ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
++ ipmi_set_timeout();
++#endif
++ ipmi_wdog_open = 0;
++ MOD_DEC_USE_COUNT;
++ }
++ return 0;
++}
++
++static struct file_operations ipmi_wdog_fops = {
++ .owner = THIS_MODULE,
++ .read = ipmi_read,
++ .write = ipmi_write,
++ .ioctl = ipmi_ioctl,
++ .open = ipmi_open,
++ .release = ipmi_close,
++};
++
++static struct miscdevice ipmi_wdog_miscdev = {
++ WATCHDOG_MINOR,
++ "watchdog",
++ &ipmi_wdog_fops
++};
++
++static spinlock_t register_lock = SPIN_LOCK_UNLOCKED;
++
++static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
++ void *handler_data)
++{
++ if (msg->msg.data[0] != 0) {
++ printk(KERN_ERR "IPMI Watchdog response: Error %x on cmd %x\n",
++ msg->msg.data[0],
++ msg->msg.cmd);
++ }
++
++ ipmi_free_recv_msg(msg);
++}
++
++static void ipmi_wdog_pretimeout_handler(void *handler_data)
++{
++ panic("Watchdog pre-timeout");
++}
++
++static struct ipmi_user_hndl ipmi_hndlrs =
++{
++ .ipmi_recv_hndl = ipmi_wdog_msg_handler,
++ .ipmi_watchdog_pretimeout = ipmi_wdog_pretimeout_handler
++};
++
++static void ipmi_register_watchdog(int ipmi_intf)
++{
++ unsigned long flags;
++ int rv = -EBUSY;
++
++ spin_lock_irqsave(&register_lock, flags);
++ if (watchdog_user)
++ goto out;
++
++ rv = ipmi_create_user(ipmi_intf, &ipmi_hndlrs, NULL, &watchdog_user);
++ if (rv < 0) {
++ printk("IPMI watchdog: Unable to register with ipmi\n");
++ goto out;
++ }
++
++ ipmi_get_version(watchdog_user,
++ &ipmi_version_major,
++ &ipmi_version_minor);
++
++ rv = misc_register(&ipmi_wdog_miscdev);
++ if (rv < 0) {
++ ipmi_destroy_user(watchdog_user);
++ watchdog_user = NULL;
++ printk("IPMI watchdog: Unable to register misc device\n");
++ }
++
++ out:
++ spin_unlock_irqrestore(&register_lock, flags);
++
++ if ((start_now) && (rv == 0)) {
++ /* Run from startup, so start the timer now. */
++ start_now = 0; /* Disable this function after first startup. */
++ ipmi_watchdog_state = action_val;
++ ipmi_set_timeout();
++ printk("Starting IPMI Watchdog now!\n");
++ }
++}
++
++#ifdef HAVE_NMI_HANDLER
++static int
++ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled)
++{
++ /* If no one else handled the NMI, we assume it was the IPMI
++ watchdog. */
++ if (!handled)
++ panic("IPMI watchdog pre-timeout");
++ return NOTIFY_DONE;
++}
++
++static struct nmi_handler ipmi_nmi_handler =
++{
++ .link = LIST_HEAD_INIT(ipmi_nmi_handler.link),
++ .dev_name = "ipmi_watchdog",
++ .dev_id = NULL,
++ .handler = ipmi_nmi,
++ .priority = 0, /* Call us last. */
++};
++#endif
++
++static int wdog_reboot_handler(struct notifier_block *this,
++ unsigned long code,
++ void *unused)
++{
++ static int reboot_event_handled = 0;
++
++ if ((watchdog_user) && (!reboot_event_handled)) {
++ /* Make sure we only do this once. */
++ reboot_event_handled = 1;
++
++ if (code == SYS_DOWN || code == SYS_HALT) {
++ /* Disable the WDT if we are shutting down. */
++ ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
++ ipmi_set_timeout();
++ } else {
++ /* Set a long timer to let the reboot happens, but
++ reboot if it hangs. */
++ timeout = 120;
++ pretimeout = 0;
++ ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
++ ipmi_set_timeout();
++ }
++ }
++ return NOTIFY_OK;
++}
++
++static struct notifier_block wdog_reboot_notifier = {
++ wdog_reboot_handler,
++ NULL,
++ 0
++};
++
++extern int panic_timeout; /* Why isn't this defined anywhere? */
++
++static int wdog_panic_handler(struct notifier_block *this,
++ unsigned long event,
++ void *unused)
++{
++ static int panic_event_handled = 0;
++
++ /* On a panic, if we have a panic timeout, make sure that the thing
++ reboots, even if it hangs during that panic. */
++ if (watchdog_user && !panic_event_handled && (panic_timeout > 0)) {
++ /* Make sure the panic doesn't hang, and make sure we
++ do this only once. */
++ panic_event_handled = 1;
++
++ timeout = panic_timeout + 120;
++ if (timeout > 255)
++ timeout = 255;
++ pretimeout = 0;
++ ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
++ ipmi_set_timeout();
++ }
++
++ return NOTIFY_OK;
++}
++
++static struct notifier_block wdog_panic_notifier = {
++ wdog_panic_handler,
++ NULL,
++ 150 /* priority: INT_MAX >= x >= 0 */
++};
++
++
++static void ipmi_new_smi(int if_num)
++{
++ ipmi_register_watchdog(if_num);
++}
++
++static void ipmi_smi_gone(int if_num)
++{
++ /* This can never be called, because once the watchdog is
++ registered, the interface can't go away until the watchdog
++ is unregistered. */
++}
++
++static struct ipmi_smi_watcher smi_watcher =
++{
++ .new_smi = ipmi_new_smi,
++ .smi_gone = ipmi_smi_gone
++};
++
++static int __init ipmi_wdog_init(void)
++{
++ int rv;
++
++ if (strcmp(action, "reset") == 0) {
++ action_val = WDOG_TIMEOUT_RESET;
++ } else if (strcmp(action, "power_cycle") == 0) {
++ action_val = WDOG_TIMEOUT_POWER_CYCLE;
++ } else if (strcmp(action, "power_off") == 0) {
++ action_val = WDOG_TIMEOUT_POWER_DOWN;
++ } else {
++ action_val = WDOG_TIMEOUT_RESET;
++ printk("ipmi_watchdog: Unknown action '%s', defaulting to"
++ " reset\n", action);
++ }
++
++ if (strcmp(preaction, "none") == 0) {
++ preaction_val = WDOG_PRETIMEOUT_NONE;
++ } else if (strcmp(preaction, "pre_smi") == 0) {
++ preaction_val = WDOG_PRETIMEOUT_SMI;
++#ifdef HAVE_NMI_HANDLER
++ } else if (strcmp(preaction, "pre_nmi") == 0) {
++ preaction_val = WDOG_PRETIMEOUT_NMI;
++#endif
++ } else if (strcmp(preaction, "pre_int") == 0) {
++ preaction_val = WDOG_PRETIMEOUT_MSG_INT;
++ } else {
++ action_val = WDOG_PRETIMEOUT_NONE;
++ printk("ipmi_watchdog: Unknown preaction '%s', defaulting to"
++ " none\n", preaction);
++ }
++
++#ifdef HAVE_NMI_HANDLER
++ if (preaction_val == WDOG_PRETIMEOUT_NMI) {
++ rv = request_nmi(&ipmi_nmi_handler);
++ if (rv) {
++ printk(KERN_WARNING
++ "impi_watchdog: Can't register nmi handler\n");
++ return rv;
++ }
++ }
++#endif
++
++ rv = ipmi_smi_watcher_register(&smi_watcher);
++ if (rv) {
++#ifdef HAVE_NMI_HANDLER
++ if (preaction_val == WDOG_PRETIMEOUT_NMI)
++ release_nmi(&ipmi_nmi_handler);
++#endif
++ printk(KERN_WARNING
++ "ipmi_watchdog: can't register smi watcher\n");
++ return rv;
++ }
++
++ register_reboot_notifier(&wdog_reboot_notifier);
++ notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier);
++
++ printk(KERN_INFO "IPMI watchdog by "
++ "Corey Minyard (minyard@mvista.com)\n");
++
++ return 0;
++}
++
++#ifdef MODULE
++static void ipmi_unregister_watchdog(void)
++{
++ int rv;
++ unsigned long flags;
++
++ spin_lock_irqsave(&register_lock, flags);
++
++ if (! watchdog_user)
++ goto out;
++
++#ifdef HAVE_NMI_HANDLER
++ if (preaction_val == WDOG_PRETIMEOUT_NMI)
++ release_nmi(&ipmi_nmi_handler);
++#endif
++
++ /* Make sure no one can call us any more. */
++ misc_deregister(&ipmi_wdog_miscdev);
++
++ notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier);
++ unregister_reboot_notifier(&wdog_reboot_notifier);
++
++ /* Disable the timer. */
++ ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
++ ipmi_set_timeout();
++
++ /* Wait to make sure the message makes it out. The lower layer has
++ pointers to our buffers, we want to make sure they are done before
++ we release our memory. */
++ while (atomic_read(&set_timeout_tofree)) {
++ schedule_timeout(1);
++ }
++
++ /* Disconnect from IPMI. */
++ rv = ipmi_destroy_user(watchdog_user);
++ if (rv) {
++ printk(KERN_WARNING
++ "IPMI Watchdog, error unlinking from IPMI: %d\n",
++ rv);
++ }
++ watchdog_user = NULL;
++
++ out:
++ spin_unlock_irqrestore(&register_lock, flags);
++}
++
++static void __exit ipmi_wdog_exit(void)
++{
++ ipmi_smi_watcher_unregister(&smi_watcher);
++ ipmi_unregister_watchdog();
++}
++module_exit(ipmi_wdog_exit);
++#else
++static int __init ipmi_wdog_setup(char *str)
++{
++ int val;
++ int rv;
++ char *option;
++
++ rv = get_option(&str, &val);
++ if (rv == 0)
++ return 1;
++ if (val > 0)
++ timeout = val;
++ if (rv == 1)
++ return 1;
++
++ rv = get_option(&str, &val);
++ if (rv == 0)
++ return 1;
++ if (val >= 0)
++ pretimeout = val;
++ if (rv == 1)
++ return 1;
++
++ while ((option = strsep(&str, ",")) != NULL) {
++ if (strcmp(str, "reset") == 0) {
++ action = "reset";
++ }
++ else if (strcmp(str, "power_cycle") == 0) {
++ action = "power_cycle";
++ }
++ else if (strcmp(str, "power_off") == 0) {
++ action = "power_off";
++ }
++ else if (strcmp(str, "pre_smi") == 0) {
++ preaction = "pre_smi";
++ }
++#ifdef HAVE_NMI_HANDLER
++ else if (strcmp(str, "pre_nmi") == 0) {
++ preaction = "pre_nmi";
++ }
++#endif
++ else if (strcmp(str, "pre_int") == 0) {
++ preaction = "pre_int";
++ }
++ else if (strcmp(str, "start_now") == 0) {
++ start_now = 1;
++ } else {
++ printk("Unknown IPMI watchdog option: '%s'\n", str);
++ }
++ }
++
++ return 1;
++}
++__setup("ipmi_wdog=", ipmi_wdog_setup);
++#endif
++
++EXPORT_SYMBOL(ipmi_delayed_shutdown);
++
++module_init(ipmi_wdog_init);
++MODULE_LICENSE("GPL");
+diff -urN linux.orig/include/asm-i386/apic.h linux/include/asm-i386/apic.h
+--- linux.orig/include/asm-i386/apic.h Mon Oct 21 13:26:04 2002
++++ linux/include/asm-i386/apic.h Tue Oct 22 12:40:16 2002
+@@ -79,7 +79,6 @@
+ extern void setup_boot_APIC_clock (void);
+ extern void setup_secondary_APIC_clock (void);
+ extern void setup_apic_nmi_watchdog (void);
+-extern inline void nmi_watchdog_tick (struct pt_regs * regs);
+ extern int APIC_init_uniprocessor (void);
+ extern void disable_APIC_timer(void);
+ extern void enable_APIC_timer(void);
+diff -urN linux.orig/include/asm-i386/nmi.h linux/include/asm-i386/nmi.h
+--- linux.orig/include/asm-i386/nmi.h Mon Oct 21 13:25:52 2002
++++ linux/include/asm-i386/nmi.h Thu Oct 24 20:50:22 2002
+@@ -5,26 +5,11 @@
+ #define ASM_NMI_H
+
+ #include <linux/pm.h>
++#include <linux/rcupdate.h>
++#include <linux/sched.h>
+
+ struct pt_regs;
+
+-typedef int (*nmi_callback_t)(struct pt_regs * regs, int cpu);
+-
+-/**
+- * set_nmi_callback
+- *
+- * Set a handler for an NMI. Only one handler may be
+- * set. Return 1 if the NMI was handled.
+- */
+-void set_nmi_callback(nmi_callback_t callback);
+-
+-/**
+- * unset_nmi_callback
+- *
+- * Remove the handler previously set.
+- */
+-void unset_nmi_callback(void);
+-
+ #ifdef CONFIG_PM
+
+ /** Replace the PM callback routine for NMI. */
+@@ -45,5 +30,34 @@
+ }
+
+ #endif /* CONFIG_PM */
++
++
++/**
++ * Register a handler to get called when an NMI occurs. If the
++ * handler actually handles the NMI, it should return NOTIFY_OK. If
++ * it did not handle the NMI, it should return NOTIFY_DONE. It may "or"
++ * on NOTIFY_STOP_MASK to the return value if it does not want other
++ * handlers after it to be notified.
++ */
++#define HAVE_NMI_HANDLER 1
++struct nmi_handler
++{
++ struct list_head link; /* You must init this before use. */
++
++ char *dev_name;
++ void *dev_id;
++ int (*handler)(void *dev_id, struct pt_regs *regs, int cpu, int handled);
++ int priority; /* Handlers called in priority order. */
++
++ /* Don't mess with anything below here. */
++
++ struct rcu_head rcu;
++ struct completion complete;
++};
++
++int request_nmi(struct nmi_handler *handler);
++
++/* Release will block until the handler is completely free. */
++void release_nmi(struct nmi_handler *handler);
+
+ #endif /* ASM_NMI_H */
+diff -urN linux.orig/include/linux/ipmi.h linux/include/linux/ipmi.h
+--- linux.orig/include/linux/ipmi.h Wed Dec 31 18:00:00 1969
++++ linux/include/linux/ipmi.h Wed Oct 30 13:51:55 2002
+@@ -0,0 +1,516 @@
++/*
++ * ipmi.h
++ *
++ * MontaVista IPMI interface
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __LINUX_IPMI_H
++#define __LINUX_IPMI_H
++
++#include <linux/ipmi_msgdefs.h>
++
++/*
++ * This file describes an interface to an IPMI driver. You have to
++ * have a fairly good understanding of IPMI to use this, so go read
++ * the specs first before actually trying to do anything.
++ *
++ * With that said, this driver provides a multi-user interface to the
++ * IPMI driver, and it allows multiple IPMI physical interfaces below
++ * the driver. The physical interfaces bind as a lower layer on the
++ * driver. They appear as interfaces to the application using this
++ * interface.
++ *
++ * Multi-user means that multiple applications may use the driver,
++ * send commands, receive responses, etc. The driver keeps track of
++ * commands the user sends and tracks the responses. The responses
++ * will go back to the application that send the command. If the
++ * response doesn't come back in time, the driver will return a
++ * timeout error response to the application. Asynchronous events
++ * from the BMC event queue will go to all users bound to the driver.
++ * The incoming event queue in the BMC will automatically be flushed
++ * if it becomes full and it is queried once a second to see if
++ * anything is in it. Incoming commands to the driver will get
++ * delivered as commands.
++ *
++ * This driver provides two main interfaces: one for in-kernel
++ * applications and another for userland applications. The
++ * capabilities are basically the same for both interface, although
++ * the interfaces are somewhat different. The stuff in the
++ * #ifdef KERNEL below is the in-kernel interface. The userland
++ * interface is defined later in the file. */
++
++
++
++/*
++ * This is an overlay for all the address types, so it's easy to
++ * determine the actual address type. This is kind of like addresses
++ * work for sockets.
++ */
++#define IPMI_MAX_ADDR_SIZE 32
++struct ipmi_addr
++{
++ /* Try to take these from the "Channel Medium Type" table
++ in section 6.5 of the IPMI 1.5 manual. */
++ int addr_type;
++ short channel;
++ char data[IPMI_MAX_ADDR_SIZE];
++};
++
++/*
++ * When the address is not used, the type will be set to this value.
++ * The channel is the BMC's channel number for the channel (usually
++ * 0), or IPMC_BMC_CHANNEL if communicating directly with the BMC.
++ */
++#define IPMI_SYSTEM_INTERFACE_ADDR_TYPE 0x0c
++struct ipmi_system_interface_addr
++{
++ int addr_type;
++ short channel;
++ unsigned char lun;
++};
++
++/* An IPMB Address. */
++#define IPMI_IPMB_ADDR_TYPE 0x01
++/* Used for broadcast get device id as described in section 17.9 of the
++ IPMI 1.5 manual. */
++#define IPMI_IPMB_BROADCAST_ADDR_TYPE 0x41
++struct ipmi_ipmb_addr
++{
++ int addr_type;
++ short channel;
++ unsigned char slave_addr;
++ unsigned char lun;
++};
++
++
++/*
++ * Channel for talking directly with the BMC. When using this
++ * channel, This is for the system interface address type only. FIXME
++ * - is this right, or should we use -1?
++ */
++#define IPMI_BMC_CHANNEL 0xf
++#define IPMI_NUM_CHANNELS 0x10
++
++
++/*
++ * A raw IPMI message without any addressing. This covers both
++ * commands and responses. The completion code is always the first
++ * byte of data in the response (as the spec shows the messages laid
++ * out).
++ */
++struct ipmi_msg
++{
++ unsigned char netfn;
++ unsigned char cmd;
++ unsigned short data_len;
++ unsigned char *data;
++};
++
++/*
++ * Various defines that are useful for IPMI applications.
++ */
++#define IPMI_INVALID_CMD_COMPLETION_CODE 0xC1
++#define IPMI_TIMEOUT_COMPLETION_CODE 0xC3
++#define IPMI_UNKNOWN_ERR_COMPLETION_CODE 0xff
++
++
++/*
++ * Receive types for messages coming from the receive interface. This
++ * is used for the receive in-kernel interface and in the receive
++ * IOCTL.
++ */
++#define IPMI_RESPONSE_RECV_TYPE 1 /* A response to a command */
++#define IPMI_ASYNC_EVENT_RECV_TYPE 2 /* Something from the event queue */
++#define IPMI_CMD_RECV_TYPE 3 /* A command from somewhere else */
++/* Note that async events and received commands do not have a completion
++ code as the first byte of the incoming data, unlike a response. */
++
++
++
++#ifdef __KERNEL__
++
++/*
++ * The in-kernel interface.
++ */
++#include <linux/list.h>
++
++/* Opaque type for a IPMI message user. One of these is needed to
++ send and receive messages. */
++typedef struct ipmi_user *ipmi_user_t;
++
++/*
++ * Stuff coming from the recieve interface comes as one of these.
++ * They are allocated, the receiver must free them with
++ * ipmi_free_recv_msg() when done with the message. The link is not
++ * used after the message is delivered, so the upper layer may use the
++ * link to build a linked list, if it likes.
++ */
++struct ipmi_recv_msg
++{
++ struct list_head link;
++
++ /* The type of message as defined in the "Receive Types"
++ defines above. */
++ int recv_type;
++
++ ipmi_user_t user;
++ struct ipmi_addr addr;
++ long msgid;
++ struct ipmi_msg msg;
++
++ /* Call this when done with the message. It will presumably free
++ the message and do any other necessary cleanup. */
++ void (*done)(struct ipmi_recv_msg *msg);
++
++ /* Place-holder for the data, don't make any assumptions about
++ the size or existance of this, since it may change. */
++ unsigned char msg_data[IPMI_MAX_MSG_LENGTH];
++};
++
++/* Allocate and free the receive message. */
++static inline void ipmi_free_recv_msg(struct ipmi_recv_msg *msg)
++{
++ msg->done(msg);
++}
++struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
++
++struct ipmi_user_hndl
++{
++ /* Routine type to call when a message needs to be routed to
++ the upper layer. This will be called with some locks held,
++ the only IPMI routines that can be called are ipmi_request
++ and the alloc/free operations. */
++ void (*ipmi_recv_hndl)(struct ipmi_recv_msg *msg,
++ void *handler_data);
++
++ /* Called when the interface detects a watchdog pre-timeout. If
++ this is NULL, it will be ignored for the user. */
++ void (*ipmi_watchdog_pretimeout)(void *handler_data);
++};
++
++/* Create a new user of the IPMI layer on the given interface number. */
++int ipmi_create_user(unsigned int if_num,
++ struct ipmi_user_hndl *handler,
++ void *handler_data,
++ ipmi_user_t *user);
++
++/* Destroy the given user of the IPMI layer. */
++int ipmi_destroy_user(ipmi_user_t user);
++
++/* Get the IPMI version of the BMC we are talking to. */
++void ipmi_get_version(ipmi_user_t user,
++ unsigned char *major,
++ unsigned char *minor);
++
++/* Set and get the slave address and LUN that we will use for our
++ source messages. Note that this affects the interface, not just
++ this user, so it will affect all users of this interface. This is
++ so some initialization code can come in and do the OEM-specific
++ things it takes to determine your address (if not the BMC) and set
++ it for everyone else. */
++void ipmi_set_my_address(ipmi_user_t user,
++ unsigned char address);
++unsigned char ipmi_get_my_address(ipmi_user_t user);
++void ipmi_set_my_LUN(ipmi_user_t user,
++ unsigned char LUN);
++unsigned char ipmi_get_my_LUN(ipmi_user_t user);
++
++/*
++ * Send a command request from the given user. The address is the
++ * proper address for the channel type. If this is a command, then
++ * the message response comes back, the receive handler for this user
++ * will be called with the given msgid value in the recv msg. If this
++ * is a response to a command, then the msgid will be used as the
++ * sequence number for the response (truncated if necessary), so when
++ * sending a response you should use the sequence number you received
++ * in the msgid field of the received command. If the priority is >
++ * 0, the message will go into a high-priority queue and be sent
++ * first. Otherwise, it goes into a normal-priority queue.
++ */
++int ipmi_request(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ int priority);
++
++/*
++ * Like ipmi_request, but lets you specify the slave return address.
++ */
++int ipmi_request_with_source(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ int priority,
++ unsigned char source_address,
++ unsigned char source_lun);
++
++/*
++ * Like ipmi_request, but with messages supplied. This will not
++ * allocate any memory, and the messages may be statically allocated
++ * (just make sure to do the "done" handling on them). Note that this
++ * is primarily for the watchdog timer, since it should be able to
++ * send messages even if no memory is available. This is subject to
++ * change as the system changes, so don't use it unless you REALLY
++ * have to.
++ */
++int ipmi_request_supply_msgs(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ void *supplied_smi,
++ struct ipmi_recv_msg *supplied_recv,
++ int priority);
++
++/*
++ * When commands come in to the SMS, the user can register to receive
++ * them. Only one user can be listening on a specific netfn/cmd pair
++ * at a time, you will get an EBUSY error if the command is already
++ * registered. If a command is received that does not have a user
++ * registered, the driver will automatically return the proper
++ * error.
++ */
++int ipmi_register_for_cmd(ipmi_user_t user,
++ unsigned char netfn,
++ unsigned char cmd);
++int ipmi_unregister_for_cmd(ipmi_user_t user,
++ unsigned char netfn,
++ unsigned char cmd);
++
++/*
++ * When the user is created, it will not receive IPMI events by
++ * default. The user must set this to TRUE to get incoming events.
++ * The first user that sets this to TRUE will receive all events that
++ * have been queued while no one was waiting for events.
++ */
++int ipmi_set_gets_events(ipmi_user_t user, int val);
++
++/*
++ * Register the given user to handle all received IPMI commands. This
++ * will fail if anyone is registered as a command receiver or if
++ * another is already registered to receive all commands. NOTE THAT
++ * THIS IS FOR EMULATION USERS ONLY, DO NOT USER THIS FOR NORMAL
++ * STUFF.
++ */
++int ipmi_register_all_cmd_rcvr(ipmi_user_t user);
++int ipmi_unregister_all_cmd_rcvr(ipmi_user_t user);
++
++
++/*
++ * Called when a new SMI is registered. This will also be called on
++ * every existing interface when a new watcher is registered with
++ * ipmi_smi_watcher_register().
++ */
++struct ipmi_smi_watcher
++{
++ struct list_head link;
++
++ /* These two are called with read locks held for the interface
++ the watcher list. So you can add and remove users from the
++ IPMI interface, send messages, etc., but you cannot add
++ or remove SMI watchers or SMI interfaces. */
++ void (*new_smi)(int if_num);
++ void (*smi_gone)(int if_num);
++};
++
++int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher);
++int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher);
++
++/* The following are various helper functions for dealing with IPMI
++ addresses. */
++
++/* Return the maximum length of an IPMI address given it's type. */
++unsigned int ipmi_addr_length(int addr_type);
++
++/* Validate that the given IPMI address is valid. */
++int ipmi_validate_addr(struct ipmi_addr *addr, int len);
++
++/* Return 1 if the given addresses are equal, 0 if not. */
++int ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2);
++
++#endif /* __KERNEL__ */
++
++
++/*
++ * The userland interface
++ */
++
++/*
++ * The userland interface for the IPMI driver is a standard character
++ * device, with each instance of an interface registered as a minor
++ * number under the major character device.
++ *
++ * The read and write calls do not work, to get messages in and out
++ * requires ioctl calls because of the complexity of the data. select
++ * and poll do work, so you can wait for input using the file
++ * descriptor, you just can use read to get it.
++ *
++ * In general, you send a command down to the interface and receive
++ * responses back. You can use the msgid value to correlate commands
++ * and responses, the driver will take care of figuring out which
++ * incoming messages are for which command and find the proper msgid
++ * value to report. You will only receive reponses for commands you
++ * send. Asynchronous events, however, go to all open users, so you
++ * must be ready to handle these (or ignore them if you don't care).
++ *
++ * The address type depends upon the channel type. When talking
++ * directly to the BMC (IPMC_BMC_CHANNEL), the address is ignored
++ * (IPMI_UNUSED_ADDR_TYPE). When talking to an IPMB channel, you must
++ * supply a valid IPMB address with the addr_type set properly.
++ *
++ * When talking to normal channels, the driver takes care of the
++ * details of formatting and sending messages on that channel. You do
++ * not, for instance, have to format a send command, you just send
++ * whatever command you want to the channel, the driver will create
++ * the send command, automatically issue receive command and get even
++ * commands, and pass those up to the proper user.
++ */
++
++
++/* The magic IOCTL value for this interface. */
++#define IPMI_IOC_MAGIC 'i'
++
++
++/* Messages sent to the interface are this format. */
++struct ipmi_req
++{
++ unsigned char *addr; /* Address to send the message to. */
++ unsigned int addr_len;
++
++ long msgid; /* The sequence number for the message. This
++ exact value will be reported back in the
++ response to this request if it is a command.
++ If it is a response, this will be used as
++ the sequence value for the response. */
++
++ struct ipmi_msg msg;
++};
++/*
++ * Send a message to the interfaces. error values are:
++ * - EFAULT - an address supplied was invalid.
++ * - EINVAL - The address supplied was not valid, or the command
++ * was not allowed.
++ * - EMSGSIZE - The message to was too large.
++ * - ENOMEM - Buffers could not be allocated for the command.
++ */
++#define IPMICTL_SEND_COMMAND _IOR(IPMI_IOC_MAGIC, 13, \
++ struct ipmi_req)
++
++/* Messages received from the interface are this format. */
++struct ipmi_recv
++{
++ int recv_type; /* Is this a command, response or an
++ asyncronous event. */
++
++ unsigned char *addr; /* Address the message was from is put
++ here. The caller must supply the
++ memory. */
++ unsigned int addr_len; /* The size of the address buffer.
++ The caller supplies the full buffer
++ length, this value is updated to
++ the actual message length when the
++ message is received. */
++
++ long msgid; /* The sequence number specified in the request
++ if this is a response. If this is a command,
++ this will be the sequence number from the
++ command. */
++
++ struct ipmi_msg msg; /* The data field must point to a buffer.
++ The data_size field must be set to the
++ size of the message buffer. The
++ caller supplies the full buffer
++ length, this value is updated to the
++ actual message length when the message
++ is received. */
++};
++
++/*
++ * Receive a message. error values:
++ * - EAGAIN - no messages in the queue.
++ * - EFAULT - an address supplied was invalid.
++ * - EINVAL - The address supplied was not valid.
++ * - EMSGSIZE - The message to was too large to fit into the message buffer,
++ * the message will be left in the buffer. */
++#define IPMICTL_RECEIVE_MSG _IOWR(IPMI_IOC_MAGIC, 12, \
++ struct ipmi_recv)
++
++/*
++ * Like RECEIVE_MSG, but if the message won't fit in the buffer, it
++ * will truncate the contents instead of leaving the data in the
++ * buffer.
++ */
++#define IPMICTL_RECEIVE_MSG_TRUNC _IOWR(IPMI_IOC_MAGIC, 11, \
++ struct ipmi_recv)
++
++/* Register to get commands from other entities on this interface. */
++struct ipmi_cmdspec
++{
++ unsigned char netfn;
++ unsigned char cmd;
++};
++
++/*
++ * Register to receive a specific command. error values:
++ * - EFAULT - an address supplied was invalid.
++ * - EBUSY - The netfn/cmd supplied was already in use.
++ * - ENOMEM - could not allocate memory for the entry.
++ */
++#define IPMICTL_REGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 14, \
++ struct ipmi_cmdspec)
++/*
++ * Unregister a regsitered command. error values:
++ * - EFAULT - an address supplied was invalid.
++ * - ENOENT - The netfn/cmd was not found registered for this user.
++ */
++#define IPMICTL_UNREGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 15, \
++ struct ipmi_cmdspec)
++
++/*
++ * Set whether this interface receives events. Note that the first
++ * user registered for events will get all pending events for the
++ * interface. error values:
++ * - EFAULT - an address supplied was invalid.
++ */
++#define IPMICTL_SET_GETS_EVENTS_CMD _IOR(IPMI_IOC_MAGIC, 16, int)
++
++/*
++ * Set and get the slave address and LUN that we will use for our
++ * source messages. Note that this affects the interface, not just
++ * this user, so it will affect all users of this interface. This is
++ * so some initialization code can come in and do the OEM-specific
++ * things it takes to determine your address (if not the BMC) and set
++ * it for everyone else. You should probably leave the LUN alone.
++ */
++#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)
++#define IPMICTL_SET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 19, unsigned int)
++#define IPMICTL_GET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 20, unsigned int)
++
++#endif /* __LINUX_IPMI_H */
+diff -urN linux.orig/include/linux/ipmi_msgdefs.h linux/include/linux/ipmi_msgdefs.h
+--- linux.orig/include/linux/ipmi_msgdefs.h Wed Dec 31 18:00:00 1969
++++ linux/include/linux/ipmi_msgdefs.h Thu Aug 22 08:26:11 2002
+@@ -0,0 +1,58 @@
++/*
++ * ipmi_smi.h
++ *
++ * MontaVista IPMI system management interface
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __LINUX_IPMI_MSGDEFS_H
++#define __LINUX_IPMI_MSGDEFS_H
++
++/* Various definitions for IPMI messages used by almost everything in
++ the IPMI stack. */
++
++#define IPMI_NETFN_APP_REQUEST 0x06
++#define IPMI_NETFN_APP_RESPONSE 0x07
++
++#define IPMI_BMC_SLAVE_ADDR 0x20
++
++#define IPMI_GET_DEVICE_ID_CMD 0x01
++
++#define IPMI_CLEAR_MSG_FLAGS_CMD 0x30
++#define IPMI_GET_MSG_FLAGS_CMD 0x31
++#define IPMI_SEND_MSG_CMD 0x34
++#define IPMI_GET_MSG_CMD 0x33
++
++#define IPMI_SET_BMC_GLOBAL_ENABLES_CMD 0x2e
++#define IPMI_GET_BMC_GLOBAL_ENABLES_CMD 0x2f
++#define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35
++
++#define IPMI_MAX_MSG_LENGTH 80
++
++#endif /* __LINUX_IPMI_MSGDEFS_H */
+diff -urN linux.orig/include/linux/ipmi_smi.h linux/include/linux/ipmi_smi.h
+--- linux.orig/include/linux/ipmi_smi.h Wed Dec 31 18:00:00 1969
++++ linux/include/linux/ipmi_smi.h Sun Oct 13 16:25:50 2002
+@@ -0,0 +1,143 @@
++/*
++ * ipmi_smi.h
++ *
++ * MontaVista IPMI system management interface
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __LINUX_IPMI_SMI_H
++#define __LINUX_IPMI_SMI_H
++
++#include <linux/ipmi_msgdefs.h>
++
++/* This files describes the interface for IPMI system management interface
++ drivers to bind into the IPMI message handler. */
++
++/* Structure for the low-level drivers. */
++typedef struct ipmi_smi *ipmi_smi_t;
++
++/*
++ * Messages to/from the lower layer. The smi interface will take one
++ * of these to send. After the send has occurred and a response has
++ * been received, it will report this same data structure back up to
++ * the upper layer. If an error occurs, it should fill in the
++ * response with an error code in the completion code location. When
++ * asyncronous data is received, one of these is allocated, the
++ * data_size is set to zero and the response holds the data from the
++ * get message or get event command that the interface initiated.
++ * Note that it is the interfaces responsibility to detect
++ * asynchronous data and messages and request them from the
++ * interface.
++ */
++struct ipmi_smi_msg
++{
++ struct list_head link;
++
++ long msgid;
++ void *user_data;
++
++ /* If 0, add to the end of the queue. If 1, add to the beginning. */
++ int prio;
++
++ int data_size;
++ unsigned char data[IPMI_MAX_MSG_LENGTH];
++
++ int rsp_size;
++ unsigned char rsp[IPMI_MAX_MSG_LENGTH];
++
++ /* Will be called when the system is done with the message
++ (presumably to free it). */
++ void (*done)(struct ipmi_smi_msg *msg);
++};
++
++struct ipmi_smi_handlers
++{
++ /* Called to enqueue an SMI message to be sent. This
++ operation is not allowed to fail. If an error occurs, it
++ should report back the error in a received message. It may
++ do this in the current call context, since no write locks
++ are held when this is run. If the priority is > 0, the
++ message will go into a high-priority queue and be sent
++ first. Otherwise, it goes into a normal-priority queue. */
++ void (*sender)(void *send_info,
++ struct ipmi_smi_msg *msg,
++ int priority);
++
++ /* Called by the upper layer to request that we try to get
++ events from the BMC we are attached to. */
++ void (*request_events)(void *send_info);
++
++ /* Called when someone is using the interface, so the module can
++ adjust it's use count. */
++ void (*new_user)(void *send_info);
++
++ /* Called when someone is no longer using the interface, so the
++ module can adjust it's use count. */
++ void (*user_left)(void *send_info);
++
++ /* Called when the interface should go into "run to
++ completion" mode. If this call sets the value to true, the
++ interface should make sure that all messages are flushed
++ out and that none are pending, and any new requests are run
++ to completion immediately. */
++ void (*set_run_to_completion)(void *send_info, int run_to_completion);
++};
++
++/* Add a low-level interface to the IPMI driver. */
++int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
++ void *send_info,
++ unsigned char version_major,
++ unsigned char version_minor,
++ ipmi_smi_t *intf);
++
++/*
++ * Remove a low-level interface from the IPMI driver. This will
++ * return an error if the interface is still in use by a user.
++ */
++int ipmi_unregister_smi(ipmi_smi_t intf);
++
++/*
++ * The lower layer reports received messages through this interface.
++ * The data_size should be zero if this is an asyncronous message. If
++ * the lower layer gets an error sending a message, it should format
++ * an error response in the message response.
++ */
++void ipmi_smi_msg_received(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg);
++
++/* The lower layer received a watchdog pre-timeout on interface. */
++void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf);
++
++struct ipmi_smi_msg *ipmi_alloc_smi_msg(void);
++static inline void ipmi_free_smi_msg(struct ipmi_smi_msg *msg)
++{
++ msg->done(msg);
++}
++
++#endif /* __LINUX_IPMI_SMI_H */
+diff -urN linux.orig/include/linux/nmi.h linux/include/linux/nmi.h
+--- linux.orig/include/linux/nmi.h Thu Jun 20 17:53:40 2002
++++ linux/include/linux/nmi.h Thu Oct 24 16:28:53 2002
+@@ -1,22 +1,11 @@
+ /*
+- * linux/include/linux/nmi.h
++ * linux/include/linux/nmi.h
++ *
++ * (C) 2002 Corey Minyard <cminyard@mvista.com>
++ *
++ * Include file for NMI handling.
+ */
+-#ifndef LINUX_NMI_H
+-#define LINUX_NMI_H
+-
+-#include <asm/irq.h>
+-
+-/**
+- * touch_nmi_watchdog - restart NMI watchdog timeout.
+- *
+- * If the architecture supports the NMI watchdog, touch_nmi_watchdog()
+- * may be used to reset the timeout - for code which intentionally
+- * disables interrupts for a long time. This call is stateless.
+- */
+-#ifdef ARCH_HAS_NMI_WATCHDOG
+-extern void touch_nmi_watchdog(void);
+-#else
+-# define touch_nmi_watchdog() do { } while(0)
+-#endif
+
++#if defined(__i386__)
++#include <asm/nmi.h>
+ #endif
+diff -urN linux.orig/include/linux/nmi_watchdog.h linux/include/linux/nmi_watchdog.h
+--- linux.orig/include/linux/nmi_watchdog.h Thu Oct 24 19:56:54 2002
++++ linux/include/linux/nmi_watchdog.h Thu Oct 24 12:50:30 2002
+@@ -0,0 +1,22 @@
++/*
++ * linux/include/linux/nmi.h
++ */
++#ifndef LINUX_NMI_WATCHDOG_H
++#define LINUX_NMI_WATCHDOG_H
++
++#include <asm/irq.h>
++
++/**
++ * touch_nmi_watchdog - restart NMI watchdog timeout.
++ *
++ * If the architecture supports the NMI watchdog, touch_nmi_watchdog()
++ * may be used to reset the timeout - for code which intentionally
++ * disables interrupts for a long time. This call is stateless.
++ */
++#ifdef ARCH_HAS_NMI_WATCHDOG
++extern void touch_nmi_watchdog(void);
++#else
++# define touch_nmi_watchdog() do { } while(0)
++#endif
++
++#endif
diff --git a/kern/linux-ipmi-emu-2.4.20-v17.diff b/kern/linux-ipmi-emu-2.4.20-v17.diff
new file mode 100644
index 0000000..2d0fa40
--- /dev/null
+++ b/kern/linux-ipmi-emu-2.4.20-v17.diff
@@ -0,0 +1,2776 @@
+diff -urN linux/Documentation/Configure.help linux-emu/Documentation/Configure.help
+--- linux/Documentation/Configure.help Fri Dec 6 09:12:27 2002
++++ linux-emu/Documentation/Configure.help Fri Jan 10 11:24:14 2003
+@@ -26267,6 +26267,17 @@
+ CONFIG_IPMI_WATCHDOG
+ This enables the IPMI watchdog timer.
+
++Emulate Radisys IPMI driver
++CONFIG_IPMI_EMULATE_RADISYS
++ This enables emulation of the Radisys IPMI device driver.
++
++Emulate Intel IBM driver
++CONFIG_IPMI_EMULATE_IMB
++ This enables emulation of the Intel IMB device driver. Note that you
++ MUST have the IPMI watchdog timer enabled to use this. This code
++ uses some of the watchdog code, but the dependency is not enforced
++ by config.
++
+ #
+ # A couple of things I keep forgetting:
+ # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
+--- linux/drivers/char/Config.in Fri Dec 6 09:12:38 2002
++++ linux-emu/drivers/char/Config.in Fri Jan 10 11:24:14 2003
+@@ -195,6 +195,8 @@
+ dep_tristate ' Device interface for IPMI' CONFIG_IPMI_DEVICE_INTERFACE $CONFIG_IPMI_HANDLER
+ dep_tristate ' IPMI KCS handler' CONFIG_IPMI_KCS $CONFIG_IPMI_HANDLER
+ dep_tristate ' IPMI Watchdog Timer' CONFIG_IPMI_WATCHDOG $CONFIG_IPMI_HANDLER
++dep_tristate ' Emulate Radisys IPMI driver' CONFIG_IPMI_EMULATE_RADISYS $CONFIG_IPMI_HANDLER
++dep_tristate ' Emulate Intel IMB driver' CONFIG_IPMI_EMULATE_IMB $CONFIG_IPMI_WATCHDOG
+
+ mainmenu_option next_comment
+ comment 'Watchdog Cards'
+diff -urN linux/drivers/char/ipmi/Makefile linux-emu/drivers/char/ipmi/Makefile
+--- linux/drivers/char/ipmi/Makefile Thu Aug 22 16:58:48 2002
++++ linux-emu/drivers/char/ipmi/Makefile Fri Jan 10 11:24:14 2003
+@@ -13,6 +13,8 @@
+ obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
+ obj-$(CONFIG_IPMI_KCS) += ipmi_kcs_drv.o
+ obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
++obj-$(CONFIG_IPMI_EMULATE_RADISYS) += ipmi_radisys.o
++obj-$(CONFIG_IPMI_EMULATE_IMB) += ipmi_imb.o
+
+ include $(TOPDIR)/Rules.make
+
+diff -urN linux/drivers/char/ipmi/ipmi_imb.c linux-emu/drivers/char/ipmi/ipmi_imb.c
+--- linux/drivers/char/ipmi/ipmi_imb.c Wed Dec 31 18:00:00 1969
++++ linux-emu/drivers/char/ipmi/ipmi_imb.c Fri Jan 10 11:24:37 2003
+@@ -0,0 +1,744 @@
++/*
++ * ipmi_imb.c
++ *
++ * Intel IMB emulation for the IPMI interface.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <asm/system.h>
++#include <linux/sched.h>
++#include <linux/poll.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/devfs_fs_kernel.h>
++#include <linux/ipmi.h>
++#include <linux/ipmi_imb.h>
++
++
++
++#define MAX_BUFFER_SIZE 64
++#define BMC_SA 0x20
++
++struct priv_data
++{
++ /* This is for supporting the old Imb interface. */
++ ipmi_user_t imb_user;
++ spinlock_t imb_lock;
++
++ unsigned long curr_msgid;
++
++ /* A list of responses in the queue. */
++ struct list_head imb_waiting_rsps;
++
++ /* A list of things waiting for responses. We wake them all up
++ when a response comes in. */
++ wait_queue_head_t imb_waiting_rsp_rcvrs;
++
++ /* A list of commands that have come in. */
++ struct list_head imb_waiting_cmds;
++
++ /* A list of thing waiting for commands. We wake them all up
++ when a command comes in. */
++ wait_queue_head_t imb_waiting_cmd_rcvrs;
++
++ /* The registered command receiver value. This only allows someone
++ with the "magic number" to issue commands. */
++ unsigned long imb_cmd_receiver;
++
++ /* Is someone already waiting for a command? The Imb driver
++ only allows one waiter, this enforces that. */
++ int imb_cmd_waiting;
++
++ /* A list of IPMI events waiting to be delivered. (not that
++ the Imb driver calls incoming commands "events", this
++ variable is actual IPMI events, not incoming commands). */
++ struct list_head imb_waiting_events;
++
++#define IMB_EVENT_QUEUE_LIMIT 16 /* Allow up to 16 events. */
++ /* The number of events in the event queue. */
++ unsigned int imb_waiting_event_count;
++};
++
++static devfs_handle_t devfs_handle;
++
++
++/* We cheat and use a piece of the address as the timeout. */
++static long *imb_timeout(struct ipmi_recv_msg *msg)
++{
++ char *base = (char *) &(msg->addr);
++ base += sizeof(struct ipmi_ipmb_addr);
++ return (long *) base;
++}
++
++static void imb_msg_recv(struct ipmi_recv_msg *msg,
++ void *data)
++{
++ struct priv_data *priv = data;
++ unsigned long flags;
++
++ spin_lock_irqsave(&(priv->imb_lock), flags);
++ if (msg->recv_type == IPMI_RESPONSE_RECV_TYPE) {
++ *imb_timeout(msg) = 5000;
++ list_add_tail(&(msg->link), &(priv->imb_waiting_rsps));
++ wake_up_all(&(priv->imb_waiting_rsp_rcvrs));
++ } else if (msg->recv_type == IPMI_CMD_RECV_TYPE) {
++ *imb_timeout(msg) = 5000;
++ list_add_tail(&(msg->link), &(priv->imb_waiting_cmds));
++ wake_up_all(&(priv->imb_waiting_cmd_rcvrs));
++ } else if (msg->recv_type == IPMI_ASYNC_EVENT_RECV_TYPE) {
++ if (priv->imb_waiting_event_count > IMB_EVENT_QUEUE_LIMIT) {
++ ipmi_free_recv_msg(msg);
++ } else {
++ list_add_tail(&(msg->link),&(priv->imb_waiting_events));
++ (priv->imb_waiting_event_count)++;
++ }
++ } else {
++ ipmi_free_recv_msg(msg);
++ }
++ spin_unlock_irqrestore(&(priv->imb_lock), flags);
++}
++
++/* We emulate the event queue in the driver for the imb emulation. */
++static int imb_handle_event_request(struct priv_data *priv,
++ struct ipmi_recv_msg **rsp)
++{
++ struct list_head *entry;
++ unsigned long flags;
++ struct ipmi_recv_msg *msg = NULL;
++ int rv = 0;
++
++ spin_lock_irqsave(&(priv->imb_lock), flags);
++ if (list_empty(&(priv->imb_waiting_events))) {
++ /* Nothing in the event queue, just return an error. */
++ msg = ipmi_alloc_recv_msg();
++ if (msg == NULL) {
++ rv = -EAGAIN;
++ goto out_err;
++ }
++ msg->addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ msg->addr.channel = IPMI_BMC_CHANNEL;
++ msg->msg.cmd = IPMI_READ_EVENT_MSG_BUFFER_CMD;
++ msg->msgid = 0;
++ msg->recv_type = IPMI_ASYNC_EVENT_RECV_TYPE;
++ msg->msg.netfn = IPMI_NETFN_APP_RESPONSE;
++ msg->msg.data = msg->msg_data;
++ msg->msg.data[0] = 0x80; /* Data not available. */
++ msg->msg.data_len = 1;
++ } else {
++ /* Pull an item from the event queue . */
++ entry = priv->imb_waiting_events.next;
++ list_del(entry);
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ (priv->imb_waiting_event_count)--;
++ }
++
++ *rsp = msg;
++
++ out_err:
++ spin_unlock_irqrestore(&(priv->imb_lock), flags);
++ return rv;
++}
++
++static struct priv_data *ipmi_user;
++static unsigned int user_count = 0; /* How many users have this open. */
++static spinlock_t dev_lock = SPIN_LOCK_UNLOCKED;
++
++static int ipmi_imb_open(struct inode *inode, struct file *file)
++{
++ int rv;
++
++ if (user_count == 0) {
++ rv = ipmi_register_all_cmd_rcvr(ipmi_user->imb_user);
++ if (rv) {
++ return rv;
++ }
++ }
++
++ file->private_data = ipmi_user;
++ spin_lock(&dev_lock);
++ if (user_count == 0)
++ ipmi_set_gets_events(ipmi_user->imb_user, 1);
++ user_count++;
++ spin_unlock(&dev_lock);
++
++ return 0;
++}
++
++static int ipmi_imb_release(struct inode *inode, struct file *file)
++{
++ spin_lock(&dev_lock);
++ user_count--;
++ if (user_count == 0) {
++ ipmi_set_gets_events(ipmi_user->imb_user, 0);
++ ipmi_unregister_all_cmd_rcvr(ipmi_user->imb_user);
++ }
++ spin_unlock(&dev_lock);
++ return 0;
++}
++
++static unsigned char
++ipmb_checksum(unsigned char *data, int size)
++{
++ unsigned char csum = 0;
++
++ for (; size > 0; size--, data++)
++ csum += *data;
++
++ return -csum;
++}
++
++extern void ipmi_delayed_shutdown(long delay, int power_off);
++
++static int ipmi_imb_ioctl(struct inode *inode,
++ struct file *file,
++ unsigned int cmd,
++ unsigned long data)
++{
++ struct priv_data *priv = file->private_data;
++ int rv = -EINVAL;
++ struct smi smi;
++ unsigned long flags;
++
++ if (copy_from_user((caddr_t)&smi, (caddr_t)data, sizeof(smi))) {
++ return -EFAULT;
++ }
++
++ switch(cmd) {
++ case IOCTL_IMB_POLL_ASYNC:
++ /*
++ * No-op for this, the low-level driver polls.
++ */
++ break;
++
++ case IOCTL_IMB_GET_ASYNC_MSG:
++ {
++ unsigned char resp[MAX_ASYNC_RESP_SIZE];
++ struct ipmi_recv_msg *msg = NULL;
++ ImbAsyncResponse *pAsyncResp = (ImbAsyncResponse *) resp;
++ unsigned long length = 0;
++
++ if (smi.cbInBuffer < sizeof(ImbAsyncRequest))
++ return -EINVAL;
++ if (smi.cbOutBuffer < MIN_ASYNC_RESP_SIZE)
++ return -EINVAL;
++
++ spin_lock_irqsave(&(priv->imb_lock), flags);
++
++ if (list_empty(&(priv->imb_waiting_cmds))) {
++ /* No command waiting, just return an error. */
++ rv = IMB_NO_ASYNC_MSG;
++ } else {
++ struct list_head *entry;
++
++ /* Got a command, pull it out and handle it. */
++ entry = priv->imb_waiting_cmds.next;
++ list_del(entry);
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ rv = STATUS_SUCCESS;
++ }
++ spin_unlock_irqrestore(&(priv->imb_lock), flags);
++
++ if (msg != NULL) {
++ struct ipmi_ipmb_addr *ipmb_addr;
++
++ ipmb_addr = (struct ipmi_ipmb_addr *) &(msg->addr);
++ pAsyncResp->thisSeq = msg->msgid;
++ pAsyncResp->data[0] = IPMI_NETFN_APP_REQUEST << 2;
++ pAsyncResp->data[1] = IPMI_SEND_MSG_CMD;
++ pAsyncResp->data[2] = 0;
++ pAsyncResp->data[3] = msg->addr.channel;
++ pAsyncResp->data[4] = ((msg->msg.netfn << 2)
++ | 2);
++ pAsyncResp->data[5]
++ = ipmb_checksum(&(pAsyncResp->data[3]),
++ 2);
++ pAsyncResp->data[6] = ipmb_addr->slave_addr;
++ pAsyncResp->data[7] = ((msg->msgid << 2)
++ | ipmb_addr->lun);
++ pAsyncResp->data[8] = msg->msg.cmd;
++
++ memcpy(&(pAsyncResp->data[9]),
++ &(msg->msg.data[0]),
++ msg->msg.data_len);
++
++ length = msg->msg.data_len + MIN_ASYNC_RESP_SIZE;
++
++ ipmi_free_recv_msg(msg);
++
++ if (copy_to_user(smi.lpvOutBuffer, pAsyncResp, length))
++ {
++ return -EFAULT;
++ }
++ }
++
++ if (copy_to_user(smi.lpcbBytesReturned,
++ &length,
++ sizeof(length)))
++ {
++ return -EFAULT;
++ }
++ rv = 0;
++ break;
++ }
++
++ case IOCTL_IMB_SEND_MESSAGE:
++ {
++ unsigned char imbReqBuffer[MAX_IMB_RESPONSE_SIZE + 8];
++ unsigned char imbRespBuffer[MAX_IMB_RESPONSE_SIZE + 8];
++ ImbRequestBuffer *pImbReq=(ImbRequestBuffer *)imbReqBuffer;
++ ImbResponseBuffer *pImbResp=(ImbResponseBuffer*)imbRespBuffer;
++ struct ipmi_addr addr;
++ struct ipmi_msg msg;
++ unsigned long msgid;
++ struct ipmi_recv_msg *rsp;
++ unsigned long length;
++ wait_queue_t wait;
++ struct list_head *entry;
++
++
++ if ((smi.cbInBuffer < MIN_IMB_REQ_BUF_SIZE)
++ || (smi.cbOutBuffer < MIN_IMB_RESP_BUF_SIZE))
++ {
++ return -EINVAL;
++ }
++
++ if (smi.cbInBuffer > (MAX_IMB_RESPONSE_SIZE + 8)) {
++ /* Input buffer is too large */
++ return -EINVAL;
++ }
++
++ if (copy_from_user(pImbReq, smi.lpvInBuffer, smi.cbInBuffer)) {
++ return -EFAULT;
++ }
++ if ((pImbReq->req.dataLength + MIN_IMB_REQ_BUF_SIZE)
++ > smi.cbInBuffer)
++ {
++ return -EINVAL;
++ }
++ if (pImbReq->req.dataLength > MAX_BUFFER_SIZE) {
++ return -EINVAL;
++ }
++
++ if (pImbReq->req.rsSa == BMC_SA) {
++ struct ipmi_system_interface_addr *smi_addr
++ = (struct ipmi_system_interface_addr *) &addr;
++
++ if ((pImbReq->req.netFn
++ == (IPMI_NETFN_APP_REQUEST << 2))
++ && (pImbReq->req.cmd
++ == IPMI_READ_EVENT_MSG_BUFFER_CMD))
++ {
++ /* The driver gets event messages
++ automatically, so we emulate
++ this. */
++ rv = imb_handle_event_request(priv, &rsp);
++ goto copy_resp;
++ } else {
++ smi_addr->addr_type
++ = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr->channel = IPMI_BMC_CHANNEL;
++ smi_addr->lun = 0;
++ }
++ } else {
++ struct ipmi_ipmb_addr *ipmb_addr =
++ (struct ipmi_ipmb_addr *) &addr;
++
++ ipmb_addr->addr_type = IPMI_IPMB_ADDR_TYPE;
++ ipmb_addr->slave_addr = pImbReq->req.rsSa;
++ ipmb_addr->lun = pImbReq->req.rsLun;
++ ipmb_addr->channel = 0;
++ }
++
++ if (pImbReq->flags & NO_RESPONSE_EXPECTED) {
++ spin_lock(&priv->imb_lock);
++ msgid = priv->curr_msgid;
++ (priv->curr_msgid)++;
++ spin_unlock(&priv->imb_lock);
++ } else {
++ msgid = 0;
++ }
++
++ msg.netfn = pImbReq->req.netFn;
++ msg.cmd = pImbReq->req.cmd;
++ msg.data = pImbReq->req.data;
++ msg.data_len = pImbReq->req.dataLength;
++ rv = ipmi_request(priv->imb_user,
++ &addr,
++ msgid,
++ &msg,
++ 0);
++ if (rv) {
++ rv = IMB_SEND_REQUEST_FAILED;
++ goto copy_resp;
++ }
++
++ if (pImbReq->flags & NO_RESPONSE_EXPECTED)
++ goto no_response;
++
++ /* Now wait for the response to come back. */
++ spin_lock_irqsave(&(priv->imb_lock), flags);
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&(priv->imb_waiting_rsp_rcvrs),
++ &wait);
++ for (;;) {
++ /* Check to see if it's there. */
++ if (!list_empty(&(priv->imb_waiting_rsps))) {
++ entry = priv->imb_waiting_rsps.next;
++ list_del(entry);
++ rsp = list_entry(entry,
++ struct ipmi_recv_msg,
++ link);
++ if (rsp->msgid != msgid) {
++ ipmi_free_recv_msg(rsp);
++ rsp = NULL;
++ } else {
++ break;
++ }
++ }
++
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (!signal_pending(current)) {
++ spin_unlock_irqrestore
++ (&(priv->imb_lock), flags);
++ schedule();
++ spin_lock_irqsave
++ (&(priv->imb_lock), flags);
++ } else {
++ rv = -ERESTARTSYS;
++ break;
++ }
++ }
++ remove_wait_queue(&(priv->imb_waiting_rsp_rcvrs),
++ &wait);
++ spin_unlock_irqrestore(&(priv->imb_lock), flags);
++
++ copy_resp:
++ if (rsp != NULL) {
++ pImbResp->cCode = rsp->msg.data[0];
++ memcpy(pImbResp->data,
++ rsp->msg.data+1,
++ rsp->msg.data_len-1);
++ length = (rsp->msg.data_len - 1
++ + MIN_IMB_RESP_BUF_SIZE);
++
++ if (copy_to_user(smi.lpvOutBuffer, pImbResp, length)) {
++ return -EFAULT;
++ }
++
++ if (copy_to_user(smi.lpcbBytesReturned,
++ &length,
++ sizeof(length)))
++ {
++ return -EFAULT;
++ }
++ }
++ no_response:
++ break;
++ }
++
++ case IOCTL_IMB_SHUTDOWN_CODE:
++ {
++ ShutdownCmdBuffer shutdownCmd;
++
++ if (copy_from_user(&shutdownCmd,
++ smi.lpvInBuffer,
++ sizeof(ShutdownCmdBuffer)))
++ {
++ return -EFAULT;
++ }
++
++ if (smi.cbInBuffer < sizeof(ShutdownCmdBuffer))
++ {
++ return -EINVAL;
++ }
++
++ rv = 0;
++ switch (shutdownCmd.code) {
++ case SD_POWER_OFF:
++ ipmi_delayed_shutdown(shutdownCmd.delayTime / 10, 1);
++ break;
++
++ case SD_RESET:
++ ipmi_delayed_shutdown(shutdownCmd.delayTime / 10, 0);
++ break;
++
++ case SD_NO_ACTION:
++ break;
++
++ default:
++ rv = INVALID_ARGUMENTS;
++ }
++
++ }
++
++ case IOCTL_IMB_REGISTER_ASYNC_OBJ:
++ rv = STATUS_SUCCESS;
++ break;
++
++
++ case IOCTL_IMB_CHECK_EVENT:
++ {
++ wait_queue_t wait;
++
++ spin_lock_irqsave(&(priv->imb_lock), flags);
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&(priv->imb_waiting_cmd_rcvrs),
++ &wait);
++ while (!list_empty(&(priv->imb_waiting_cmds))) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (!signal_pending(current)) {
++ spin_unlock_irqrestore
++ (&(priv->imb_lock), flags);
++ schedule();
++ spin_lock_irqsave
++ (&(priv->imb_lock), flags);
++ } else {
++ rv = -ERESTARTSYS;
++ break;
++ }
++ }
++ remove_wait_queue(&(priv->imb_waiting_cmd_rcvrs),
++ &wait);
++ spin_unlock_irqrestore(&(priv->imb_lock), flags);
++ rv = 0;
++ break;
++ }
++ }
++
++ return rv;
++}
++
++static int ipmi_imb_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ off_t offset = vma->vm_pgoff << PAGE_SHIFT;
++
++ if (offset < 0)
++ return -EINVAL;
++
++ if (remap_page_range(vma->vm_start, offset,
++ vma->vm_end - vma->vm_start,
++ vma->vm_page_prot))
++ {
++ return -EAGAIN;
++ }
++
++ /*vma->vm_inode = what_goes_here; */
++
++ return 0;
++
++}
++
++
++static struct file_operations ipmi_fops = {
++ owner: THIS_MODULE,
++ ioctl: ipmi_imb_ioctl,
++ open: ipmi_imb_open,
++ release: ipmi_imb_release,
++ mmap: ipmi_imb_mmap
++};
++
++static struct timer_list ipmi_imb_timer;
++
++/* Call every 100 ms. */
++#define IPMI_TIMEOUT_TIME 100
++#define IPMI_TIMEOUT_JIFFIES (IPMI_TIMEOUT_TIME/(1000/HZ))
++
++static volatile int stop_operation = 0;
++static volatile int timer_stopped = 0;
++
++static void ipmi_imb_timeout(unsigned long data)
++{
++ struct list_head *entry, *entry2;
++ struct priv_data *priv = (struct priv_data *) data;
++ int timeout_period = IPMI_TIMEOUT_TIME;
++ struct ipmi_recv_msg *msg;
++
++ if (stop_operation) {
++ timer_stopped = 1;
++ return;
++ }
++
++ /* Now time out any messages in the Imb message queue. */
++ spin_lock(&(priv->imb_lock));
++ list_for_each_safe(entry, entry2, &(priv->imb_waiting_rsps)) {
++ long *timeout;
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ timeout = imb_timeout(msg);
++ *timeout -= timeout_period;
++ if ((*timeout) <= 0) {
++ list_del(entry);
++ ipmi_free_recv_msg(msg);
++ }
++ }
++ list_for_each_safe(entry, entry2, &(priv->imb_waiting_cmds)) {
++ long *timeout;
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ timeout = imb_timeout(msg);
++ *timeout -= timeout_period;
++ if ((*timeout) <= 0) {
++ list_del(entry);
++ ipmi_free_recv_msg(msg);
++ }
++ }
++ spin_unlock(&priv->imb_lock);
++
++ ipmi_imb_timer.expires += IPMI_TIMEOUT_JIFFIES;
++ add_timer(&ipmi_imb_timer);
++}
++
++#define DEVICE_NAME "imb"
++
++static int ipmi_imb_major = 0;
++MODULE_PARM(ipmi_imb_major, "i");
++
++static struct ipmi_user_hndl ipmi_hndlrs =
++{
++ ipmi_recv_hndl : imb_msg_recv
++};
++
++static int init_ipmi_imb(void)
++{
++ int rv;
++
++ if (ipmi_imb_major < 0)
++ return -EINVAL;
++
++ ipmi_user = kmalloc(sizeof(*ipmi_user), GFP_KERNEL);
++ if (!ipmi_user) {
++ return -ENOMEM;
++ }
++
++ /* Create the Imb interface user. */
++ spin_lock_init(&(ipmi_user->imb_lock));
++ INIT_LIST_HEAD(&(ipmi_user->imb_waiting_rsps));
++ init_waitqueue_head(&(ipmi_user->imb_waiting_rsp_rcvrs));
++ INIT_LIST_HEAD(&(ipmi_user->imb_waiting_cmds));
++ init_waitqueue_head(&(ipmi_user->imb_waiting_cmd_rcvrs));
++ ipmi_user->imb_cmd_waiting = 0;
++ INIT_LIST_HEAD(&(ipmi_user->imb_waiting_events));
++
++ rv = ipmi_create_user(0,
++ &ipmi_hndlrs,
++ ipmi_user,
++ &(ipmi_user->imb_user));
++ if (rv) {
++ kfree(ipmi_user);
++ ipmi_user = NULL;
++ return rv;
++ }
++
++ rv = register_chrdev(ipmi_imb_major, DEVICE_NAME, &ipmi_fops);
++ if (rv < 0)
++ {
++ kfree(ipmi_user);
++ ipmi_user = NULL;
++ printk(KERN_ERR "ipmi: can't get major %d\n",
++ ipmi_imb_major);
++ return rv;
++ }
++
++ if (ipmi_imb_major == 0)
++ {
++ ipmi_imb_major = rv;
++ }
++
++ devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_NONE,
++ ipmi_imb_major, 0,
++ S_IFCHR | S_IRUSR | S_IWUSR,
++ &ipmi_fops, NULL);
++
++ ipmi_imb_timer.data = (long) ipmi_user;
++ ipmi_imb_timer.function = ipmi_imb_timeout;
++ ipmi_imb_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES;
++ add_timer(&ipmi_imb_timer);
++
++ printk(KERN_INFO "ipmi_imb: driver initialized at char major %d\n",
++ ipmi_imb_major);
++
++ return 0;
++}
++
++#ifdef MODULE
++static void free_recv_msg_list(struct list_head *q)
++{
++ struct list_head *entry, *entry2;
++ struct ipmi_recv_msg *msg;
++
++ list_for_each_safe(entry, entry2, q) {
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ list_del(entry);
++ ipmi_free_recv_msg(msg);
++ }
++}
++
++static void cleanup_ipmi_imb(void)
++{
++ devfs_unregister(devfs_handle);
++
++ /* Tell the timer to stop, then wait for it to stop. This avoids
++ problems with race conditions removing the timer here. */
++ stop_operation = 1;
++ while (!timer_stopped) {
++ schedule_timeout(1);
++ }
++
++ ipmi_destroy_user(ipmi_user->imb_user);
++
++ free_recv_msg_list(&(ipmi_user->imb_waiting_rsps));
++ free_recv_msg_list(&(ipmi_user->imb_waiting_cmds));
++ free_recv_msg_list(&(ipmi_user->imb_waiting_events));
++
++ kfree(ipmi_user);
++ ipmi_user = NULL;
++
++ unregister_chrdev(ipmi_imb_major, DEVICE_NAME);
++}
++module_exit(cleanup_ipmi_imb);
++#else
++static int __init ipmi_imb_setup (char *str)
++{
++ int x;
++
++ if (get_option (&str, &x)) {
++ /* ipmi=x sets the major number to x. */
++ ipmi_imb_major = x;
++ } else if (!strcmp(str, "off")) {
++ ipmi_imb_major = -1;
++ }
++
++ return 1;
++}
++__setup("ipmi_imb=", ipmi_imb_setup);
++#endif
++
++module_init(init_ipmi_imb);
++MODULE_LICENSE("GPL");
+diff -urN linux/drivers/char/ipmi/ipmi_radisys.c linux-emu/drivers/char/ipmi/ipmi_radisys.c
+--- linux/drivers/char/ipmi/ipmi_radisys.c Wed Dec 31 18:00:00 1969
++++ linux-emu/drivers/char/ipmi/ipmi_radisys.c Fri Jan 10 11:24:56 2003
+@@ -0,0 +1,834 @@
++/*
++ * ipmi_radisys.c
++ *
++ * Radisys emulation for the IPMI interface.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <asm/system.h>
++#include <linux/sched.h>
++#include <linux/poll.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/devfs_fs_kernel.h>
++#include <linux/ipmi.h>
++#include <linux/ipmi_radisys.h>
++
++
++struct priv_data
++{
++ /* This is for supporting the old Radisys interface. */
++ ipmi_user_t rs_user;
++ spinlock_t rs_lock;
++
++ /* A list of responses in the queue. */
++ struct list_head rs_waiting_rsps;
++
++ /* A list of things waiting for responses. We wake them all up
++ when a response comes in. */
++ wait_queue_head_t rs_waiting_rsp_rcvrs;
++
++ /* A list of commands that have come in. */
++ struct list_head rs_waiting_cmds;
++
++ /* A list of thing waiting for commands. We wake them all up
++ when a command comes in. */
++ wait_queue_head_t rs_waiting_cmd_rcvrs;
++
++ /* The registered command receiver value. This only allows someone
++ with the "magic number" to issue commands. */
++ unsigned long rs_cmd_receiver;
++
++ /* Is someone already waiting for a command? The Radisys driver
++ only allows one waiter, this enforces that. */
++ int rs_cmd_waiting;
++
++ /* A list of IPMI events waiting to be delivered. (not that
++ the Radisys driver calls incoming commands "events", this
++ variable is actual IPMI events, not incoming commands). */
++ struct list_head rs_waiting_events;
++
++#define RS_EVENT_QUEUE_LIMIT 16 /* Allow up to 16 events. */
++ /* The number of events in the event queue. */
++ unsigned int rs_waiting_event_count;
++};
++
++
++static devfs_handle_t devfs_handle;
++
++/* We cheat and use a piece of the address as the timeout. */
++static long *rs_timeout(struct ipmi_recv_msg *msg)
++{
++ char *base = (char *) &(msg->addr);
++ base += sizeof(struct ipmi_ipmb_addr);
++ return (long *) base;
++}
++
++static void rs_msg_recv(struct ipmi_recv_msg *msg,
++ void *data)
++{
++ struct priv_data *priv = data;
++ unsigned long flags;
++
++ spin_lock_irqsave(&(priv->rs_lock), flags);
++ if (msg->recv_type == IPMI_RESPONSE_RECV_TYPE) {
++ *rs_timeout(msg) = 5000;
++ list_add_tail(&(msg->link), &(priv->rs_waiting_rsps));
++ wake_up_all(&(priv->rs_waiting_rsp_rcvrs));
++ } else if (msg->recv_type == IPMI_CMD_RECV_TYPE) {
++ *rs_timeout(msg) = 5000;
++ list_add_tail(&(msg->link), &(priv->rs_waiting_cmds));
++ wake_up_all(&(priv->rs_waiting_cmd_rcvrs));
++ } else if (msg->recv_type == IPMI_ASYNC_EVENT_RECV_TYPE) {
++ if (priv->rs_waiting_event_count > RS_EVENT_QUEUE_LIMIT) {
++ ipmi_free_recv_msg(msg);
++ } else {
++ list_add_tail(&(msg->link),&(priv->rs_waiting_events));
++ (priv->rs_waiting_event_count)++;
++ }
++ } else {
++ ipmi_free_recv_msg(msg);
++ }
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++}
++
++/* We emulate the event queue in the driver for the Radisys emulation. */
++static int rs_handle_event_request(struct priv_data *priv)
++{
++ struct list_head *entry;
++ unsigned long flags;
++ struct ipmi_recv_msg *msg = NULL;
++ int rv = 0;
++
++ spin_lock_irqsave(&(priv->rs_lock), flags);
++ if (list_empty(&(priv->rs_waiting_events))) {
++ /* Nothing in the event queue, just return an error. */
++ msg = ipmi_alloc_recv_msg();
++ if (msg == NULL) {
++ rv = -EAGAIN;
++ goto out_err;
++ }
++ msg->addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ msg->addr.channel = IPMI_BMC_CHANNEL;
++ msg->msg.cmd = IPMI_READ_EVENT_MSG_BUFFER_CMD;
++ msg->msgid = 0;
++ msg->recv_type = IPMI_ASYNC_EVENT_RECV_TYPE;
++ msg->msg.netfn = IPMI_NETFN_APP_RESPONSE;
++ msg->msg.data = msg->msg_data;
++ msg->msg.data[0] = 0x80; /* Data not available. */
++ msg->msg.data_len = 1;
++ } else {
++ /* Pull an item from the event queue . */
++ entry = priv->rs_waiting_events.next;
++ list_del(entry);
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ (priv->rs_waiting_event_count)--;
++ }
++
++ /* Put the response into the list of waiting responses and
++ wake all the response waiters up. */
++ *rs_timeout(msg) = 5000;
++ list_add_tail(&(msg->link), &(priv->rs_waiting_rsps));
++ wake_up_all(&(priv->rs_waiting_rsp_rcvrs));
++
++ out_err:
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++ return rv;
++}
++
++static struct ipmi_recv_msg *rs_find_in_list(struct list_head *q,
++ unsigned char slave_addr,
++ unsigned char lun,
++ unsigned char netfn,
++ unsigned char cmd,
++ unsigned char seq)
++{
++ struct list_head *entry;
++ struct ipmi_recv_msg *msg;
++ struct ipmi_addr addr;
++ unsigned char msg_seq;
++
++ if (slave_addr == 1) {
++ struct ipmi_system_interface_addr *smi_addr;
++ smi_addr = (struct ipmi_system_interface_addr *) &addr;
++ smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr->lun = lun;
++ /* Slave address 1 means no matching sequence in the
++ Radisys driver. */
++ } else {
++ struct ipmi_ipmb_addr *ipmb_addr;
++ ipmb_addr = (struct ipmi_ipmb_addr *) &addr;
++ ipmb_addr->addr_type = IPMI_IPMB_ADDR_TYPE;
++ ipmb_addr->slave_addr = slave_addr;
++ ipmb_addr->lun = lun;
++ }
++
++ list_for_each(entry, q) {
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ if (msg->addr.channel == IPMI_BMC_CHANNEL)
++ msg_seq = 0;
++ else
++ msg_seq = msg->msgid;
++
++ /* We ignore the channel for these comparisons, since the
++ Radisys driver seems to ignore it. */
++ addr.channel = msg->addr.channel;
++
++ if ((msg_seq == seq)
++ && (msg->msg.cmd == cmd)
++ && (msg->msg.netfn == (netfn >> 2))
++ && ipmi_addr_equal(&addr, &(msg->addr)))
++ {
++ list_del(entry);
++ return msg;
++ }
++ }
++
++ return NULL;
++}
++
++static struct priv_data *ipmi_user;
++static unsigned int user_count = 0; /* How many users have this open. */
++static spinlock_t dev_lock = SPIN_LOCK_UNLOCKED;
++
++static int ipmi_open(struct inode *inode, struct file *file)
++{
++ file->private_data = ipmi_user;
++ spin_lock(&dev_lock);
++ if (user_count == 0)
++ ipmi_set_gets_events(ipmi_user->rs_user, 1);
++ user_count++;
++ spin_unlock(&dev_lock);
++
++ return 0;
++}
++
++static int ipmi_release(struct inode *inode, struct file *file)
++{
++ spin_lock(&dev_lock);
++ user_count--;
++ if (user_count == 0)
++ ipmi_set_gets_events(ipmi_user->rs_user, 0);
++ spin_unlock(&dev_lock);
++ return 0;
++}
++
++static unsigned char
++ipmb_checksum(unsigned char *data, int size)
++{
++ unsigned char csum = 0;
++
++ for (; size > 0; size--, data++)
++ csum += *data;
++
++ return -csum;
++}
++
++static int ipmi_ioctl(struct inode *inode,
++ struct file *file,
++ unsigned int cmd,
++ unsigned long data)
++{
++ struct priv_data *priv = file->private_data;
++ int rv = -EINVAL;
++
++ switch(cmd) {
++ case IOCTL_IPMI_RCV: /* get ipmi message */
++ {
++ IPMI_MSGDESC rsp;
++ struct ipmi_recv_msg *msg;
++ unsigned long flags;
++ long timeout;
++ wait_queue_t wait;
++
++ if (copy_from_user(&rsp, (void *) data, sizeof(rsp))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = 0;
++
++ spin_lock_irqsave(&(priv->rs_lock), flags);
++
++ msg = rs_find_in_list(&(priv->rs_waiting_rsps),
++ rsp.Dest.uchSlave,
++ rsp.Dest.uchLun,
++ rsp.uchNetFn,
++ rsp.uchCmd,
++ rsp.uchSeq);
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&(priv->rs_waiting_rsp_rcvrs),
++ &wait);
++ timeout = 5000 / (1000 / HZ);
++ while (msg == NULL) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (!signal_pending(current)) {
++ spin_unlock_irqrestore
++ (&(priv->rs_lock), flags);
++ timeout = schedule_timeout(timeout);
++ spin_lock_irqsave
++ (&(priv->rs_lock), flags);
++ } else {
++ rv = -ERESTARTSYS;
++ break;
++ }
++ if (timeout <= 0) {
++ rsp.uchComplete = IPMI_TIMEOUT_COMPLETION_CODE;
++ break;
++ } else {
++ msg = rs_find_in_list
++ (&(priv->rs_waiting_rsps),
++ rsp.Dest.uchSlave,
++ rsp.Dest.uchLun,
++ rsp.uchNetFn,
++ rsp.uchCmd,
++ rsp.uchSeq);
++ }
++ }
++ remove_wait_queue(&(priv->rs_waiting_rsp_rcvrs),
++ &wait);
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++
++ if (msg != NULL) {
++ rsp.uchComplete = msg->msg.data[0];
++ /* The Radisys driver expects all the data to
++ be there in the data, even the stuff we
++ already have processed for it. So make is
++ so. */
++ if (msg->addr.channel == IPMI_BMC_CHANNEL) {
++ struct ipmi_system_interface_addr *smi_addr;
++
++ smi_addr = ((struct ipmi_system_interface_addr *)
++ &(msg->addr));
++ memcpy(&(rsp.auchBuffer[2]),
++ &(msg->msg.data[0]),
++ msg->msg.data_len);
++ rsp.ulLength = msg->msg.data_len+2;
++ rsp.auchBuffer[0] = ((msg->msg.netfn << 2)
++ | (smi_addr->lun));
++ rsp.auchBuffer[1] = msg->msg.cmd;
++ } else {
++ struct ipmi_ipmb_addr *ipmb_addr;
++
++ ipmb_addr = (struct ipmi_ipmb_addr *) &msg->addr;
++ memcpy(&(rsp.auchBuffer[9]),
++ &(msg->msg.data[0]),
++ msg->msg.data_len);
++ rsp.ulLength = msg->msg.data_len+10;
++ rsp.auchBuffer[0] = IPMI_NETFN_APP_REQUEST << 2;
++ rsp.auchBuffer[1] = IPMI_GET_MSG_CMD;
++ rsp.auchBuffer[2] = 0;
++ rsp.auchBuffer[3] = msg->addr.channel;
++ rsp.auchBuffer[4] = ((msg->msg.netfn << 2)
++ | 2);
++ rsp.auchBuffer[5]
++ = ipmb_checksum(&(rsp.auchBuffer[3]),
++ 2);
++ rsp.auchBuffer[6] = ipmb_addr->slave_addr;
++ rsp.auchBuffer[7] = ((msg->msgid << 2)
++ | ipmb_addr->lun);
++ rsp.auchBuffer[8] = msg->msg.cmd;
++ rsp.auchBuffer[msg->msg.data_len+9]
++ = ipmb_checksum(&(rsp.auchBuffer[6]),
++ msg->msg.data_len+3);
++ }
++ ipmi_free_recv_msg(msg);
++ }
++
++ if (copy_to_user((void *) data, &rsp, sizeof(rsp))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ break;
++ }
++
++ case IOCTL_IPMI_SEND: /* send ipmi message */
++ {
++ IPMI_MSGDESC req;
++ struct ipmi_addr addr;
++ struct ipmi_msg msg;
++ unsigned char source_address;
++ unsigned char source_lun;
++ unsigned int start_offset;
++
++ if (copy_from_user(&req, (void *) data, sizeof(req))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ if (req.Dest.uchSlave == 1) {
++ struct ipmi_system_interface_addr *smi_addr
++ = (struct ipmi_system_interface_addr *) &addr;
++ if ((req.uchNetFn == (IPMI_NETFN_APP_REQUEST << 2))
++ && (req.uchCmd == IPMI_READ_EVENT_MSG_BUFFER_CMD))
++ {
++ /* The driver gets event messages
++ automatically, so we emulate
++ this. */
++ rv = rs_handle_event_request(priv);
++ break;
++ }
++
++ smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr->channel = IPMI_BMC_CHANNEL;
++ smi_addr->lun = req.uchNetFn & 0x3;
++ source_address = 0;
++ source_lun = 0;
++ start_offset = 2;
++ } else {
++ struct ipmi_ipmb_addr *ipmb_addr =
++ (struct ipmi_ipmb_addr *) &addr;
++
++ ipmb_addr->addr_type = IPMI_IPMB_ADDR_TYPE;
++ ipmb_addr->channel = 0;
++ ipmb_addr->slave_addr = req.Dest.uchSlave;
++ ipmb_addr->lun = req.Dest.uchLun;
++ source_address = req.auchBuffer[6];
++ source_lun = req.auchBuffer[7] & 0x3;
++ start_offset = 9;
++ req.ulLength--; /* Remove the checksum the userland
++ process adds. */
++ }
++
++ msg.netfn = req.uchNetFn >> 2;
++ msg.cmd = req.uchCmd;
++ msg.data = req.auchBuffer + start_offset;
++ msg.data_len = req.ulLength - start_offset;
++
++ rv = ipmi_request_with_source(priv->rs_user,
++ &addr,
++ req.uchSeq,
++ &msg,
++ 0,
++ source_address,
++ source_lun);
++ if (rv)
++ req.uchComplete = IPMI_UNKNOWN_ERR_COMPLETION_CODE;
++ else
++ req.uchComplete = 0;
++ /* The Radisys driver does no error checking here. */
++ copy_to_user((void *) data, &req, sizeof(req));
++ rv = 0;
++ break;
++ }
++
++ case IOCTL_IPMI_EVENT: /* get an incoming command. Don't be
++ fooled by the name, these are
++ commands, not IPMI events. */
++ {
++ IPMI_MSGDESC rsp;
++ struct ipmi_recv_msg *msg = NULL;
++ struct list_head *entry;
++ unsigned long flags;
++ long timeout;
++ unsigned long receiver;
++ wait_queue_t wait;
++
++ if (copy_from_user(&receiver, (void *) data, sizeof(receiver)))
++ {
++ rv = -EFAULT;
++ break;
++ }
++
++ if (copy_from_user(&timeout,
++ (void *) (data + sizeof(receiver)),
++ sizeof(timeout)))
++ {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = 0;
++
++ spin_lock_irqsave(&(priv->rs_lock), flags);
++
++ /* If someone else is already waiting, the Radisys driver
++ returns EFAULT, so we do to. */
++ if (priv->rs_cmd_waiting) {
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++ rv = -EFAULT;
++ break;
++ }
++
++ /* If the user thread doesn't match up, abort. */
++ if (receiver != priv->rs_cmd_receiver) {
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++ rsp.uchComplete = IPMI_INVALID_CMD_COMPLETION_CODE;
++ break;
++ }
++
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&(priv->rs_waiting_cmd_rcvrs),
++ &wait);
++ priv->rs_cmd_waiting = 1;
++ timeout = timeout / (1000 / HZ); /* from ms to jiffies */
++ while ((timeout > 0) &&
++ list_empty(&(priv->rs_waiting_cmds)))
++ {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (!signal_pending(current)) {
++ spin_unlock_irqrestore
++ (&(priv->rs_lock), flags);
++ timeout = schedule_timeout(timeout);
++ spin_lock_irqsave
++ (&(priv->rs_lock), flags);
++ } else {
++ rv = -ERESTARTSYS;
++ break;
++ }
++ }
++ if (!list_empty(&(priv->rs_waiting_cmds))) {
++ entry = priv->rs_waiting_cmds.next;
++ list_del(entry);
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ }
++ priv->rs_cmd_waiting = 0;
++ remove_wait_queue(&(priv->rs_waiting_cmd_rcvrs),
++ &wait);
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++
++ if (msg != NULL) {
++ /* The Radisys driver expects all the data to
++ be there in the data, even the stuff we
++ already have processed for it. So make is
++ so. */
++ struct ipmi_ipmb_addr *ipmb_addr;
++
++ ipmb_addr = (struct ipmi_ipmb_addr *) &msg->addr;
++ memcpy(&(rsp.auchBuffer[9]),
++ &(msg->msg.data[0]),
++ msg->msg.data_len);
++ rsp.ulLength = msg->msg.data_len+9;
++ rsp.auchBuffer[0] = IPMI_NETFN_APP_REQUEST << 2;
++ rsp.auchBuffer[1] = IPMI_SEND_MSG_CMD;
++ rsp.auchBuffer[2] = 0;
++ rsp.auchBuffer[3] = msg->addr.channel;
++ rsp.auchBuffer[4] = ((msg->msg.netfn << 2)
++ | 2);
++ rsp.auchBuffer[5]
++ = ipmb_checksum(&(rsp.auchBuffer[3]),
++ 2);
++ rsp.auchBuffer[6] = ipmb_addr->slave_addr;
++ rsp.auchBuffer[7] = ((msg->msgid << 2)
++ | ipmb_addr->lun);
++ rsp.auchBuffer[8] = msg->msg.cmd;
++
++ rsp.uchNetFn = (msg->msg.netfn << 2);
++ rsp.uchCmd = msg->msg.cmd;
++ rsp.uchSeq = msg->msgid;
++ rsp.ulLength = msg->msg.data_len + 9;
++ ipmi_free_recv_msg(msg);
++ } else if (!rv) {
++ /* On a time out, the Radisys driver returns
++ IPMIRC_ERROR in the completion code, for
++ some wierd reason. */
++ rsp.uchComplete = IPMI_UNKNOWN_ERR_COMPLETION_CODE;
++ }
++
++ /* The Radisys driver does no error checking here. */
++ copy_to_user((void *) data, &rsp, sizeof(rsp));
++ rv = 0;
++ break;
++ }
++
++ case IOCTL_IPMI_REGISTER: /* register as event receiver */
++ {
++ unsigned long receiver;
++ unsigned char rc = LOWLRC_SUCCESS;
++ unsigned long flags;
++
++ if (copy_from_user(&receiver, (void *) data, sizeof(receiver)))
++ {
++ rv = -EFAULT;
++ break;
++ }
++
++ spin_lock_irqsave(&(priv->rs_lock), flags);
++ if (priv->rs_cmd_receiver == 0) {
++ rv = ipmi_register_all_cmd_rcvr(priv->rs_user);
++ if (rv) {
++ priv->rs_cmd_receiver = receiver;
++ } else {
++ rc = LOWLRC_ERROR;
++ }
++ } else if (priv->rs_cmd_receiver != receiver) {
++ rc = LOWLRC_ERROR;
++ }
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++
++ /* The Radisys driver does no error checking here. */
++ copy_to_user((void *) data, &rc, sizeof(rc));
++ rv = 0;
++ break;
++ }
++
++ case IOCTL_IPMI_UNREGISTER: /* unregister as event receiver */
++ {
++ unsigned long receiver;
++ unsigned char rc = LOWLRC_SUCCESS;
++ unsigned long flags;
++
++ if (copy_from_user(&receiver, (void *) data, sizeof(receiver)))
++ {
++ rv = -EFAULT;
++ break;
++ }
++
++ spin_lock_irqsave(&(priv->rs_lock), flags);
++ if (priv->rs_cmd_receiver == receiver) {
++ ipmi_unregister_all_cmd_rcvr(priv->rs_user);
++ priv->rs_cmd_receiver = 0;
++ } else {
++ rc = LOWLRC_ERROR;
++ }
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++
++ /* The Radisys driver does no error checking here. */
++ copy_to_user((void *) data, &rc, sizeof(rc));
++ rv = 0;
++ break;
++ }
++
++ case IOCTL_IPMI_CLEAR: /* clear registered event receiver */
++ {
++ unsigned char rc = LOWLRC_SUCCESS;
++ unsigned long flags;
++
++ spin_lock_irqsave(&(priv->rs_lock), flags);
++ ipmi_unregister_all_cmd_rcvr(priv->rs_user);
++ priv->rs_cmd_receiver = 0;
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++
++ /* The Radisys driver does no error checking here. */
++ copy_to_user((void *) data, &rc, sizeof(rc));
++ rv = 0;
++ break;
++ }
++ }
++
++ return rv;
++}
++
++static struct file_operations ipmi_fops = {
++ owner: THIS_MODULE,
++ ioctl: ipmi_ioctl,
++ open: ipmi_open,
++ release: ipmi_release
++};
++
++static struct timer_list ipmi_radisys_timer;
++
++/* Call every 100 ms. */
++#define IPMI_TIMEOUT_TIME 100
++#define IPMI_TIMEOUT_JIFFIES (IPMI_TIMEOUT_TIME/(1000/HZ))
++
++/* Request events from the queue every second. Hopefully, in the
++ future, IPMI will add a way to know immediately if an event is
++ in the queue. */
++#define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME))
++
++static volatile int stop_operation = 0;
++static volatile int timer_stopped = 0;
++
++static void ipmi_radisys_timeout(unsigned long data)
++{
++ struct list_head *entry, *entry2;
++ struct priv_data *priv = (struct priv_data *) data;
++ int timeout_period = IPMI_TIMEOUT_TIME;
++ struct ipmi_recv_msg *msg;
++
++ if (stop_operation) {
++ timer_stopped = 1;
++ return;
++ }
++
++ /* Now time out any messages in the Radisys message queue. */
++ spin_lock(&(priv->rs_lock));
++ list_for_each_safe(entry, entry2, &(priv->rs_waiting_rsps)) {
++ long *timeout;
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ timeout = rs_timeout(msg);
++ *timeout -= timeout_period;
++ if ((*timeout) <= 0) {
++ list_del(entry);
++ ipmi_free_recv_msg(msg);
++ }
++ }
++ list_for_each_safe(entry, entry2, &(priv->rs_waiting_cmds)) {
++ long *timeout;
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ timeout = rs_timeout(msg);
++ *timeout -= timeout_period;
++ if ((*timeout) <= 0) {
++ list_del(entry);
++ ipmi_free_recv_msg(msg);
++ }
++ }
++ spin_unlock(&priv->rs_lock);
++
++ ipmi_radisys_timer.expires += IPMI_TIMEOUT_JIFFIES;
++ add_timer(&ipmi_radisys_timer);
++}
++
++#define DEVICE_NAME "ipmi_radisys"
++
++static int ipmi_radisys_major = 0;
++MODULE_PARM(ipmi_radisys_major, "i");
++
++static struct ipmi_user_hndl ipmi_hndlrs =
++{
++ ipmi_recv_hndl : rs_msg_recv
++};
++
++
++static int init_ipmi_radisys(void)
++{
++ int rv;
++
++ if (ipmi_radisys_major < 0)
++ return -EINVAL;
++
++ ipmi_user = kmalloc(sizeof(*ipmi_user), GFP_KERNEL);
++ if (!ipmi_user) {
++ printk("ipmi_radisys: Unable to allocate memory\n");
++ return -ENOMEM;
++ }
++
++ /* Create the Radisys interface user. */
++ spin_lock_init(&(ipmi_user->rs_lock));
++ INIT_LIST_HEAD(&(ipmi_user->rs_waiting_rsps));
++ init_waitqueue_head(&(ipmi_user->rs_waiting_rsp_rcvrs));
++ INIT_LIST_HEAD(&(ipmi_user->rs_waiting_cmds));
++ init_waitqueue_head(&(ipmi_user->rs_waiting_cmd_rcvrs));
++ ipmi_user->rs_cmd_waiting = 0;
++ INIT_LIST_HEAD(&(ipmi_user->rs_waiting_events));
++
++ rv = ipmi_create_user(0,
++ &ipmi_hndlrs,
++ ipmi_user,
++ &(ipmi_user->rs_user));
++ if (rv) {
++ printk("ipmi_radisys: Unable to create an IPMI user, probably"
++ " no physical devices present.\n");
++ kfree(ipmi_user);
++ ipmi_user = NULL;
++ return rv;
++ }
++
++ rv = register_chrdev(ipmi_radisys_major, DEVICE_NAME, &ipmi_fops);
++ if (rv < 0)
++ {
++ printk("ipmi_radisys: Unable to create the character device\n");
++ kfree(ipmi_user);
++ ipmi_user = NULL;
++ printk(KERN_ERR "ipmi: can't get major %d\n",
++ ipmi_radisys_major);
++ return rv;
++ }
++
++ if (ipmi_radisys_major == 0)
++ {
++ ipmi_radisys_major = rv;
++ }
++
++ devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_NONE,
++ ipmi_radisys_major, 0,
++ S_IFCHR | S_IRUSR | S_IWUSR,
++ &ipmi_fops, NULL);
++
++ ipmi_radisys_timer.data = (long) ipmi_user;
++ ipmi_radisys_timer.function = ipmi_radisys_timeout;
++ ipmi_radisys_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES;
++ add_timer(&ipmi_radisys_timer);
++
++ printk(KERN_INFO "ipmi_radisys: driver initialized at char major %d\n",
++ ipmi_radisys_major);
++
++ return 0;
++}
++
++#ifdef MODULE
++static void free_recv_msg_list(struct list_head *q)
++{
++ struct list_head *entry, *entry2;
++ struct ipmi_recv_msg *msg;
++
++ list_for_each_safe(entry, entry2, q) {
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ list_del(entry);
++ ipmi_free_recv_msg(msg);
++ }
++}
++
++static void cleanup_ipmi_radisys(void)
++{
++ devfs_unregister(devfs_handle);
++
++ /* Tell the timer to stop, then wait for it to stop. This avoids
++ problems with race conditions removing the timer here. */
++ stop_operation = 1;
++ while (!timer_stopped) {
++ schedule_timeout(1);
++ }
++
++ ipmi_destroy_user(ipmi_user->rs_user);
++
++ free_recv_msg_list(&(ipmi_user->rs_waiting_rsps));
++ free_recv_msg_list(&(ipmi_user->rs_waiting_cmds));
++ free_recv_msg_list(&(ipmi_user->rs_waiting_events));
++
++ kfree(ipmi_user);
++ ipmi_user = NULL;
++
++ unregister_chrdev(ipmi_radisys_major, DEVICE_NAME);
++}
++module_exit(cleanup_ipmi_radisys);
++#else
++static int __init ipmi_radisys_setup (char *str)
++{
++ int x;
++
++ if (get_option (&str, &x)) {
++ /* ipmi=x sets the major number to x. */
++ ipmi_radisys_major = x;
++ } else if (!strcmp(str, "off")) {
++ ipmi_radisys_major = -1;
++ }
++
++ return 1;
++}
++__setup("ipmi_radisys=", ipmi_radisys_setup);
++#endif
++
++module_init(init_ipmi_radisys);
++MODULE_LICENSE("GPL");
+diff -urN linux/include/linux/autoconf.h linux-emu/include/linux/autoconf.h
+--- linux/include/linux/autoconf.h Mon Jan 13 13:25:58 2003
++++ linux-emu/include/linux/autoconf.h Wed Dec 31 18:00:00 1969
+@@ -1,862 +0,0 @@
+-/*
+- * Automatically generated C config: don't edit
+- */
+-#define AUTOCONF_INCLUDED
+-#define CONFIG_X86 1
+-#undef CONFIG_SBUS
+-#define CONFIG_UID16 1
+-
+-/*
+- * Code maturity level options
+- */
+-#define CONFIG_EXPERIMENTAL 1
+-
+-/*
+- * Loadable module support
+- */
+-#define CONFIG_MODULES 1
+-#undef CONFIG_MODVERSIONS
+-#define CONFIG_KMOD 1
+-
+-/*
+- * Processor type and features
+- */
+-#undef CONFIG_M386
+-#undef CONFIG_M486
+-#undef CONFIG_M586
+-#undef CONFIG_M586TSC
+-#undef CONFIG_M586MMX
+-#undef CONFIG_M686
+-#define CONFIG_MPENTIUMIII 1
+-#undef CONFIG_MPENTIUM4
+-#undef CONFIG_MK6
+-#undef CONFIG_MK7
+-#undef CONFIG_MELAN
+-#undef CONFIG_MCRUSOE
+-#undef CONFIG_MWINCHIPC6
+-#undef CONFIG_MWINCHIP2
+-#undef CONFIG_MWINCHIP3D
+-#undef CONFIG_MCYRIXIII
+-#define CONFIG_X86_WP_WORKS_OK 1
+-#define CONFIG_X86_INVLPG 1
+-#define CONFIG_X86_CMPXCHG 1
+-#define CONFIG_X86_XADD 1
+-#define CONFIG_X86_BSWAP 1
+-#define CONFIG_X86_POPAD_OK 1
+-#undef CONFIG_RWSEM_GENERIC_SPINLOCK
+-#define CONFIG_RWSEM_XCHGADD_ALGORITHM 1
+-#define CONFIG_X86_L1_CACHE_SHIFT (5)
+-#define CONFIG_X86_HAS_TSC 1
+-#define CONFIG_X86_GOOD_APIC 1
+-#define CONFIG_X86_PGE 1
+-#define CONFIG_X86_USE_PPRO_CHECKSUM 1
+-#define CONFIG_X86_F00F_WORKS_OK 1
+-#define CONFIG_X86_MCE 1
+-#undef CONFIG_TOSHIBA
+-#undef CONFIG_I8K
+-#undef CONFIG_MICROCODE
+-#undef CONFIG_X86_MSR
+-#undef CONFIG_X86_CPUID
+-#define CONFIG_NOHIGHMEM 1
+-#undef CONFIG_HIGHMEM4G
+-#undef CONFIG_HIGHMEM64G
+-#undef CONFIG_HIGHMEM
+-#undef CONFIG_MATH_EMULATION
+-#undef CONFIG_MTRR
+-#define CONFIG_SMP 1
+-#undef CONFIG_MULTIQUAD
+-#undef CONFIG_X86_TSC_DISABLE
+-#define CONFIG_X86_TSC 1
+-#define CONFIG_HAVE_DEC_LOCK 1
+-
+-/*
+- * General setup
+- */
+-#define CONFIG_NET 1
+-#define CONFIG_X86_IO_APIC 1
+-#define CONFIG_X86_LOCAL_APIC 1
+-#define CONFIG_PCI 1
+-#undef CONFIG_PCI_GOBIOS
+-#undef CONFIG_PCI_GODIRECT
+-#define CONFIG_PCI_GOANY 1
+-#define CONFIG_PCI_BIOS 1
+-#define CONFIG_PCI_DIRECT 1
+-#define CONFIG_ISA 1
+-#define CONFIG_PCI_NAMES 1
+-#undef CONFIG_EISA
+-#undef CONFIG_MCA
+-#define CONFIG_HOTPLUG 1
+-
+-/*
+- * PCMCIA/CardBus support
+- */
+-#define CONFIG_PCMCIA 1
+-#define CONFIG_CARDBUS 1
+-#undef CONFIG_TCIC
+-#undef CONFIG_I82092
+-#undef CONFIG_I82365
+-
+-/*
+- * PCI Hotplug Support
+- */
+-#undef CONFIG_HOTPLUG_PCI
+-#undef CONFIG_HOTPLUG_PCI_COMPAQ
+-#undef CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM
+-#undef CONFIG_HOTPLUG_PCI_IBM
+-#undef CONFIG_HOTPLUG_PCI_ACPI
+-#define CONFIG_SYSVIPC 1
+-#undef CONFIG_BSD_PROCESS_ACCT
+-#define CONFIG_SYSCTL 1
+-#define CONFIG_KCORE_ELF 1
+-#undef CONFIG_KCORE_AOUT
+-#define CONFIG_BINFMT_AOUT 1
+-#define CONFIG_BINFMT_ELF 1
+-#define CONFIG_BINFMT_MISC 1
+-#define CONFIG_PM 1
+-#undef CONFIG_ACPI
+-#undef CONFIG_APM
+-
+-/*
+- * Memory Technology Devices (MTD)
+- */
+-#undef CONFIG_MTD
+-
+-/*
+- * Parallel port support
+- */
+-#undef CONFIG_PARPORT
+-
+-/*
+- * Plug and Play configuration
+- */
+-#define CONFIG_PNP 1
+-#define CONFIG_ISAPNP 1
+-
+-/*
+- * Block devices
+- */
+-#define CONFIG_BLK_DEV_FD 1
+-#undef CONFIG_BLK_DEV_XD
+-#undef CONFIG_PARIDE
+-#undef CONFIG_BLK_CPQ_DA
+-#undef CONFIG_BLK_CPQ_CISS_DA
+-#undef CONFIG_CISS_SCSI_TAPE
+-#undef CONFIG_BLK_DEV_DAC960
+-#undef CONFIG_BLK_DEV_UMEM
+-#undef CONFIG_BLK_DEV_LOOP
+-#undef CONFIG_BLK_DEV_NBD
+-#define CONFIG_BLK_DEV_RAM 1
+-#define CONFIG_BLK_DEV_RAM_SIZE (4096)
+-#define CONFIG_BLK_DEV_INITRD 1
+-#undef CONFIG_BLK_STATS
+-
+-/*
+- * Multi-device support (RAID and LVM)
+- */
+-#undef CONFIG_MD
+-#undef CONFIG_BLK_DEV_MD
+-#undef CONFIG_MD_LINEAR
+-#undef CONFIG_MD_RAID0
+-#undef CONFIG_MD_RAID1
+-#undef CONFIG_MD_RAID5
+-#undef CONFIG_MD_MULTIPATH
+-#undef CONFIG_BLK_DEV_LVM
+-
+-/*
+- * Networking options
+- */
+-#define CONFIG_PACKET 1
+-#undef CONFIG_PACKET_MMAP
+-#undef CONFIG_NETLINK_DEV
+-#undef CONFIG_NETFILTER
+-#undef CONFIG_FILTER
+-#define CONFIG_UNIX 1
+-#define CONFIG_INET 1
+-#define CONFIG_IP_MULTICAST 1
+-#undef CONFIG_IP_ADVANCED_ROUTER
+-#define CONFIG_IP_PNP 1
+-#define CONFIG_IP_PNP_DHCP 1
+-#undef CONFIG_IP_PNP_BOOTP
+-#undef CONFIG_IP_PNP_RARP
+-#undef CONFIG_NET_IPIP
+-#undef CONFIG_NET_IPGRE
+-#undef CONFIG_IP_MROUTE
+-#undef CONFIG_ARPD
+-#undef CONFIG_INET_ECN
+-#undef CONFIG_SYN_COOKIES
+-#undef CONFIG_IPV6
+-#undef CONFIG_KHTTPD
+-#undef CONFIG_ATM
+-#undef CONFIG_VLAN_8021Q
+-
+-/*
+- *
+- */
+-#undef CONFIG_IPX
+-#undef CONFIG_ATALK
+-
+-/*
+- * Appletalk devices
+- */
+-#undef CONFIG_DEV_APPLETALK
+-#undef CONFIG_DECNET
+-#undef CONFIG_BRIDGE
+-#undef CONFIG_X25
+-#undef CONFIG_LAPB
+-#undef CONFIG_LLC
+-#undef CONFIG_NET_DIVERT
+-#undef CONFIG_ECONET
+-#undef CONFIG_WAN_ROUTER
+-#undef CONFIG_NET_FASTROUTE
+-#undef CONFIG_NET_HW_FLOWCONTROL
+-
+-/*
+- * QoS and/or fair queueing
+- */
+-#undef CONFIG_NET_SCHED
+-
+-/*
+- * Network testing
+- */
+-#undef CONFIG_NET_PKTGEN
+-
+-/*
+- * Telephony Support
+- */
+-#undef CONFIG_PHONE
+-#undef CONFIG_PHONE_IXJ
+-#undef CONFIG_PHONE_IXJ_PCMCIA
+-
+-/*
+- * ATA/IDE/MFM/RLL support
+- */
+-#define CONFIG_IDE 1
+-
+-/*
+- * IDE, ATA and ATAPI Block devices
+- */
+-#define CONFIG_BLK_DEV_IDE 1
+-
+-/*
+- * Please see Documentation/ide.txt for help/info on IDE drives
+- */
+-#undef CONFIG_BLK_DEV_HD_IDE
+-#undef CONFIG_BLK_DEV_HD
+-#define CONFIG_BLK_DEV_IDEDISK 1
+-#define CONFIG_IDEDISK_MULTI_MODE 1
+-#undef CONFIG_IDEDISK_STROKE
+-#undef CONFIG_BLK_DEV_IDEDISK_VENDOR
+-#undef CONFIG_BLK_DEV_IDEDISK_FUJITSU
+-#undef CONFIG_BLK_DEV_IDEDISK_IBM
+-#undef CONFIG_BLK_DEV_IDEDISK_MAXTOR
+-#undef CONFIG_BLK_DEV_IDEDISK_QUANTUM
+-#undef CONFIG_BLK_DEV_IDEDISK_SEAGATE
+-#undef CONFIG_BLK_DEV_IDEDISK_WD
+-#undef CONFIG_BLK_DEV_COMMERIAL
+-#undef CONFIG_BLK_DEV_TIVO
+-#undef CONFIG_BLK_DEV_IDECS
+-#define CONFIG_BLK_DEV_IDECD 1
+-#undef CONFIG_BLK_DEV_IDETAPE
+-#undef CONFIG_BLK_DEV_IDEFLOPPY
+-#undef CONFIG_BLK_DEV_IDESCSI
+-#undef CONFIG_IDE_TASK_IOCTL
+-
+-/*
+- * IDE chipset support/bugfixes
+- */
+-#define CONFIG_BLK_DEV_CMD640 1
+-#undef CONFIG_BLK_DEV_CMD640_ENHANCED
+-#undef CONFIG_BLK_DEV_ISAPNP
+-#define CONFIG_BLK_DEV_RZ1000 1
+-#define CONFIG_BLK_DEV_IDEPCI 1
+-#define CONFIG_IDEPCI_SHARE_IRQ 1
+-#define CONFIG_BLK_DEV_IDEDMA_PCI 1
+-#undef CONFIG_BLK_DEV_OFFBOARD
+-#undef CONFIG_BLK_DEV_IDEDMA_FORCED
+-#define CONFIG_IDEDMA_PCI_AUTO 1
+-#undef CONFIG_IDEDMA_ONLYDISK
+-#define CONFIG_BLK_DEV_IDEDMA 1
+-#undef CONFIG_IDEDMA_PCI_WIP
+-#undef CONFIG_BLK_DEV_IDEDMA_TIMEOUT
+-#undef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS
+-#define CONFIG_BLK_DEV_ADMA 1
+-#undef CONFIG_BLK_DEV_AEC62XX
+-#undef CONFIG_AEC62XX_TUNING
+-#undef CONFIG_BLK_DEV_ALI15X3
+-#undef CONFIG_WDC_ALI15X3
+-#undef CONFIG_BLK_DEV_AMD74XX
+-#undef CONFIG_AMD74XX_OVERRIDE
+-#undef CONFIG_BLK_DEV_CMD64X
+-#undef CONFIG_BLK_DEV_CMD680
+-#undef CONFIG_BLK_DEV_CY82C693
+-#undef CONFIG_BLK_DEV_CS5530
+-#undef CONFIG_BLK_DEV_HPT34X
+-#undef CONFIG_HPT34X_AUTODMA
+-#undef CONFIG_BLK_DEV_HPT366
+-#define CONFIG_BLK_DEV_PIIX 1
+-#define CONFIG_PIIX_TUNING 1
+-#undef CONFIG_BLK_DEV_NS87415
+-#undef CONFIG_BLK_DEV_OPTI621
+-#undef CONFIG_BLK_DEV_PDC202XX
+-#undef CONFIG_PDC202XX_BURST
+-#undef CONFIG_PDC202XX_FORCE
+-#undef CONFIG_BLK_DEV_SVWKS
+-#undef CONFIG_BLK_DEV_SIS5513
+-#undef CONFIG_BLK_DEV_SLC90E66
+-#undef CONFIG_BLK_DEV_TRM290
+-#undef CONFIG_BLK_DEV_VIA82CXXX
+-#undef CONFIG_IDE_CHIPSETS
+-#define CONFIG_IDEDMA_AUTO 1
+-#undef CONFIG_IDEDMA_IVB
+-#undef CONFIG_DMA_NONPCI
+-#define CONFIG_BLK_DEV_IDE_MODES 1
+-#undef CONFIG_BLK_DEV_ATARAID
+-#undef CONFIG_BLK_DEV_ATARAID_PDC
+-#undef CONFIG_BLK_DEV_ATARAID_HPT
+-
+-/*
+- * SCSI support
+- */
+-#undef CONFIG_SCSI
+-
+-/*
+- * Fusion MPT device support
+- */
+-#undef CONFIG_FUSION
+-#undef CONFIG_FUSION_BOOT
+-#undef CONFIG_FUSION_ISENSE
+-#undef CONFIG_FUSION_CTL
+-#undef CONFIG_FUSION_LAN
+-
+-/*
+- * IEEE 1394 (FireWire) support (EXPERIMENTAL)
+- */
+-#undef CONFIG_IEEE1394
+-
+-/*
+- * I2O device support
+- */
+-#undef CONFIG_I2O
+-#undef CONFIG_I2O_PCI
+-#undef CONFIG_I2O_BLOCK
+-#undef CONFIG_I2O_LAN
+-#undef CONFIG_I2O_SCSI
+-#undef CONFIG_I2O_PROC
+-
+-/*
+- * Network device support
+- */
+-#define CONFIG_NETDEVICES 1
+-
+-/*
+- * ARCnet devices
+- */
+-#undef CONFIG_ARCNET
+-#undef CONFIG_DUMMY
+-#define CONFIG_DUMMY_MODULE 1
+-#undef CONFIG_BONDING
+-#undef CONFIG_EQUALIZER
+-#undef CONFIG_TUN
+-#undef CONFIG_ETHERTAP
+-#undef CONFIG_NET_SB1000
+-
+-/*
+- * Ethernet (10 or 100Mbit)
+- */
+-#define CONFIG_NET_ETHERNET 1
+-#undef CONFIG_SUNLANCE
+-#undef CONFIG_HAPPYMEAL
+-#undef CONFIG_SUNBMAC
+-#undef CONFIG_SUNQE
+-#undef CONFIG_SUNGEM
+-#undef CONFIG_NET_VENDOR_3COM
+-#undef CONFIG_LANCE
+-#undef CONFIG_NET_VENDOR_SMC
+-#undef CONFIG_NET_VENDOR_RACAL
+-#undef CONFIG_AT1700
+-#undef CONFIG_DEPCA
+-#undef CONFIG_HP100
+-#undef CONFIG_NET_ISA
+-#define CONFIG_NET_PCI 1
+-#undef CONFIG_PCNET32
+-#undef CONFIG_ADAPTEC_STARFIRE
+-#undef CONFIG_AC3200
+-#undef CONFIG_APRICOT
+-#undef CONFIG_CS89x0
+-#undef CONFIG_TULIP
+-#undef CONFIG_DE4X5
+-#undef CONFIG_DGRS
+-#undef CONFIG_DM9102
+-#define CONFIG_EEPRO100 1
+-#undef CONFIG_E100
+-#undef CONFIG_LNE390
+-#undef CONFIG_FEALNX
+-#undef CONFIG_NATSEMI
+-#undef CONFIG_NE2K_PCI
+-#undef CONFIG_NE3210
+-#undef CONFIG_ES3210
+-#undef CONFIG_8139CP
+-#undef CONFIG_8139TOO
+-#undef CONFIG_8139TOO_PIO
+-#undef CONFIG_8139TOO_TUNE_TWISTER
+-#undef CONFIG_8139TOO_8129
+-#undef CONFIG_8139_OLD_RX_RESET
+-#undef CONFIG_SIS900
+-#undef CONFIG_EPIC100
+-#undef CONFIG_SUNDANCE
+-#undef CONFIG_SUNDANCE_MMIO
+-#undef CONFIG_TLAN
+-#undef CONFIG_TC35815
+-#undef CONFIG_VIA_RHINE
+-#undef CONFIG_VIA_RHINE_MMIO
+-#undef CONFIG_WINBOND_840
+-#undef CONFIG_NET_POCKET
+-
+-/*
+- * Ethernet (1000 Mbit)
+- */
+-#undef CONFIG_ACENIC
+-#undef CONFIG_DL2K
+-#undef CONFIG_E1000
+-#undef CONFIG_MYRI_SBUS
+-#undef CONFIG_NS83820
+-#undef CONFIG_HAMACHI
+-#undef CONFIG_YELLOWFIN
+-#undef CONFIG_SK98LIN
+-#undef CONFIG_TIGON3
+-#undef CONFIG_FDDI
+-#undef CONFIG_HIPPI
+-#undef CONFIG_PLIP
+-#undef CONFIG_PPP
+-#undef CONFIG_SLIP
+-
+-/*
+- * Wireless LAN (non-hamradio)
+- */
+-#undef CONFIG_NET_RADIO
+-
+-/*
+- * Token Ring devices
+- */
+-#undef CONFIG_TR
+-#undef CONFIG_NET_FC
+-#undef CONFIG_RCPCI
+-#undef CONFIG_SHAPER
+-
+-/*
+- * Wan interfaces
+- */
+-#undef CONFIG_WAN
+-
+-/*
+- * PCMCIA network device support
+- */
+-#define CONFIG_NET_PCMCIA 1
+-#undef CONFIG_PCMCIA_3C589
+-#undef CONFIG_PCMCIA_3C574
+-#undef CONFIG_PCMCIA_FMVJ18X
+-#define CONFIG_PCMCIA_PCNET 1
+-#undef CONFIG_PCMCIA_AXNET
+-#undef CONFIG_PCMCIA_NMCLAN
+-#undef CONFIG_PCMCIA_SMC91C92
+-#undef CONFIG_PCMCIA_XIRC2PS
+-#undef CONFIG_ARCNET_COM20020_CS
+-#undef CONFIG_PCMCIA_IBMTR
+-#undef CONFIG_PCMCIA_XIRCOM
+-#undef CONFIG_PCMCIA_XIRTULIP
+-#define CONFIG_NET_PCMCIA_RADIO 1
+-#define CONFIG_PCMCIA_RAYCS 1
+-#undef CONFIG_PCMCIA_NETWAVE
+-#undef CONFIG_PCMCIA_WAVELAN
+-#undef CONFIG_AIRONET4500_CS
+-
+-/*
+- * Amateur Radio support
+- */
+-#undef CONFIG_HAMRADIO
+-
+-/*
+- * IrDA (infrared) support
+- */
+-#undef CONFIG_IRDA
+-
+-/*
+- * ISDN subsystem
+- */
+-#undef CONFIG_ISDN
+-
+-/*
+- * Old CD-ROM drivers (not SCSI, not IDE)
+- */
+-#undef CONFIG_CD_NO_IDESCSI
+-
+-/*
+- * Input core support
+- */
+-#undef CONFIG_INPUT
+-#undef CONFIG_INPUT_KEYBDEV
+-#undef CONFIG_INPUT_MOUSEDEV
+-#undef CONFIG_INPUT_JOYDEV
+-#undef CONFIG_INPUT_EVDEV
+-
+-/*
+- * Character devices
+- */
+-#define CONFIG_VT 1
+-#define CONFIG_VT_CONSOLE 1
+-#define CONFIG_SERIAL 1
+-#define CONFIG_SERIAL_CONSOLE 1
+-#undef CONFIG_SERIAL_EXTENDED
+-#undef CONFIG_SERIAL_NONSTANDARD
+-#define CONFIG_UNIX98_PTYS 1
+-#define CONFIG_UNIX98_PTY_COUNT (256)
+-
+-/*
+- * I2C support
+- */
+-#undef CONFIG_I2C
+-
+-/*
+- * Mice
+- */
+-#undef CONFIG_BUSMOUSE
+-#define CONFIG_MOUSE 1
+-#define CONFIG_PSMOUSE 1
+-#undef CONFIG_82C710_MOUSE
+-#undef CONFIG_PC110_PAD
+-#undef CONFIG_MK712_MOUSE
+-
+-/*
+- * Joysticks
+- */
+-#undef CONFIG_INPUT_GAMEPORT
+-
+-/*
+- * Input core support is needed for gameports
+- */
+-
+-/*
+- * Input core support is needed for joysticks
+- */
+-#undef CONFIG_QIC02_TAPE
+-#undef CONFIG_IPMI_HANDLER
+-#define CONFIG_IPMI_HANDLER_MODULE 1
+-#define CONFIG_IPMI_PANIC_EVENT 1
+-#undef CONFIG_IPMI_DEVICE_INTERFACE
+-#define CONFIG_IPMI_DEVICE_INTERFACE_MODULE 1
+-#undef CONFIG_IPMI_KCS
+-#define CONFIG_IPMI_KCS_MODULE 1
+-#undef CONFIG_IPMI_WATCHDOG
+-#define CONFIG_IPMI_WATCHDOG_MODULE 1
+-
+-/*
+- * Watchdog Cards
+- */
+-#undef CONFIG_WATCHDOG
+-#undef CONFIG_AMD_RNG
+-#undef CONFIG_INTEL_RNG
+-#undef CONFIG_AMD_PM768
+-#undef CONFIG_NVRAM
+-#undef CONFIG_RTC
+-#undef CONFIG_DTLK
+-#undef CONFIG_R3964
+-#undef CONFIG_APPLICOM
+-#undef CONFIG_SONYPI
+-
+-/*
+- * Ftape, the floppy tape device driver
+- */
+-#undef CONFIG_FTAPE
+-#define CONFIG_AGP 1
+-#define CONFIG_AGP_INTEL 1
+-#define CONFIG_AGP_I810 1
+-#define CONFIG_AGP_VIA 1
+-#define CONFIG_AGP_AMD 1
+-#undef CONFIG_AGP_AMD_8151
+-#define CONFIG_AGP_SIS 1
+-#define CONFIG_AGP_ALI 1
+-#undef CONFIG_AGP_SWORKS
+-#define CONFIG_DRM 1
+-#undef CONFIG_DRM_OLD
+-
+-/*
+- * DRM 4.1 drivers
+- */
+-#define CONFIG_DRM_NEW 1
+-#define CONFIG_DRM_TDFX 1
+-#undef CONFIG_DRM_R128
+-#define CONFIG_DRM_RADEON 1
+-#undef CONFIG_DRM_I810
+-#undef CONFIG_DRM_I810_XFREE_41
+-#undef CONFIG_DRM_I830
+-#undef CONFIG_DRM_MGA
+-#undef CONFIG_DRM_SIS
+-
+-/*
+- * PCMCIA character devices
+- */
+-#undef CONFIG_PCMCIA_SERIAL_CS
+-#undef CONFIG_SYNCLINK_CS
+-#undef CONFIG_MWAVE
+-
+-/*
+- * Multimedia devices
+- */
+-#undef CONFIG_VIDEO_DEV
+-
+-/*
+- * File systems
+- */
+-#undef CONFIG_QUOTA
+-#undef CONFIG_AUTOFS_FS
+-#define CONFIG_AUTOFS4_FS 1
+-#undef CONFIG_REISERFS_FS
+-#undef CONFIG_REISERFS_CHECK
+-#undef CONFIG_REISERFS_PROC_INFO
+-#undef CONFIG_ADFS_FS
+-#undef CONFIG_ADFS_FS_RW
+-#undef CONFIG_AFFS_FS
+-#undef CONFIG_HFS_FS
+-#undef CONFIG_BEFS_FS
+-#undef CONFIG_BEFS_DEBUG
+-#undef CONFIG_BFS_FS
+-#undef CONFIG_EXT3_FS
+-#undef CONFIG_JBD
+-#undef CONFIG_JBD_DEBUG
+-#undef CONFIG_FAT_FS
+-#undef CONFIG_MSDOS_FS
+-#undef CONFIG_UMSDOS_FS
+-#undef CONFIG_VFAT_FS
+-#undef CONFIG_EFS_FS
+-#undef CONFIG_JFFS_FS
+-#undef CONFIG_JFFS2_FS
+-#undef CONFIG_CRAMFS
+-#define CONFIG_TMPFS 1
+-#define CONFIG_RAMFS 1
+-#define CONFIG_ISO9660_FS 1
+-#undef CONFIG_JOLIET
+-#undef CONFIG_ZISOFS
+-#undef CONFIG_JFS_FS
+-#undef CONFIG_JFS_DEBUG
+-#undef CONFIG_JFS_STATISTICS
+-#undef CONFIG_MINIX_FS
+-#undef CONFIG_VXFS_FS
+-#undef CONFIG_NTFS_FS
+-#undef CONFIG_NTFS_RW
+-#undef CONFIG_HPFS_FS
+-#define CONFIG_PROC_FS 1
+-#undef CONFIG_DEVFS_FS
+-#undef CONFIG_DEVFS_MOUNT
+-#undef CONFIG_DEVFS_DEBUG
+-#define CONFIG_DEVPTS_FS 1
+-#undef CONFIG_QNX4FS_FS
+-#undef CONFIG_QNX4FS_RW
+-#undef CONFIG_ROMFS_FS
+-#define CONFIG_EXT2_FS 1
+-#undef CONFIG_SYSV_FS
+-#undef CONFIG_UDF_FS
+-#undef CONFIG_UDF_RW
+-#undef CONFIG_UFS_FS
+-#undef CONFIG_UFS_FS_WRITE
+-
+-/*
+- * Network File Systems
+- */
+-#undef CONFIG_CODA_FS
+-#undef CONFIG_INTERMEZZO_FS
+-#define CONFIG_NFS_FS 1
+-#define CONFIG_NFS_V3 1
+-#define CONFIG_ROOT_NFS 1
+-#undef CONFIG_NFSD
+-#undef CONFIG_NFSD_V3
+-#undef CONFIG_NFSD_TCP
+-#define CONFIG_SUNRPC 1
+-#define CONFIG_LOCKD 1
+-#define CONFIG_LOCKD_V4 1
+-#undef CONFIG_SMB_FS
+-#undef CONFIG_NCP_FS
+-#undef CONFIG_NCPFS_PACKET_SIGNING
+-#undef CONFIG_NCPFS_IOCTL_LOCKING
+-#undef CONFIG_NCPFS_STRONG
+-#undef CONFIG_NCPFS_NFS_NS
+-#undef CONFIG_NCPFS_OS2_NS
+-#undef CONFIG_NCPFS_SMALLDOS
+-#undef CONFIG_NCPFS_NLS
+-#undef CONFIG_NCPFS_EXTRAS
+-#undef CONFIG_ZISOFS_FS
+-
+-/*
+- * Partition Types
+- */
+-#undef CONFIG_PARTITION_ADVANCED
+-#define CONFIG_MSDOS_PARTITION 1
+-#undef CONFIG_SMB_NLS
+-#undef CONFIG_NLS
+-
+-/*
+- * Console drivers
+- */
+-#define CONFIG_VGA_CONSOLE 1
+-#undef CONFIG_VIDEO_SELECT
+-#undef CONFIG_MDA_CONSOLE
+-
+-/*
+- * Frame-buffer support
+- */
+-#undef CONFIG_FB
+-
+-/*
+- * Sound
+- */
+-#define CONFIG_SOUND 1
+-#undef CONFIG_SOUND_ALI5455
+-#undef CONFIG_SOUND_BT878
+-#undef CONFIG_SOUND_CMPCI
+-#undef CONFIG_SOUND_EMU10K1
+-#undef CONFIG_MIDI_EMU10K1
+-#undef CONFIG_SOUND_FUSION
+-#undef CONFIG_SOUND_CS4281
+-#undef CONFIG_SOUND_ES1370
+-#define CONFIG_SOUND_ES1371 1
+-#undef CONFIG_SOUND_ESSSOLO1
+-#undef CONFIG_SOUND_MAESTRO
+-#undef CONFIG_SOUND_MAESTRO3
+-#undef CONFIG_SOUND_FORTE
+-#undef CONFIG_SOUND_ICH
+-#undef CONFIG_SOUND_RME96XX
+-#undef CONFIG_SOUND_SONICVIBES
+-#undef CONFIG_SOUND_TRIDENT
+-#undef CONFIG_SOUND_MSNDCLAS
+-#undef CONFIG_SOUND_MSNDPIN
+-#undef CONFIG_SOUND_VIA82CXXX
+-#undef CONFIG_MIDI_VIA82CXXX
+-#undef CONFIG_SOUND_OSS
+-#undef CONFIG_SOUND_TVMIXER
+-
+-/*
+- * USB support
+- */
+-#define CONFIG_USB 1
+-#undef CONFIG_USB_DEBUG
+-
+-/*
+- * Miscellaneous USB options
+- */
+-#undef CONFIG_USB_DEVICEFS
+-#undef CONFIG_USB_BANDWIDTH
+-#undef CONFIG_USB_LONG_TIMEOUT
+-
+-/*
+- * USB Host Controller Drivers
+- */
+-#undef CONFIG_USB_EHCI_HCD
+-#define CONFIG_USB_UHCI_ALT 1
+-#undef CONFIG_USB_OHCI
+-
+-/*
+- * USB Device Class drivers
+- */
+-#undef CONFIG_USB_AUDIO
+-#undef CONFIG_USB_EMI26
+-#undef CONFIG_USB_BLUETOOTH
+-#undef CONFIG_USB_MIDI
+-
+-/*
+- * SCSI support is needed for USB Storage
+- */
+-#undef CONFIG_USB_STORAGE
+-#undef CONFIG_USB_STORAGE_DEBUG
+-#undef CONFIG_USB_STORAGE_DATAFAB
+-#undef CONFIG_USB_STORAGE_FREECOM
+-#undef CONFIG_USB_STORAGE_ISD200
+-#undef CONFIG_USB_STORAGE_DPCM
+-#undef CONFIG_USB_STORAGE_HP8200e
+-#undef CONFIG_USB_STORAGE_SDDR09
+-#undef CONFIG_USB_STORAGE_SDDR55
+-#undef CONFIG_USB_STORAGE_JUMPSHOT
+-#undef CONFIG_USB_ACM
+-#undef CONFIG_USB_PRINTER
+-
+-/*
+- * USB Human Interface Devices (HID)
+- */
+-#undef CONFIG_USB_HID
+-
+-/*
+- * Input core support is needed for USB HID input layer or HIDBP support
+- */
+-#undef CONFIG_USB_HIDINPUT
+-#undef CONFIG_USB_HIDDEV
+-#undef CONFIG_USB_KBD
+-#undef CONFIG_USB_MOUSE
+-#undef CONFIG_USB_AIPTEK
+-#undef CONFIG_USB_WACOM
+-
+-/*
+- * USB Imaging devices
+- */
+-#undef CONFIG_USB_DC2XX
+-#undef CONFIG_USB_MDC800
+-#undef CONFIG_USB_SCANNER
+-#undef CONFIG_USB_MICROTEK
+-#undef CONFIG_USB_HPUSBSCSI
+-
+-/*
+- * USB Multimedia devices
+- */
+-
+-/*
+- * Video4Linux support is needed for USB Multimedia device support
+- */
+-
+-/*
+- * USB Network adaptors
+- */
+-#undef CONFIG_USB_PEGASUS
+-#undef CONFIG_USB_RTL8150
+-#undef CONFIG_USB_KAWETH
+-#undef CONFIG_USB_CATC
+-#undef CONFIG_USB_CDCETHER
+-#undef CONFIG_USB_USBNET
+-
+-/*
+- * USB port drivers
+- */
+-#undef CONFIG_USB_USS720
+-
+-/*
+- * USB Serial Converter support
+- */
+-#undef CONFIG_USB_SERIAL
+-
+-/*
+- * USB Miscellaneous drivers
+- */
+-#undef CONFIG_USB_RIO500
+-#undef CONFIG_USB_AUERSWALD
+-#undef CONFIG_USB_TIGL
+-#undef CONFIG_USB_BRLVGER
+-#undef CONFIG_USB_LCD
+-
+-/*
+- * Bluetooth support
+- */
+-#undef CONFIG_BLUEZ
+-
+-/*
+- * Kernel hacking
+- */
+-#define CONFIG_DEBUG_KERNEL 1
+-#undef CONFIG_DEBUG_STACKOVERFLOW
+-#undef CONFIG_DEBUG_HIGHMEM
+-#undef CONFIG_DEBUG_SLAB
+-#undef CONFIG_DEBUG_IOVIRT
+-#undef CONFIG_MAGIC_SYSRQ
+-#undef CONFIG_DEBUG_SPINLOCK
+-#undef CONFIG_FRAME_POINTER
+-
+-/*
+- * Library routines
+- */
+-#undef CONFIG_ZLIB_INFLATE
+-#undef CONFIG_ZLIB_DEFLATE
+diff -urN linux/include/linux/ipmi_imb.h linux-emu/include/linux/ipmi_imb.h
+--- linux/include/linux/ipmi_imb.h Wed Dec 31 18:00:00 1969
++++ linux-emu/include/linux/ipmi_imb.h Fri Jan 10 11:24:14 2003
+@@ -0,0 +1,144 @@
++/*
++ * ipmi_imb.h
++ *
++ * Intels IMB emulation on the MontaVista IPMI interface
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __LINUX_IPMI_IMB_H
++#define __LINUX_IPMI_IMB_H
++
++typedef struct overlapped_s {
++ unsigned long Internal;
++ unsigned long InternalHigh;
++ unsigned long Offset;
++ unsigned long OffsetHigh;
++} overlapped_t;
++
++struct smi {
++ unsigned long smi_VersionNo;
++ unsigned long smi_Reserved1;
++ unsigned long smi_Reserved2;
++ void *ntstatus; /* address of NT status block*/
++ void *lpvInBuffer; /* address of buffer for input data*/
++ unsigned long cbInBuffer; /* size of input buffer*/
++ void *lpvOutBuffer; /* address of output buffer*/
++ unsigned long cbOutBuffer; /* size of output buffer*/
++ unsigned long *lpcbBytesReturned; /* address of actual bytes of output*/
++ overlapped_t *lpoOverlapped; /* address of overlapped structure*/
++};
++
++
++#define MAX_IMB_PACKET_SIZE 33
++
++typedef struct {
++ unsigned char rsSa;
++ unsigned char cmd;
++ unsigned char netFn;
++ unsigned char rsLun;
++ unsigned char dataLength;
++ unsigned char data[1];
++} ImbRequest;
++
++typedef struct {
++ unsigned long flags;
++#define NO_RESPONSE_EXPECTED 0x01
++
++ unsigned long timeOut;
++ ImbRequest req;
++} ImbRequestBuffer;
++
++#define MIN_IMB_REQ_BUF_SIZE 13
++
++
++typedef struct {
++ unsigned char cCode;
++ unsigned char data[1];
++} ImbResponseBuffer;
++
++#define MIN_IMB_RESP_BUF_SIZE 1 // a buffer without any request data
++#define MAX_IMB_RESP_SIZE (MIN_IMB_RESP_BUF_SIZE + MAX_IMB_RESPONSE_SIZE)
++
++#define MIN_IMB_RESPONSE_SIZE 7
++#define MAX_IMB_RESPONSE_SIZE MAX_IMB_PACKET_SIZE
++
++typedef struct {
++ unsigned long timeOut;
++ unsigned long lastSeq;
++} ImbAsyncRequest;
++
++typedef struct {
++ unsigned long thisSeq;
++ unsigned char data[1];
++} ImbAsyncResponse;
++
++#define MIN_ASYNC_RESP_SIZE sizeof(unsigned long)
++#define MAX_ASYNC_RESP_SIZE (MIN_ASYNC_RESP_SIZE + MAX_IMB_PACKET_SIZE)
++
++#define STATUS_SUCCESS (0x00000000U)
++#define IMB_NO_ASYNC_MSG ((unsigned long)0xE0070012L)
++#define IMB_SEND_REQUEST_FAILED ((unsigned long)0xE0070013L)
++#define INVALID_ARGUMENTS ((unsigned long)0xE0070002L)
++
++
++#define FILE_DEVICE_IMB 0x00008010
++#define IOCTL_IMB_BASE 0x00000880
++
++#define CTL_CODE(DeviceType, Function, Method, Access)\
++ _IO(DeviceType & 0x00FF, Function & 0x00FF)
++
++#define FILE_DEVICE_IMB 0x00008010
++#define IOCTL_IMB_BASE 0x00000880
++#define METHOD_BUFFERED 0
++#define FILE_ANY_ACCESS 0
++
++
++typedef struct {
++ int code;
++#define SD_NO_ACTION 0
++#define SD_RESET 1
++#define SD_POWER_OFF 2
++
++ int delayTime; /* in units of 100 millisecond */
++} ShutdownCmdBuffer;
++
++
++/* BMC added parentheses around IOCTL_IMB_BASE + 2 */
++#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 /* __LINUX_IPMI_IMB_H */
+diff -urN linux/include/linux/ipmi_radisys.h linux-emu/include/linux/ipmi_radisys.h
+--- linux/include/linux/ipmi_radisys.h Wed Dec 31 18:00:00 1969
++++ linux-emu/include/linux/ipmi_radisys.h Fri Jan 10 11:24:14 2003
+@@ -0,0 +1,128 @@
++/*
++ * ipmi_radisys.h
++ *
++ * An emulation of the Radisys IPMI interface on top of the MontaVista
++ * interface.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __LINUX_IPMI_RADISYS_H
++#define __LINUX_IPMI_RADISYS_H
++
++/******************************************************************************
++ * This is the old IPMI interface defined by Radisys. We are
++ * compliant with that. Don't use it for new designs, though.
++ */
++#define IOCTL_IPMI_RCV ( IPMI_IOC_MAGIC<<8 | 1 )
++#define IOCTL_IPMI_SEND ( IPMI_IOC_MAGIC<<8 | 2 )
++#define IOCTL_IPMI_EVENT ( IPMI_IOC_MAGIC<<8 | 3 )
++#define IOCTL_IPMI_REGISTER ( IPMI_IOC_MAGIC<<8 | 4 )
++#define IOCTL_IPMI_UNREGISTER ( IPMI_IOC_MAGIC<<8 | 5 )
++#define IOCTL_IPMI_CLEAR ( IPMI_IOC_MAGIC<<8 | 9 )
++
++/* These don't seem to be implemented in the Radisys driver.
++#define IOCTL_IPMI_RESET_BMC ( IPMI_IOC_MAGIC<<8 | 6 )
++#define IOCTL_IPMI_GET_BMC_ADDR ( IPMI_IOC_MAGIC<<8 | 7 )
++#define IOCTL_IPMI_SET_BMC_ADDR ( IPMI_IOC_MAGIC<<8 | 8 )
++*/
++
++/*
++ * Network Function Codes
++ */
++#define IPMI_NETFN_CHASSIS 0x00 /* Chassis - 0x00 << 2 */
++#define IPMI_NETFN_CHASSIS_RESP 0x04 /* Chassis - 0x01 << 2 */
++
++#define IPMI_NETFN_BRIDGE 0x08 /* Bridge - 0x02 << 2 */
++#define IPMI_NETFN_BRIDGE_RESP 0x0c /* Bridge - 0x03 << 2 */
++
++#define IPMI_NETFN_SENSOR_EVT 0x10 /* Sensor/Event - 0x04 << 2 */
++#define IPMI_NETFN_SENSOR_EVT_RESP 0x14 /* Sensor/Event - 0x05 << 2 */
++
++#define IPMI_NETFN_APP 0x18 /* Application - 0x06 << 2 */
++#define IPMI_NETFN_APP_RESP 0x1c /* Application - 0x07 << 2 */
++
++#define IPMI_NETFN_FIRMWARE 0x20 /* Firmware - 0x08 << 2 */
++#define IPMI_NETFN_FIRMWARE_RESP 0x24 /* Firmware - 0x09 << 2 */
++
++#define IPMI_NETFN_STORAGE 0x28 /* Storage - 0x0a << 2 */
++#define IPMI_NETFN_STORAGE_RESP 0x2c /* Storage - 0x0b << 2 */
++
++#define IPMI_NETFN_OEM_1 0xC0 /* Storage - 0x30 << 2 */
++#define IPMI_NETFN_OEM_1_RESP 0xC4 /* Storage - 0x31 << 2 */
++
++/* there are 15 other OEM netfn pairs (OEM - 0x30-0x3f) */
++
++typedef struct _IPMI_LIST_ENTRY {
++ struct _IPMI_LIST_ENTRY * volatile Flink;
++ struct _IPMI_LIST_ENTRY * volatile Blink;
++} IPMI_LIST_ENTRY, *PIPMI_LIST_ENTRY;
++
++typedef struct IPMI_semaphore IPMI_KSEMAPHORE;
++typedef struct IPMI_semaphore * IPMI_PKSEMAPHORE;
++
++/* IPMI Address structure */
++typedef struct _IPMI_ADDR {
++ unsigned char uchSlave; /* Slave Address */
++ unsigned char uchLun; /* Logical Unit Number */
++} IPMI_ADDR, *PIPMI_ADDR;
++
++#define IPMI_MAX_MSG_SIZE 36
++
++/* IPMI Message Descriptor structure */
++typedef struct _IPMI_MSGDESC {
++ /************************************/
++ /* Device Driver Specific Elements */
++ /************************************/
++ IPMI_LIST_ENTRY Entry; /* Linked list element */
++ void *pIRPacket; /* Pointer to IRP object */
++ IPMI_PKSEMAPHORE pSema; /* Semaphore Object */
++ long lTimeout; /* Timeout value */
++ /************************************/
++ /* Shared elements */
++ /************************************/
++ unsigned char auchBuffer[IPMI_MAX_MSG_SIZE]; /* Message buffer */
++ unsigned long ulLength; /* Length of message in bytes */
++ int fDefer; /* TRUE - Defer I/O
++ operation, doesn't seem
++ to be used in the
++ Radisys driver. */
++ IPMI_ADDR Dest; /* Destination IPM Address */
++ unsigned char uchNetFn; /* Network Function */
++ unsigned char uchCmd; /* Command */
++ unsigned char uchSeq; /* Sequence Number */
++ unsigned char uchComplete; /* Completion Code */
++} IPMI_MSGDESC, *PIPMI_MSGDESC;
++
++/* Byte return codes for some things. */
++#define LOWLRC_SUCCESS 0x00 /* routine completed successfully */
++#define LOWLRC_ERROR 0xff /* routine did not complete */
++#define LOWLRC_INVALID_PARAMETERS 0xfe /* invalid parameters */
++#define LOWLRC_INVALID_REQUEST_DATA 0xfd /* invalid request data */
++
++#endif /* __LINUX_IPMI_RADISYS_H */
diff --git a/kern/openipmi-emu-rh80.patch b/kern/openipmi-emu-rh80.patch
new file mode 100644
index 0000000..a7e46a0
--- /dev/null
+++ b/kern/openipmi-emu-rh80.patch
@@ -0,0 +1,1904 @@
+--- linux-2.4.18-14orig/Documentation/Configure.help 2003-03-27 15:37:28.000000000 -0500
++++ linux-2.4.18-14/Documentation/Configure.help 2003-03-27 15:32:58.000000000 -0500
+@@ -25590,6 +25590,17 @@
+ CONFIG_IPMI_WATCHDOG
+ This enables the IPMI watchdog timer.
+
++Emulate Radisys IPMI driver
++CONFIG_IPMI_EMULATE_RADISYS
++ This enables emulation of the Radisys IPMI device driver.
++
++Emulate Intel IBM driver
++CONFIG_IPMI_EMULATE_IMB
++ This enables emulation of the Intel IMB device driver. Note that you
++ MUST have the IPMI watchdog timer enabled to use this. This code
++ uses some of the watchdog code, but the dependency is not enforced
++ by config.
++
+ #
+ # A couple of things I keep forgetting:
+ # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
+--- linux-2.4.18-14orig/drivers/char/Config.in 2003-03-27 15:37:28.000000000 -0500
++++ linux-2.4.18-14/drivers/char/Config.in 2003-03-27 15:32:58.000000000 -0500
+@@ -180,6 +180,8 @@
+ dep_tristate ' Device interface for IPMI' CONFIG_IPMI_DEVICE_INTERFACE $CONFIG_IPMI_HANDLER
+ dep_tristate ' IPMI KCS handler' CONFIG_IPMI_KCS $CONFIG_IPMI_HANDLER
+ dep_tristate ' IPMI Watchdog Timer' CONFIG_IPMI_WATCHDOG $CONFIG_IPMI_HANDLER
++dep_tristate ' Emulate Radisys IPMI driver' CONFIG_IPMI_EMULATE_RADISYS $CONFIG_IPMI_HANDLER
++dep_tristate ' Emulate Intel IMB driver' CONFIG_IPMI_EMULATE_IMB $CONFIG_IPMI_WATCHDOG
+
+ mainmenu_option next_comment
+ comment 'Watchdog Cards'
+--- linux-2.4.18-14orig/drivers/char/ipmi/Makefile 2003-03-27 15:37:28.000000000 -0500
++++ linux-2.4.18-14/drivers/char/ipmi/Makefile 2003-03-27 15:32:58.000000000 -0500
+@@ -13,6 +13,8 @@
+ obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
+ obj-$(CONFIG_IPMI_KCS) += ipmi_kcs_drv.o
+ obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
++obj-$(CONFIG_IPMI_EMULATE_RADISYS) += ipmi_radisys.o
++obj-$(CONFIG_IPMI_EMULATE_IMB) += ipmi_imb.o
+
+ include $(TOPDIR)/Rules.make
+
+--- /dev/null 2002-08-30 19:31:37.000000000 -0400
++++ linux-2.4.18-14/include/linux/ipmi_imb.h 2003-03-27 15:33:11.000000000 -0500
+@@ -0,0 +1,144 @@
++/*
++ * ipmi_imb.h
++ *
++ * Intels IMB emulation on the MontaVista IPMI interface
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __LINUX_IPMI_IMB_H
++#define __LINUX_IPMI_IMB_H
++
++typedef struct overlapped_s {
++ unsigned long Internal;
++ unsigned long InternalHigh;
++ unsigned long Offset;
++ unsigned long OffsetHigh;
++} overlapped_t;
++
++struct smi {
++ unsigned long smi_VersionNo;
++ unsigned long smi_Reserved1;
++ unsigned long smi_Reserved2;
++ void *ntstatus; /* address of NT status block*/
++ void *lpvInBuffer; /* address of buffer for input data*/
++ unsigned long cbInBuffer; /* size of input buffer*/
++ void *lpvOutBuffer; /* address of output buffer*/
++ unsigned long cbOutBuffer; /* size of output buffer*/
++ unsigned long *lpcbBytesReturned; /* address of actual bytes of output*/
++ overlapped_t *lpoOverlapped; /* address of overlapped structure*/
++};
++
++
++#define MAX_IMB_PACKET_SIZE 33
++
++typedef struct {
++ unsigned char rsSa;
++ unsigned char cmd;
++ unsigned char netFn;
++ unsigned char rsLun;
++ unsigned char dataLength;
++ unsigned char data[1];
++} ImbRequest;
++
++typedef struct {
++ unsigned long flags;
++#define NO_RESPONSE_EXPECTED 0x01
++
++ unsigned long timeOut;
++ ImbRequest req;
++} ImbRequestBuffer;
++
++#define MIN_IMB_REQ_BUF_SIZE 13
++
++
++typedef struct {
++ unsigned char cCode;
++ unsigned char data[1];
++} ImbResponseBuffer;
++
++#define MIN_IMB_RESP_BUF_SIZE 1 // a buffer without any request data
++#define MAX_IMB_RESP_SIZE (MIN_IMB_RESP_BUF_SIZE + MAX_IMB_RESPONSE_SIZE)
++
++#define MIN_IMB_RESPONSE_SIZE 7
++#define MAX_IMB_RESPONSE_SIZE MAX_IMB_PACKET_SIZE
++
++typedef struct {
++ unsigned long timeOut;
++ unsigned long lastSeq;
++} ImbAsyncRequest;
++
++typedef struct {
++ unsigned long thisSeq;
++ unsigned char data[1];
++} ImbAsyncResponse;
++
++#define MIN_ASYNC_RESP_SIZE sizeof(unsigned long)
++#define MAX_ASYNC_RESP_SIZE (MIN_ASYNC_RESP_SIZE + MAX_IMB_PACKET_SIZE)
++
++#define STATUS_SUCCESS (0x00000000U)
++#define IMB_NO_ASYNC_MSG ((unsigned long)0xE0070012L)
++#define IMB_SEND_REQUEST_FAILED ((unsigned long)0xE0070013L)
++#define INVALID_ARGUMENTS ((unsigned long)0xE0070002L)
++
++
++#define FILE_DEVICE_IMB 0x00008010
++#define IOCTL_IMB_BASE 0x00000880
++
++#define CTL_CODE(DeviceType, Function, Method, Access)\
++ _IO(DeviceType & 0x00FF, Function & 0x00FF)
++
++#define FILE_DEVICE_IMB 0x00008010
++#define IOCTL_IMB_BASE 0x00000880
++#define METHOD_BUFFERED 0
++#define FILE_ANY_ACCESS 0
++
++
++typedef struct {
++ int code;
++#define SD_NO_ACTION 0
++#define SD_RESET 1
++#define SD_POWER_OFF 2
++
++ int delayTime; /* in units of 100 millisecond */
++} ShutdownCmdBuffer;
++
++
++/* BMC added parentheses around IOCTL_IMB_BASE + 2 */
++#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 /* __LINUX_IPMI_IMB_H */
+--- /dev/null 2002-08-30 19:31:37.000000000 -0400
++++ linux-2.4.18-14/include/linux/ipmi_radisys.h 2003-03-27 15:33:11.000000000 -0500
+@@ -0,0 +1,128 @@
++/*
++ * ipmi_radisys.h
++ *
++ * An emulation of the Radisys IPMI interface on top of the MontaVista
++ * interface.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __LINUX_IPMI_RADISYS_H
++#define __LINUX_IPMI_RADISYS_H
++
++/******************************************************************************
++ * This is the old IPMI interface defined by Radisys. We are
++ * compliant with that. Don't use it for new designs, though.
++ */
++#define IOCTL_IPMI_RCV ( IPMI_IOC_MAGIC<<8 | 1 )
++#define IOCTL_IPMI_SEND ( IPMI_IOC_MAGIC<<8 | 2 )
++#define IOCTL_IPMI_EVENT ( IPMI_IOC_MAGIC<<8 | 3 )
++#define IOCTL_IPMI_REGISTER ( IPMI_IOC_MAGIC<<8 | 4 )
++#define IOCTL_IPMI_UNREGISTER ( IPMI_IOC_MAGIC<<8 | 5 )
++#define IOCTL_IPMI_CLEAR ( IPMI_IOC_MAGIC<<8 | 9 )
++
++/* These don't seem to be implemented in the Radisys driver.
++#define IOCTL_IPMI_RESET_BMC ( IPMI_IOC_MAGIC<<8 | 6 )
++#define IOCTL_IPMI_GET_BMC_ADDR ( IPMI_IOC_MAGIC<<8 | 7 )
++#define IOCTL_IPMI_SET_BMC_ADDR ( IPMI_IOC_MAGIC<<8 | 8 )
++*/
++
++/*
++ * Network Function Codes
++ */
++#define IPMI_NETFN_CHASSIS 0x00 /* Chassis - 0x00 << 2 */
++#define IPMI_NETFN_CHASSIS_RESP 0x04 /* Chassis - 0x01 << 2 */
++
++#define IPMI_NETFN_BRIDGE 0x08 /* Bridge - 0x02 << 2 */
++#define IPMI_NETFN_BRIDGE_RESP 0x0c /* Bridge - 0x03 << 2 */
++
++#define IPMI_NETFN_SENSOR_EVT 0x10 /* Sensor/Event - 0x04 << 2 */
++#define IPMI_NETFN_SENSOR_EVT_RESP 0x14 /* Sensor/Event - 0x05 << 2 */
++
++#define IPMI_NETFN_APP 0x18 /* Application - 0x06 << 2 */
++#define IPMI_NETFN_APP_RESP 0x1c /* Application - 0x07 << 2 */
++
++#define IPMI_NETFN_FIRMWARE 0x20 /* Firmware - 0x08 << 2 */
++#define IPMI_NETFN_FIRMWARE_RESP 0x24 /* Firmware - 0x09 << 2 */
++
++#define IPMI_NETFN_STORAGE 0x28 /* Storage - 0x0a << 2 */
++#define IPMI_NETFN_STORAGE_RESP 0x2c /* Storage - 0x0b << 2 */
++
++#define IPMI_NETFN_OEM_1 0xC0 /* Storage - 0x30 << 2 */
++#define IPMI_NETFN_OEM_1_RESP 0xC4 /* Storage - 0x31 << 2 */
++
++/* there are 15 other OEM netfn pairs (OEM - 0x30-0x3f) */
++
++typedef struct _IPMI_LIST_ENTRY {
++ struct _IPMI_LIST_ENTRY * volatile Flink;
++ struct _IPMI_LIST_ENTRY * volatile Blink;
++} IPMI_LIST_ENTRY, *PIPMI_LIST_ENTRY;
++
++typedef struct IPMI_semaphore IPMI_KSEMAPHORE;
++typedef struct IPMI_semaphore * IPMI_PKSEMAPHORE;
++
++/* IPMI Address structure */
++typedef struct _IPMI_ADDR {
++ unsigned char uchSlave; /* Slave Address */
++ unsigned char uchLun; /* Logical Unit Number */
++} IPMI_ADDR, *PIPMI_ADDR;
++
++#define IPMI_MAX_MSG_SIZE 36
++
++/* IPMI Message Descriptor structure */
++typedef struct _IPMI_MSGDESC {
++ /************************************/
++ /* Device Driver Specific Elements */
++ /************************************/
++ IPMI_LIST_ENTRY Entry; /* Linked list element */
++ void *pIRPacket; /* Pointer to IRP object */
++ IPMI_PKSEMAPHORE pSema; /* Semaphore Object */
++ long lTimeout; /* Timeout value */
++ /************************************/
++ /* Shared elements */
++ /************************************/
++ unsigned char auchBuffer[IPMI_MAX_MSG_SIZE]; /* Message buffer */
++ unsigned long ulLength; /* Length of message in bytes */
++ int fDefer; /* TRUE - Defer I/O
++ operation, doesn't seem
++ to be used in the
++ Radisys driver. */
++ IPMI_ADDR Dest; /* Destination IPM Address */
++ unsigned char uchNetFn; /* Network Function */
++ unsigned char uchCmd; /* Command */
++ unsigned char uchSeq; /* Sequence Number */
++ unsigned char uchComplete; /* Completion Code */
++} IPMI_MSGDESC, *PIPMI_MSGDESC;
++
++/* Byte return codes for some things. */
++#define LOWLRC_SUCCESS 0x00 /* routine completed successfully */
++#define LOWLRC_ERROR 0xff /* routine did not complete */
++#define LOWLRC_INVALID_PARAMETERS 0xfe /* invalid parameters */
++#define LOWLRC_INVALID_REQUEST_DATA 0xfd /* invalid request data */
++
++#endif /* __LINUX_IPMI_RADISYS_H */
+--- /dev/null 2002-08-30 19:31:37.000000000 -0400
++++ linux-2.4.18-14/drivers/char/ipmi/ipmi_imb.c 2003-03-27 15:32:59.000000000 -0500
+@@ -0,0 +1,744 @@
++/*
++ * ipmi_imb.c
++ *
++ * Intel IMB emulation for the IPMI interface.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <asm/system.h>
++#include <linux/sched.h>
++#include <linux/poll.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/devfs_fs_kernel.h>
++#include <linux/ipmi.h>
++#include <linux/ipmi_imb.h>
++
++
++
++#define MAX_BUFFER_SIZE 64
++#define BMC_SA 0x20
++
++struct priv_data
++{
++ /* This is for supporting the old Imb interface. */
++ ipmi_user_t imb_user;
++ spinlock_t imb_lock;
++
++ unsigned long curr_msgid;
++
++ /* A list of responses in the queue. */
++ struct list_head imb_waiting_rsps;
++
++ /* A list of things waiting for responses. We wake them all up
++ when a response comes in. */
++ wait_queue_head_t imb_waiting_rsp_rcvrs;
++
++ /* A list of commands that have come in. */
++ struct list_head imb_waiting_cmds;
++
++ /* A list of thing waiting for commands. We wake them all up
++ when a command comes in. */
++ wait_queue_head_t imb_waiting_cmd_rcvrs;
++
++ /* The registered command receiver value. This only allows someone
++ with the "magic number" to issue commands. */
++ unsigned long imb_cmd_receiver;
++
++ /* Is someone already waiting for a command? The Imb driver
++ only allows one waiter, this enforces that. */
++ int imb_cmd_waiting;
++
++ /* A list of IPMI events waiting to be delivered. (not that
++ the Imb driver calls incoming commands "events", this
++ variable is actual IPMI events, not incoming commands). */
++ struct list_head imb_waiting_events;
++
++#define IMB_EVENT_QUEUE_LIMIT 16 /* Allow up to 16 events. */
++ /* The number of events in the event queue. */
++ unsigned int imb_waiting_event_count;
++};
++
++static devfs_handle_t devfs_handle;
++
++
++/* We cheat and use a piece of the address as the timeout. */
++static long *imb_timeout(struct ipmi_recv_msg *msg)
++{
++ char *base = (char *) &(msg->addr);
++ base += sizeof(struct ipmi_ipmb_addr);
++ return (long *) base;
++}
++
++static void imb_msg_recv(struct ipmi_recv_msg *msg,
++ void *data)
++{
++ struct priv_data *priv = data;
++ unsigned long flags;
++
++ spin_lock_irqsave(&(priv->imb_lock), flags);
++ if (msg->recv_type == IPMI_RESPONSE_RECV_TYPE) {
++ *imb_timeout(msg) = 5000;
++ list_add_tail(&(msg->link), &(priv->imb_waiting_rsps));
++ wake_up_all(&(priv->imb_waiting_rsp_rcvrs));
++ } else if (msg->recv_type == IPMI_CMD_RECV_TYPE) {
++ *imb_timeout(msg) = 5000;
++ list_add_tail(&(msg->link), &(priv->imb_waiting_cmds));
++ wake_up_all(&(priv->imb_waiting_cmd_rcvrs));
++ } else if (msg->recv_type == IPMI_ASYNC_EVENT_RECV_TYPE) {
++ if (priv->imb_waiting_event_count > IMB_EVENT_QUEUE_LIMIT) {
++ ipmi_free_recv_msg(msg);
++ } else {
++ list_add_tail(&(msg->link),&(priv->imb_waiting_events));
++ (priv->imb_waiting_event_count)++;
++ }
++ } else {
++ ipmi_free_recv_msg(msg);
++ }
++ spin_unlock_irqrestore(&(priv->imb_lock), flags);
++}
++
++/* We emulate the event queue in the driver for the imb emulation. */
++static int imb_handle_event_request(struct priv_data *priv,
++ struct ipmi_recv_msg **rsp)
++{
++ struct list_head *entry;
++ unsigned long flags;
++ struct ipmi_recv_msg *msg = NULL;
++ int rv = 0;
++
++ spin_lock_irqsave(&(priv->imb_lock), flags);
++ if (list_empty(&(priv->imb_waiting_events))) {
++ /* Nothing in the event queue, just return an error. */
++ msg = ipmi_alloc_recv_msg();
++ if (msg == NULL) {
++ rv = -EAGAIN;
++ goto out_err;
++ }
++ msg->addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ msg->addr.channel = IPMI_BMC_CHANNEL;
++ msg->msg.cmd = IPMI_READ_EVENT_MSG_BUFFER_CMD;
++ msg->msgid = 0;
++ msg->recv_type = IPMI_ASYNC_EVENT_RECV_TYPE;
++ msg->msg.netfn = IPMI_NETFN_APP_RESPONSE;
++ msg->msg.data = msg->msg_data;
++ msg->msg.data[0] = 0x80; /* Data not available. */
++ msg->msg.data_len = 1;
++ } else {
++ /* Pull an item from the event queue . */
++ entry = priv->imb_waiting_events.next;
++ list_del(entry);
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ (priv->imb_waiting_event_count)--;
++ }
++
++ *rsp = msg;
++
++ out_err:
++ spin_unlock_irqrestore(&(priv->imb_lock), flags);
++ return rv;
++}
++
++static struct priv_data *ipmi_user;
++static unsigned int user_count = 0; /* How many users have this open. */
++static spinlock_t dev_lock = SPIN_LOCK_UNLOCKED;
++
++static int ipmi_imb_open(struct inode *inode, struct file *file)
++{
++ int rv;
++
++ if (user_count == 0) {
++ rv = ipmi_register_all_cmd_rcvr(ipmi_user->imb_user);
++ if (rv) {
++ return rv;
++ }
++ }
++
++ file->private_data = ipmi_user;
++ spin_lock(&dev_lock);
++ if (user_count == 0)
++ ipmi_set_gets_events(ipmi_user->imb_user, 1);
++ user_count++;
++ spin_unlock(&dev_lock);
++
++ return 0;
++}
++
++static int ipmi_imb_release(struct inode *inode, struct file *file)
++{
++ spin_lock(&dev_lock);
++ user_count--;
++ if (user_count == 0) {
++ ipmi_set_gets_events(ipmi_user->imb_user, 0);
++ ipmi_unregister_all_cmd_rcvr(ipmi_user->imb_user);
++ }
++ spin_unlock(&dev_lock);
++ return 0;
++}
++
++static unsigned char
++ipmb_checksum(unsigned char *data, int size)
++{
++ unsigned char csum = 0;
++
++ for (; size > 0; size--, data++)
++ csum += *data;
++
++ return -csum;
++}
++
++extern void ipmi_delayed_shutdown(long delay, int power_off);
++
++static int ipmi_imb_ioctl(struct inode *inode,
++ struct file *file,
++ unsigned int cmd,
++ unsigned long data)
++{
++ struct priv_data *priv = file->private_data;
++ int rv = -EINVAL;
++ struct smi smi;
++ unsigned long flags;
++
++ if (copy_from_user((caddr_t)&smi, (caddr_t)data, sizeof(smi))) {
++ return -EFAULT;
++ }
++
++ switch(cmd) {
++ case IOCTL_IMB_POLL_ASYNC:
++ /*
++ * No-op for this, the low-level driver polls.
++ */
++ break;
++
++ case IOCTL_IMB_GET_ASYNC_MSG:
++ {
++ unsigned char resp[MAX_ASYNC_RESP_SIZE];
++ struct ipmi_recv_msg *msg = NULL;
++ ImbAsyncResponse *pAsyncResp = (ImbAsyncResponse *) resp;
++ unsigned long length = 0;
++
++ if (smi.cbInBuffer < sizeof(ImbAsyncRequest))
++ return -EINVAL;
++ if (smi.cbOutBuffer < MIN_ASYNC_RESP_SIZE)
++ return -EINVAL;
++
++ spin_lock_irqsave(&(priv->imb_lock), flags);
++
++ if (list_empty(&(priv->imb_waiting_cmds))) {
++ /* No command waiting, just return an error. */
++ rv = IMB_NO_ASYNC_MSG;
++ } else {
++ struct list_head *entry;
++
++ /* Got a command, pull it out and handle it. */
++ entry = priv->imb_waiting_cmds.next;
++ list_del(entry);
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ rv = STATUS_SUCCESS;
++ }
++ spin_unlock_irqrestore(&(priv->imb_lock), flags);
++
++ if (msg != NULL) {
++ struct ipmi_ipmb_addr *ipmb_addr;
++
++ ipmb_addr = (struct ipmi_ipmb_addr *) &(msg->addr);
++ pAsyncResp->thisSeq = msg->msgid;
++ pAsyncResp->data[0] = IPMI_NETFN_APP_REQUEST << 2;
++ pAsyncResp->data[1] = IPMI_SEND_MSG_CMD;
++ pAsyncResp->data[2] = 0;
++ pAsyncResp->data[3] = msg->addr.channel;
++ pAsyncResp->data[4] = ((msg->msg.netfn << 2)
++ | 2);
++ pAsyncResp->data[5]
++ = ipmb_checksum(&(pAsyncResp->data[3]),
++ 2);
++ pAsyncResp->data[6] = ipmb_addr->slave_addr;
++ pAsyncResp->data[7] = ((msg->msgid << 2)
++ | ipmb_addr->lun);
++ pAsyncResp->data[8] = msg->msg.cmd;
++
++ memcpy(&(pAsyncResp->data[9]),
++ &(msg->msg.data[0]),
++ msg->msg.data_len);
++
++ length = msg->msg.data_len + MIN_ASYNC_RESP_SIZE;
++
++ ipmi_free_recv_msg(msg);
++
++ if (copy_to_user(smi.lpvOutBuffer, pAsyncResp, length))
++ {
++ return -EFAULT;
++ }
++ }
++
++ if (copy_to_user(smi.lpcbBytesReturned,
++ &length,
++ sizeof(length)))
++ {
++ return -EFAULT;
++ }
++ rv = 0;
++ break;
++ }
++
++ case IOCTL_IMB_SEND_MESSAGE:
++ {
++ unsigned char imbReqBuffer[MAX_IMB_RESPONSE_SIZE + 8];
++ unsigned char imbRespBuffer[MAX_IMB_RESPONSE_SIZE + 8];
++ ImbRequestBuffer *pImbReq=(ImbRequestBuffer *)imbReqBuffer;
++ ImbResponseBuffer *pImbResp=(ImbResponseBuffer*)imbRespBuffer;
++ struct ipmi_addr addr;
++ struct ipmi_msg msg;
++ unsigned long msgid;
++ struct ipmi_recv_msg *rsp;
++ unsigned long length;
++ wait_queue_t wait;
++ struct list_head *entry;
++
++
++ if ((smi.cbInBuffer < MIN_IMB_REQ_BUF_SIZE)
++ || (smi.cbOutBuffer < MIN_IMB_RESP_BUF_SIZE))
++ {
++ return -EINVAL;
++ }
++
++ if (smi.cbInBuffer > (MAX_IMB_RESPONSE_SIZE + 8)) {
++ /* Input buffer is too large */
++ return -EINVAL;
++ }
++
++ if (copy_from_user(pImbReq, smi.lpvInBuffer, smi.cbInBuffer)) {
++ return -EFAULT;
++ }
++ if ((pImbReq->req.dataLength + MIN_IMB_REQ_BUF_SIZE)
++ > smi.cbInBuffer)
++ {
++ return -EINVAL;
++ }
++ if (pImbReq->req.dataLength > MAX_BUFFER_SIZE) {
++ return -EINVAL;
++ }
++
++ if (pImbReq->req.rsSa == BMC_SA) {
++ struct ipmi_system_interface_addr *smi_addr
++ = (struct ipmi_system_interface_addr *) &addr;
++
++ if ((pImbReq->req.netFn
++ == (IPMI_NETFN_APP_REQUEST << 2))
++ && (pImbReq->req.cmd
++ == IPMI_READ_EVENT_MSG_BUFFER_CMD))
++ {
++ /* The driver gets event messages
++ automatically, so we emulate
++ this. */
++ rv = imb_handle_event_request(priv, &rsp);
++ goto copy_resp;
++ } else {
++ smi_addr->addr_type
++ = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr->channel = IPMI_BMC_CHANNEL;
++ smi_addr->lun = 0;
++ }
++ } else {
++ struct ipmi_ipmb_addr *ipmb_addr =
++ (struct ipmi_ipmb_addr *) &addr;
++
++ ipmb_addr->addr_type = IPMI_IPMB_ADDR_TYPE;
++ ipmb_addr->slave_addr = pImbReq->req.rsSa;
++ ipmb_addr->lun = pImbReq->req.rsLun;
++ ipmb_addr->channel = 0;
++ }
++
++ if (pImbReq->flags & NO_RESPONSE_EXPECTED) {
++ spin_lock(&priv->imb_lock);
++ msgid = priv->curr_msgid;
++ (priv->curr_msgid)++;
++ spin_unlock(&priv->imb_lock);
++ } else {
++ msgid = 0;
++ }
++
++ msg.netfn = pImbReq->req.netFn;
++ msg.cmd = pImbReq->req.cmd;
++ msg.data = pImbReq->req.data;
++ msg.data_len = pImbReq->req.dataLength;
++ rv = ipmi_request(priv->imb_user,
++ &addr,
++ msgid,
++ &msg,
++ 0);
++ if (rv) {
++ rv = IMB_SEND_REQUEST_FAILED;
++ goto copy_resp;
++ }
++
++ if (pImbReq->flags & NO_RESPONSE_EXPECTED)
++ goto no_response;
++
++ /* Now wait for the response to come back. */
++ spin_lock_irqsave(&(priv->imb_lock), flags);
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&(priv->imb_waiting_rsp_rcvrs),
++ &wait);
++ for (;;) {
++ /* Check to see if it's there. */
++ if (!list_empty(&(priv->imb_waiting_rsps))) {
++ entry = priv->imb_waiting_rsps.next;
++ list_del(entry);
++ rsp = list_entry(entry,
++ struct ipmi_recv_msg,
++ link);
++ if (rsp->msgid != msgid) {
++ ipmi_free_recv_msg(rsp);
++ rsp = NULL;
++ } else {
++ break;
++ }
++ }
++
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (!signal_pending(current)) {
++ spin_unlock_irqrestore
++ (&(priv->imb_lock), flags);
++ schedule();
++ spin_lock_irqsave
++ (&(priv->imb_lock), flags);
++ } else {
++ rv = -ERESTARTSYS;
++ break;
++ }
++ }
++ remove_wait_queue(&(priv->imb_waiting_rsp_rcvrs),
++ &wait);
++ spin_unlock_irqrestore(&(priv->imb_lock), flags);
++
++ copy_resp:
++ if (rsp != NULL) {
++ pImbResp->cCode = rsp->msg.data[0];
++ memcpy(pImbResp->data,
++ rsp->msg.data+1,
++ rsp->msg.data_len-1);
++ length = (rsp->msg.data_len - 1
++ + MIN_IMB_RESP_BUF_SIZE);
++
++ if (copy_to_user(smi.lpvOutBuffer, pImbResp, length)) {
++ return -EFAULT;
++ }
++
++ if (copy_to_user(smi.lpcbBytesReturned,
++ &length,
++ sizeof(length)))
++ {
++ return -EFAULT;
++ }
++ }
++ no_response:
++ break;
++ }
++
++ case IOCTL_IMB_SHUTDOWN_CODE:
++ {
++ ShutdownCmdBuffer shutdownCmd;
++
++ if (copy_from_user(&shutdownCmd,
++ smi.lpvInBuffer,
++ sizeof(ShutdownCmdBuffer)))
++ {
++ return -EFAULT;
++ }
++
++ if (smi.cbInBuffer < sizeof(ShutdownCmdBuffer))
++ {
++ return -EINVAL;
++ }
++
++ rv = 0;
++ switch (shutdownCmd.code) {
++ case SD_POWER_OFF:
++ ipmi_delayed_shutdown(shutdownCmd.delayTime / 10, 1);
++ break;
++
++ case SD_RESET:
++ ipmi_delayed_shutdown(shutdownCmd.delayTime / 10, 0);
++ break;
++
++ case SD_NO_ACTION:
++ break;
++
++ default:
++ rv = INVALID_ARGUMENTS;
++ }
++
++ }
++
++ case IOCTL_IMB_REGISTER_ASYNC_OBJ:
++ rv = STATUS_SUCCESS;
++ break;
++
++
++ case IOCTL_IMB_CHECK_EVENT:
++ {
++ wait_queue_t wait;
++
++ spin_lock_irqsave(&(priv->imb_lock), flags);
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&(priv->imb_waiting_cmd_rcvrs),
++ &wait);
++ while (!list_empty(&(priv->imb_waiting_cmds))) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (!signal_pending(current)) {
++ spin_unlock_irqrestore
++ (&(priv->imb_lock), flags);
++ schedule();
++ spin_lock_irqsave
++ (&(priv->imb_lock), flags);
++ } else {
++ rv = -ERESTARTSYS;
++ break;
++ }
++ }
++ remove_wait_queue(&(priv->imb_waiting_cmd_rcvrs),
++ &wait);
++ spin_unlock_irqrestore(&(priv->imb_lock), flags);
++ rv = 0;
++ break;
++ }
++ }
++
++ return rv;
++}
++
++static int ipmi_imb_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ off_t offset = vma->vm_pgoff << PAGE_SHIFT;
++
++ if (offset < 0)
++ return -EINVAL;
++
++ if (remap_page_range(vma->vm_start, offset,
++ vma->vm_end - vma->vm_start,
++ vma->vm_page_prot))
++ {
++ return -EAGAIN;
++ }
++
++ /*vma->vm_inode = what_goes_here; */
++
++ return 0;
++
++}
++
++
++static struct file_operations ipmi_fops = {
++ owner: THIS_MODULE,
++ ioctl: ipmi_imb_ioctl,
++ open: ipmi_imb_open,
++ release: ipmi_imb_release,
++ mmap: ipmi_imb_mmap
++};
++
++static struct timer_list ipmi_imb_timer;
++
++/* Call every 100 ms. */
++#define IPMI_TIMEOUT_TIME 100
++#define IPMI_TIMEOUT_JIFFIES (IPMI_TIMEOUT_TIME/(1000/HZ))
++
++static volatile int stop_operation = 0;
++static volatile int timer_stopped = 0;
++
++static void ipmi_imb_timeout(unsigned long data)
++{
++ struct list_head *entry, *entry2;
++ struct priv_data *priv = (struct priv_data *) data;
++ int timeout_period = IPMI_TIMEOUT_TIME;
++ struct ipmi_recv_msg *msg;
++
++ if (stop_operation) {
++ timer_stopped = 1;
++ return;
++ }
++
++ /* Now time out any messages in the Imb message queue. */
++ spin_lock(&(priv->imb_lock));
++ list_for_each_safe(entry, entry2, &(priv->imb_waiting_rsps)) {
++ long *timeout;
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ timeout = imb_timeout(msg);
++ *timeout -= timeout_period;
++ if ((*timeout) <= 0) {
++ list_del(entry);
++ ipmi_free_recv_msg(msg);
++ }
++ }
++ list_for_each_safe(entry, entry2, &(priv->imb_waiting_cmds)) {
++ long *timeout;
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ timeout = imb_timeout(msg);
++ *timeout -= timeout_period;
++ if ((*timeout) <= 0) {
++ list_del(entry);
++ ipmi_free_recv_msg(msg);
++ }
++ }
++ spin_unlock(&priv->imb_lock);
++
++ ipmi_imb_timer.expires += IPMI_TIMEOUT_JIFFIES;
++ add_timer(&ipmi_imb_timer);
++}
++
++#define DEVICE_NAME "imb"
++
++static int ipmi_imb_major = 0;
++MODULE_PARM(ipmi_imb_major, "i");
++
++static struct ipmi_user_hndl ipmi_hndlrs =
++{
++ ipmi_recv_hndl : imb_msg_recv
++};
++
++static int init_ipmi_imb(void)
++{
++ int rv;
++
++ if (ipmi_imb_major < 0)
++ return -EINVAL;
++
++ ipmi_user = kmalloc(sizeof(*ipmi_user), GFP_KERNEL);
++ if (!ipmi_user) {
++ return -ENOMEM;
++ }
++
++ /* Create the Imb interface user. */
++ spin_lock_init(&(ipmi_user->imb_lock));
++ INIT_LIST_HEAD(&(ipmi_user->imb_waiting_rsps));
++ init_waitqueue_head(&(ipmi_user->imb_waiting_rsp_rcvrs));
++ INIT_LIST_HEAD(&(ipmi_user->imb_waiting_cmds));
++ init_waitqueue_head(&(ipmi_user->imb_waiting_cmd_rcvrs));
++ ipmi_user->imb_cmd_waiting = 0;
++ INIT_LIST_HEAD(&(ipmi_user->imb_waiting_events));
++
++ rv = ipmi_create_user(0,
++ &ipmi_hndlrs,
++ ipmi_user,
++ &(ipmi_user->imb_user));
++ if (rv) {
++ kfree(ipmi_user);
++ ipmi_user = NULL;
++ return rv;
++ }
++
++ rv = register_chrdev(ipmi_imb_major, DEVICE_NAME, &ipmi_fops);
++ if (rv < 0)
++ {
++ kfree(ipmi_user);
++ ipmi_user = NULL;
++ printk(KERN_ERR "ipmi: can't get major %d\n",
++ ipmi_imb_major);
++ return rv;
++ }
++
++ if (ipmi_imb_major == 0)
++ {
++ ipmi_imb_major = rv;
++ }
++
++ devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_NONE,
++ ipmi_imb_major, 0,
++ S_IFCHR | S_IRUSR | S_IWUSR,
++ &ipmi_fops, NULL);
++
++ ipmi_imb_timer.data = (long) ipmi_user;
++ ipmi_imb_timer.function = ipmi_imb_timeout;
++ ipmi_imb_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES;
++ add_timer(&ipmi_imb_timer);
++
++ printk(KERN_INFO "ipmi_imb: driver initialized at char major %d\n",
++ ipmi_imb_major);
++
++ return 0;
++}
++
++#ifdef MODULE
++static void free_recv_msg_list(struct list_head *q)
++{
++ struct list_head *entry, *entry2;
++ struct ipmi_recv_msg *msg;
++
++ list_for_each_safe(entry, entry2, q) {
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ list_del(entry);
++ ipmi_free_recv_msg(msg);
++ }
++}
++
++static void cleanup_ipmi_imb(void)
++{
++ devfs_unregister(devfs_handle);
++
++ /* Tell the timer to stop, then wait for it to stop. This avoids
++ problems with race conditions removing the timer here. */
++ stop_operation = 1;
++ while (!timer_stopped) {
++ schedule_timeout(1);
++ }
++
++ ipmi_destroy_user(ipmi_user->imb_user);
++
++ free_recv_msg_list(&(ipmi_user->imb_waiting_rsps));
++ free_recv_msg_list(&(ipmi_user->imb_waiting_cmds));
++ free_recv_msg_list(&(ipmi_user->imb_waiting_events));
++
++ kfree(ipmi_user);
++ ipmi_user = NULL;
++
++ unregister_chrdev(ipmi_imb_major, DEVICE_NAME);
++}
++module_exit(cleanup_ipmi_imb);
++#else
++static int __init ipmi_imb_setup (char *str)
++{
++ int x;
++
++ if (get_option (&str, &x)) {
++ /* ipmi=x sets the major number to x. */
++ ipmi_imb_major = x;
++ } else if (!strcmp(str, "off")) {
++ ipmi_imb_major = -1;
++ }
++
++ return 1;
++}
++__setup("ipmi_imb=", ipmi_imb_setup);
++#endif
++
++module_init(init_ipmi_imb);
++MODULE_LICENSE("GPL");
+--- /dev/null 2002-08-30 19:31:37.000000000 -0400
++++ linux-2.4.18-14/drivers/char/ipmi/ipmi_radisys.c 2003-03-27 15:32:59.000000000 -0500
+@@ -0,0 +1,834 @@
++/*
++ * ipmi_radisys.c
++ *
++ * Radisys emulation for the IPMI interface.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <asm/system.h>
++#include <linux/sched.h>
++#include <linux/poll.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/devfs_fs_kernel.h>
++#include <linux/ipmi.h>
++#include <linux/ipmi_radisys.h>
++
++
++struct priv_data
++{
++ /* This is for supporting the old Radisys interface. */
++ ipmi_user_t rs_user;
++ spinlock_t rs_lock;
++
++ /* A list of responses in the queue. */
++ struct list_head rs_waiting_rsps;
++
++ /* A list of things waiting for responses. We wake them all up
++ when a response comes in. */
++ wait_queue_head_t rs_waiting_rsp_rcvrs;
++
++ /* A list of commands that have come in. */
++ struct list_head rs_waiting_cmds;
++
++ /* A list of thing waiting for commands. We wake them all up
++ when a command comes in. */
++ wait_queue_head_t rs_waiting_cmd_rcvrs;
++
++ /* The registered command receiver value. This only allows someone
++ with the "magic number" to issue commands. */
++ unsigned long rs_cmd_receiver;
++
++ /* Is someone already waiting for a command? The Radisys driver
++ only allows one waiter, this enforces that. */
++ int rs_cmd_waiting;
++
++ /* A list of IPMI events waiting to be delivered. (not that
++ the Radisys driver calls incoming commands "events", this
++ variable is actual IPMI events, not incoming commands). */
++ struct list_head rs_waiting_events;
++
++#define RS_EVENT_QUEUE_LIMIT 16 /* Allow up to 16 events. */
++ /* The number of events in the event queue. */
++ unsigned int rs_waiting_event_count;
++};
++
++
++static devfs_handle_t devfs_handle;
++
++/* We cheat and use a piece of the address as the timeout. */
++static long *rs_timeout(struct ipmi_recv_msg *msg)
++{
++ char *base = (char *) &(msg->addr);
++ base += sizeof(struct ipmi_ipmb_addr);
++ return (long *) base;
++}
++
++static void rs_msg_recv(struct ipmi_recv_msg *msg,
++ void *data)
++{
++ struct priv_data *priv = data;
++ unsigned long flags;
++
++ spin_lock_irqsave(&(priv->rs_lock), flags);
++ if (msg->recv_type == IPMI_RESPONSE_RECV_TYPE) {
++ *rs_timeout(msg) = 5000;
++ list_add_tail(&(msg->link), &(priv->rs_waiting_rsps));
++ wake_up_all(&(priv->rs_waiting_rsp_rcvrs));
++ } else if (msg->recv_type == IPMI_CMD_RECV_TYPE) {
++ *rs_timeout(msg) = 5000;
++ list_add_tail(&(msg->link), &(priv->rs_waiting_cmds));
++ wake_up_all(&(priv->rs_waiting_cmd_rcvrs));
++ } else if (msg->recv_type == IPMI_ASYNC_EVENT_RECV_TYPE) {
++ if (priv->rs_waiting_event_count > RS_EVENT_QUEUE_LIMIT) {
++ ipmi_free_recv_msg(msg);
++ } else {
++ list_add_tail(&(msg->link),&(priv->rs_waiting_events));
++ (priv->rs_waiting_event_count)++;
++ }
++ } else {
++ ipmi_free_recv_msg(msg);
++ }
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++}
++
++/* We emulate the event queue in the driver for the Radisys emulation. */
++static int rs_handle_event_request(struct priv_data *priv)
++{
++ struct list_head *entry;
++ unsigned long flags;
++ struct ipmi_recv_msg *msg = NULL;
++ int rv = 0;
++
++ spin_lock_irqsave(&(priv->rs_lock), flags);
++ if (list_empty(&(priv->rs_waiting_events))) {
++ /* Nothing in the event queue, just return an error. */
++ msg = ipmi_alloc_recv_msg();
++ if (msg == NULL) {
++ rv = -EAGAIN;
++ goto out_err;
++ }
++ msg->addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ msg->addr.channel = IPMI_BMC_CHANNEL;
++ msg->msg.cmd = IPMI_READ_EVENT_MSG_BUFFER_CMD;
++ msg->msgid = 0;
++ msg->recv_type = IPMI_ASYNC_EVENT_RECV_TYPE;
++ msg->msg.netfn = IPMI_NETFN_APP_RESPONSE;
++ msg->msg.data = msg->msg_data;
++ msg->msg.data[0] = 0x80; /* Data not available. */
++ msg->msg.data_len = 1;
++ } else {
++ /* Pull an item from the event queue . */
++ entry = priv->rs_waiting_events.next;
++ list_del(entry);
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ (priv->rs_waiting_event_count)--;
++ }
++
++ /* Put the response into the list of waiting responses and
++ wake all the response waiters up. */
++ *rs_timeout(msg) = 5000;
++ list_add_tail(&(msg->link), &(priv->rs_waiting_rsps));
++ wake_up_all(&(priv->rs_waiting_rsp_rcvrs));
++
++ out_err:
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++ return rv;
++}
++
++static struct ipmi_recv_msg *rs_find_in_list(struct list_head *q,
++ unsigned char slave_addr,
++ unsigned char lun,
++ unsigned char netfn,
++ unsigned char cmd,
++ unsigned char seq)
++{
++ struct list_head *entry;
++ struct ipmi_recv_msg *msg;
++ struct ipmi_addr addr;
++ unsigned char msg_seq;
++
++ if (slave_addr == 1) {
++ struct ipmi_system_interface_addr *smi_addr;
++ smi_addr = (struct ipmi_system_interface_addr *) &addr;
++ smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr->lun = lun;
++ /* Slave address 1 means no matching sequence in the
++ Radisys driver. */
++ } else {
++ struct ipmi_ipmb_addr *ipmb_addr;
++ ipmb_addr = (struct ipmi_ipmb_addr *) &addr;
++ ipmb_addr->addr_type = IPMI_IPMB_ADDR_TYPE;
++ ipmb_addr->slave_addr = slave_addr;
++ ipmb_addr->lun = lun;
++ }
++
++ list_for_each(entry, q) {
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ if (msg->addr.channel == IPMI_BMC_CHANNEL)
++ msg_seq = 0;
++ else
++ msg_seq = msg->msgid;
++
++ /* We ignore the channel for these comparisons, since the
++ Radisys driver seems to ignore it. */
++ addr.channel = msg->addr.channel;
++
++ if ((msg_seq == seq)
++ && (msg->msg.cmd == cmd)
++ && (msg->msg.netfn == (netfn >> 2))
++ && ipmi_addr_equal(&addr, &(msg->addr)))
++ {
++ list_del(entry);
++ return msg;
++ }
++ }
++
++ return NULL;
++}
++
++static struct priv_data *ipmi_user;
++static unsigned int user_count = 0; /* How many users have this open. */
++static spinlock_t dev_lock = SPIN_LOCK_UNLOCKED;
++
++static int ipmi_open(struct inode *inode, struct file *file)
++{
++ file->private_data = ipmi_user;
++ spin_lock(&dev_lock);
++ if (user_count == 0)
++ ipmi_set_gets_events(ipmi_user->rs_user, 1);
++ user_count++;
++ spin_unlock(&dev_lock);
++
++ return 0;
++}
++
++static int ipmi_release(struct inode *inode, struct file *file)
++{
++ spin_lock(&dev_lock);
++ user_count--;
++ if (user_count == 0)
++ ipmi_set_gets_events(ipmi_user->rs_user, 0);
++ spin_unlock(&dev_lock);
++ return 0;
++}
++
++static unsigned char
++ipmb_checksum(unsigned char *data, int size)
++{
++ unsigned char csum = 0;
++
++ for (; size > 0; size--, data++)
++ csum += *data;
++
++ return -csum;
++}
++
++static int ipmi_ioctl(struct inode *inode,
++ struct file *file,
++ unsigned int cmd,
++ unsigned long data)
++{
++ struct priv_data *priv = file->private_data;
++ int rv = -EINVAL;
++
++ switch(cmd) {
++ case IOCTL_IPMI_RCV: /* get ipmi message */
++ {
++ IPMI_MSGDESC rsp;
++ struct ipmi_recv_msg *msg;
++ unsigned long flags;
++ long timeout;
++ wait_queue_t wait;
++
++ if (copy_from_user(&rsp, (void *) data, sizeof(rsp))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = 0;
++
++ spin_lock_irqsave(&(priv->rs_lock), flags);
++
++ msg = rs_find_in_list(&(priv->rs_waiting_rsps),
++ rsp.Dest.uchSlave,
++ rsp.Dest.uchLun,
++ rsp.uchNetFn,
++ rsp.uchCmd,
++ rsp.uchSeq);
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&(priv->rs_waiting_rsp_rcvrs),
++ &wait);
++ timeout = 5000 / (1000 / HZ);
++ while (msg == NULL) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (!signal_pending(current)) {
++ spin_unlock_irqrestore
++ (&(priv->rs_lock), flags);
++ timeout = schedule_timeout(timeout);
++ spin_lock_irqsave
++ (&(priv->rs_lock), flags);
++ } else {
++ rv = -ERESTARTSYS;
++ break;
++ }
++ if (timeout <= 0) {
++ rsp.uchComplete = IPMI_TIMEOUT_COMPLETION_CODE;
++ break;
++ } else {
++ msg = rs_find_in_list
++ (&(priv->rs_waiting_rsps),
++ rsp.Dest.uchSlave,
++ rsp.Dest.uchLun,
++ rsp.uchNetFn,
++ rsp.uchCmd,
++ rsp.uchSeq);
++ }
++ }
++ remove_wait_queue(&(priv->rs_waiting_rsp_rcvrs),
++ &wait);
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++
++ if (msg != NULL) {
++ rsp.uchComplete = msg->msg.data[0];
++ /* The Radisys driver expects all the data to
++ be there in the data, even the stuff we
++ already have processed for it. So make is
++ so. */
++ if (msg->addr.channel == IPMI_BMC_CHANNEL) {
++ struct ipmi_system_interface_addr *smi_addr;
++
++ smi_addr = ((struct ipmi_system_interface_addr *)
++ &(msg->addr));
++ memcpy(&(rsp.auchBuffer[2]),
++ &(msg->msg.data[0]),
++ msg->msg.data_len);
++ rsp.ulLength = msg->msg.data_len+2;
++ rsp.auchBuffer[0] = ((msg->msg.netfn << 2)
++ | (smi_addr->lun));
++ rsp.auchBuffer[1] = msg->msg.cmd;
++ } else {
++ struct ipmi_ipmb_addr *ipmb_addr;
++
++ ipmb_addr = (struct ipmi_ipmb_addr *) &msg->addr;
++ memcpy(&(rsp.auchBuffer[9]),
++ &(msg->msg.data[0]),
++ msg->msg.data_len);
++ rsp.ulLength = msg->msg.data_len+10;
++ rsp.auchBuffer[0] = IPMI_NETFN_APP_REQUEST << 2;
++ rsp.auchBuffer[1] = IPMI_GET_MSG_CMD;
++ rsp.auchBuffer[2] = 0;
++ rsp.auchBuffer[3] = msg->addr.channel;
++ rsp.auchBuffer[4] = ((msg->msg.netfn << 2)
++ | 2);
++ rsp.auchBuffer[5]
++ = ipmb_checksum(&(rsp.auchBuffer[3]),
++ 2);
++ rsp.auchBuffer[6] = ipmb_addr->slave_addr;
++ rsp.auchBuffer[7] = ((msg->msgid << 2)
++ | ipmb_addr->lun);
++ rsp.auchBuffer[8] = msg->msg.cmd;
++ rsp.auchBuffer[msg->msg.data_len+9]
++ = ipmb_checksum(&(rsp.auchBuffer[6]),
++ msg->msg.data_len+3);
++ }
++ ipmi_free_recv_msg(msg);
++ }
++
++ if (copy_to_user((void *) data, &rsp, sizeof(rsp))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ break;
++ }
++
++ case IOCTL_IPMI_SEND: /* send ipmi message */
++ {
++ IPMI_MSGDESC req;
++ struct ipmi_addr addr;
++ struct ipmi_msg msg;
++ unsigned char source_address;
++ unsigned char source_lun;
++ unsigned int start_offset;
++
++ if (copy_from_user(&req, (void *) data, sizeof(req))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ if (req.Dest.uchSlave == 1) {
++ struct ipmi_system_interface_addr *smi_addr
++ = (struct ipmi_system_interface_addr *) &addr;
++ if ((req.uchNetFn == (IPMI_NETFN_APP_REQUEST << 2))
++ && (req.uchCmd == IPMI_READ_EVENT_MSG_BUFFER_CMD))
++ {
++ /* The driver gets event messages
++ automatically, so we emulate
++ this. */
++ rv = rs_handle_event_request(priv);
++ break;
++ }
++
++ smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr->channel = IPMI_BMC_CHANNEL;
++ smi_addr->lun = req.uchNetFn & 0x3;
++ source_address = 0;
++ source_lun = 0;
++ start_offset = 2;
++ } else {
++ struct ipmi_ipmb_addr *ipmb_addr =
++ (struct ipmi_ipmb_addr *) &addr;
++
++ ipmb_addr->addr_type = IPMI_IPMB_ADDR_TYPE;
++ ipmb_addr->channel = 0;
++ ipmb_addr->slave_addr = req.Dest.uchSlave;
++ ipmb_addr->lun = req.Dest.uchLun;
++ source_address = req.auchBuffer[6];
++ source_lun = req.auchBuffer[7] & 0x3;
++ start_offset = 9;
++ req.ulLength--; /* Remove the checksum the userland
++ process adds. */
++ }
++
++ msg.netfn = req.uchNetFn >> 2;
++ msg.cmd = req.uchCmd;
++ msg.data = req.auchBuffer + start_offset;
++ msg.data_len = req.ulLength - start_offset;
++
++ rv = ipmi_request_with_source(priv->rs_user,
++ &addr,
++ req.uchSeq,
++ &msg,
++ 0,
++ source_address,
++ source_lun);
++ if (rv)
++ req.uchComplete = IPMI_UNKNOWN_ERR_COMPLETION_CODE;
++ else
++ req.uchComplete = 0;
++ /* The Radisys driver does no error checking here. */
++ copy_to_user((void *) data, &req, sizeof(req));
++ rv = 0;
++ break;
++ }
++
++ case IOCTL_IPMI_EVENT: /* get an incoming command. Don't be
++ fooled by the name, these are
++ commands, not IPMI events. */
++ {
++ IPMI_MSGDESC rsp;
++ struct ipmi_recv_msg *msg = NULL;
++ struct list_head *entry;
++ unsigned long flags;
++ long timeout;
++ unsigned long receiver;
++ wait_queue_t wait;
++
++ if (copy_from_user(&receiver, (void *) data, sizeof(receiver)))
++ {
++ rv = -EFAULT;
++ break;
++ }
++
++ if (copy_from_user(&timeout,
++ (void *) (data + sizeof(receiver)),
++ sizeof(timeout)))
++ {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = 0;
++
++ spin_lock_irqsave(&(priv->rs_lock), flags);
++
++ /* If someone else is already waiting, the Radisys driver
++ returns EFAULT, so we do to. */
++ if (priv->rs_cmd_waiting) {
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++ rv = -EFAULT;
++ break;
++ }
++
++ /* If the user thread doesn't match up, abort. */
++ if (receiver != priv->rs_cmd_receiver) {
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++ rsp.uchComplete = IPMI_INVALID_CMD_COMPLETION_CODE;
++ break;
++ }
++
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&(priv->rs_waiting_cmd_rcvrs),
++ &wait);
++ priv->rs_cmd_waiting = 1;
++ timeout = timeout / (1000 / HZ); /* from ms to jiffies */
++ while ((timeout > 0) &&
++ list_empty(&(priv->rs_waiting_cmds)))
++ {
++ set_current_state(TASK_INTERRUPTIBLE);
++ if (!signal_pending(current)) {
++ spin_unlock_irqrestore
++ (&(priv->rs_lock), flags);
++ timeout = schedule_timeout(timeout);
++ spin_lock_irqsave
++ (&(priv->rs_lock), flags);
++ } else {
++ rv = -ERESTARTSYS;
++ break;
++ }
++ }
++ if (!list_empty(&(priv->rs_waiting_cmds))) {
++ entry = priv->rs_waiting_cmds.next;
++ list_del(entry);
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ }
++ priv->rs_cmd_waiting = 0;
++ remove_wait_queue(&(priv->rs_waiting_cmd_rcvrs),
++ &wait);
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++
++ if (msg != NULL) {
++ /* The Radisys driver expects all the data to
++ be there in the data, even the stuff we
++ already have processed for it. So make is
++ so. */
++ struct ipmi_ipmb_addr *ipmb_addr;
++
++ ipmb_addr = (struct ipmi_ipmb_addr *) &msg->addr;
++ memcpy(&(rsp.auchBuffer[9]),
++ &(msg->msg.data[0]),
++ msg->msg.data_len);
++ rsp.ulLength = msg->msg.data_len+9;
++ rsp.auchBuffer[0] = IPMI_NETFN_APP_REQUEST << 2;
++ rsp.auchBuffer[1] = IPMI_SEND_MSG_CMD;
++ rsp.auchBuffer[2] = 0;
++ rsp.auchBuffer[3] = msg->addr.channel;
++ rsp.auchBuffer[4] = ((msg->msg.netfn << 2)
++ | 2);
++ rsp.auchBuffer[5]
++ = ipmb_checksum(&(rsp.auchBuffer[3]),
++ 2);
++ rsp.auchBuffer[6] = ipmb_addr->slave_addr;
++ rsp.auchBuffer[7] = ((msg->msgid << 2)
++ | ipmb_addr->lun);
++ rsp.auchBuffer[8] = msg->msg.cmd;
++
++ rsp.uchNetFn = (msg->msg.netfn << 2);
++ rsp.uchCmd = msg->msg.cmd;
++ rsp.uchSeq = msg->msgid;
++ rsp.ulLength = msg->msg.data_len + 9;
++ ipmi_free_recv_msg(msg);
++ } else if (!rv) {
++ /* On a time out, the Radisys driver returns
++ IPMIRC_ERROR in the completion code, for
++ some wierd reason. */
++ rsp.uchComplete = IPMI_UNKNOWN_ERR_COMPLETION_CODE;
++ }
++
++ /* The Radisys driver does no error checking here. */
++ copy_to_user((void *) data, &rsp, sizeof(rsp));
++ rv = 0;
++ break;
++ }
++
++ case IOCTL_IPMI_REGISTER: /* register as event receiver */
++ {
++ unsigned long receiver;
++ unsigned char rc = LOWLRC_SUCCESS;
++ unsigned long flags;
++
++ if (copy_from_user(&receiver, (void *) data, sizeof(receiver)))
++ {
++ rv = -EFAULT;
++ break;
++ }
++
++ spin_lock_irqsave(&(priv->rs_lock), flags);
++ if (priv->rs_cmd_receiver == 0) {
++ rv = ipmi_register_all_cmd_rcvr(priv->rs_user);
++ if (rv) {
++ priv->rs_cmd_receiver = receiver;
++ } else {
++ rc = LOWLRC_ERROR;
++ }
++ } else if (priv->rs_cmd_receiver != receiver) {
++ rc = LOWLRC_ERROR;
++ }
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++
++ /* The Radisys driver does no error checking here. */
++ copy_to_user((void *) data, &rc, sizeof(rc));
++ rv = 0;
++ break;
++ }
++
++ case IOCTL_IPMI_UNREGISTER: /* unregister as event receiver */
++ {
++ unsigned long receiver;
++ unsigned char rc = LOWLRC_SUCCESS;
++ unsigned long flags;
++
++ if (copy_from_user(&receiver, (void *) data, sizeof(receiver)))
++ {
++ rv = -EFAULT;
++ break;
++ }
++
++ spin_lock_irqsave(&(priv->rs_lock), flags);
++ if (priv->rs_cmd_receiver == receiver) {
++ ipmi_unregister_all_cmd_rcvr(priv->rs_user);
++ priv->rs_cmd_receiver = 0;
++ } else {
++ rc = LOWLRC_ERROR;
++ }
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++
++ /* The Radisys driver does no error checking here. */
++ copy_to_user((void *) data, &rc, sizeof(rc));
++ rv = 0;
++ break;
++ }
++
++ case IOCTL_IPMI_CLEAR: /* clear registered event receiver */
++ {
++ unsigned char rc = LOWLRC_SUCCESS;
++ unsigned long flags;
++
++ spin_lock_irqsave(&(priv->rs_lock), flags);
++ ipmi_unregister_all_cmd_rcvr(priv->rs_user);
++ priv->rs_cmd_receiver = 0;
++ spin_unlock_irqrestore(&(priv->rs_lock), flags);
++
++ /* The Radisys driver does no error checking here. */
++ copy_to_user((void *) data, &rc, sizeof(rc));
++ rv = 0;
++ break;
++ }
++ }
++
++ return rv;
++}
++
++static struct file_operations ipmi_fops = {
++ owner: THIS_MODULE,
++ ioctl: ipmi_ioctl,
++ open: ipmi_open,
++ release: ipmi_release
++};
++
++static struct timer_list ipmi_radisys_timer;
++
++/* Call every 100 ms. */
++#define IPMI_TIMEOUT_TIME 100
++#define IPMI_TIMEOUT_JIFFIES (IPMI_TIMEOUT_TIME/(1000/HZ))
++
++/* Request events from the queue every second. Hopefully, in the
++ future, IPMI will add a way to know immediately if an event is
++ in the queue. */
++#define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME))
++
++static volatile int stop_operation = 0;
++static volatile int timer_stopped = 0;
++
++static void ipmi_radisys_timeout(unsigned long data)
++{
++ struct list_head *entry, *entry2;
++ struct priv_data *priv = (struct priv_data *) data;
++ int timeout_period = IPMI_TIMEOUT_TIME;
++ struct ipmi_recv_msg *msg;
++
++ if (stop_operation) {
++ timer_stopped = 1;
++ return;
++ }
++
++ /* Now time out any messages in the Radisys message queue. */
++ spin_lock(&(priv->rs_lock));
++ list_for_each_safe(entry, entry2, &(priv->rs_waiting_rsps)) {
++ long *timeout;
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ timeout = rs_timeout(msg);
++ *timeout -= timeout_period;
++ if ((*timeout) <= 0) {
++ list_del(entry);
++ ipmi_free_recv_msg(msg);
++ }
++ }
++ list_for_each_safe(entry, entry2, &(priv->rs_waiting_cmds)) {
++ long *timeout;
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ timeout = rs_timeout(msg);
++ *timeout -= timeout_period;
++ if ((*timeout) <= 0) {
++ list_del(entry);
++ ipmi_free_recv_msg(msg);
++ }
++ }
++ spin_unlock(&priv->rs_lock);
++
++ ipmi_radisys_timer.expires += IPMI_TIMEOUT_JIFFIES;
++ add_timer(&ipmi_radisys_timer);
++}
++
++#define DEVICE_NAME "ipmi_radisys"
++
++static int ipmi_radisys_major = 0;
++MODULE_PARM(ipmi_radisys_major, "i");
++
++static struct ipmi_user_hndl ipmi_hndlrs =
++{
++ ipmi_recv_hndl : rs_msg_recv
++};
++
++
++static int init_ipmi_radisys(void)
++{
++ int rv;
++
++ if (ipmi_radisys_major < 0)
++ return -EINVAL;
++
++ ipmi_user = kmalloc(sizeof(*ipmi_user), GFP_KERNEL);
++ if (!ipmi_user) {
++ printk("ipmi_radisys: Unable to allocate memory\n");
++ return -ENOMEM;
++ }
++
++ /* Create the Radisys interface user. */
++ spin_lock_init(&(ipmi_user->rs_lock));
++ INIT_LIST_HEAD(&(ipmi_user->rs_waiting_rsps));
++ init_waitqueue_head(&(ipmi_user->rs_waiting_rsp_rcvrs));
++ INIT_LIST_HEAD(&(ipmi_user->rs_waiting_cmds));
++ init_waitqueue_head(&(ipmi_user->rs_waiting_cmd_rcvrs));
++ ipmi_user->rs_cmd_waiting = 0;
++ INIT_LIST_HEAD(&(ipmi_user->rs_waiting_events));
++
++ rv = ipmi_create_user(0,
++ &ipmi_hndlrs,
++ ipmi_user,
++ &(ipmi_user->rs_user));
++ if (rv) {
++ printk("ipmi_radisys: Unable to create an IPMI user, probably"
++ " no physical devices present.\n");
++ kfree(ipmi_user);
++ ipmi_user = NULL;
++ return rv;
++ }
++
++ rv = register_chrdev(ipmi_radisys_major, DEVICE_NAME, &ipmi_fops);
++ if (rv < 0)
++ {
++ printk("ipmi_radisys: Unable to create the character device\n");
++ kfree(ipmi_user);
++ ipmi_user = NULL;
++ printk(KERN_ERR "ipmi: can't get major %d\n",
++ ipmi_radisys_major);
++ return rv;
++ }
++
++ if (ipmi_radisys_major == 0)
++ {
++ ipmi_radisys_major = rv;
++ }
++
++ devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_NONE,
++ ipmi_radisys_major, 0,
++ S_IFCHR | S_IRUSR | S_IWUSR,
++ &ipmi_fops, NULL);
++
++ ipmi_radisys_timer.data = (long) ipmi_user;
++ ipmi_radisys_timer.function = ipmi_radisys_timeout;
++ ipmi_radisys_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES;
++ add_timer(&ipmi_radisys_timer);
++
++ printk(KERN_INFO "ipmi_radisys: driver initialized at char major %d\n",
++ ipmi_radisys_major);
++
++ return 0;
++}
++
++#ifdef MODULE
++static void free_recv_msg_list(struct list_head *q)
++{
++ struct list_head *entry, *entry2;
++ struct ipmi_recv_msg *msg;
++
++ list_for_each_safe(entry, entry2, q) {
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ list_del(entry);
++ ipmi_free_recv_msg(msg);
++ }
++}
++
++static void cleanup_ipmi_radisys(void)
++{
++ devfs_unregister(devfs_handle);
++
++ /* Tell the timer to stop, then wait for it to stop. This avoids
++ problems with race conditions removing the timer here. */
++ stop_operation = 1;
++ while (!timer_stopped) {
++ schedule_timeout(1);
++ }
++
++ ipmi_destroy_user(ipmi_user->rs_user);
++
++ free_recv_msg_list(&(ipmi_user->rs_waiting_rsps));
++ free_recv_msg_list(&(ipmi_user->rs_waiting_cmds));
++ free_recv_msg_list(&(ipmi_user->rs_waiting_events));
++
++ kfree(ipmi_user);
++ ipmi_user = NULL;
++
++ unregister_chrdev(ipmi_radisys_major, DEVICE_NAME);
++}
++module_exit(cleanup_ipmi_radisys);
++#else
++static int __init ipmi_radisys_setup (char *str)
++{
++ int x;
++
++ if (get_option (&str, &x)) {
++ /* ipmi=x sets the major number to x. */
++ ipmi_radisys_major = x;
++ } else if (!strcmp(str, "off")) {
++ ipmi_radisys_major = -1;
++ }
++
++ return 1;
++}
++__setup("ipmi_radisys=", ipmi_radisys_setup);
++#endif
++
++module_init(init_ipmi_radisys);
++MODULE_LICENSE("GPL");
diff --git a/kern/openipmi-rh80.patch b/kern/openipmi-rh80.patch
new file mode 100644
index 0000000..1481fd4
--- /dev/null
+++ b/kern/openipmi-rh80.patch
@@ -0,0 +1,6633 @@
+--- linux-2.4.18-14orig/Documentation/Configure.help 2002-09-04 11:54:06.000000000 -0400
++++ linux-2.4.18-14/Documentation/Configure.help 2003-03-27 15:26:22.000000000 -0500
+@@ -25565,6 +25565,31 @@
+ information: http://www.candelatech.com/~greear/vlan.html If unsure,
+ you can safely say 'N'.
+
++IPMI top-level message handler
++CONFIG_IPMI_HANDLER
++ This enables the central IPMI message handler, required for IPMI
++ to work. Note that you must have this enabled to do any other IPMI
++ things. See IPMI.txt for more details.
++
++Generate a panic event to all BMCs on a panic
++CONFIG_IPMI_PANIC_EVENT
++ When a panic occurs, this will cause the IPMI message handler to
++ generate an IPMI event describing the panic to each interface
++ registered with the message handler.
++
++Device interface for IPMI
++CONFIG_IPMI_DEVICE_INTERFACE
++ This provides an IOCTL interface to the IPMI message handler so
++ userland processes may use IPMI. It supports poll() and select().
++
++IPMI KCS handler
++CONFIG_IPMI_KCS
++ Provides a driver for a KCS-style interface to a BMC.
++
++IPMI Watchdog Timer
++CONFIG_IPMI_WATCHDOG
++ This enables the IPMI watchdog timer.
++
+ #
+ # A couple of things I keep forgetting:
+ # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
+--- linux-2.4.18-14orig/drivers/char/Makefile 2002-09-04 11:54:03.000000000 -0400
++++ linux-2.4.18-14/drivers/char/Makefile 2003-03-27 15:26:22.000000000 -0500
+@@ -293,6 +293,11 @@
+ obj-y += oprofile/oprofile_mod.o
+ endif
+
++subdir-$(CONFIG_IPMI_HANDLER) += ipmi
++ifeq ($(CONFIG_IPMI_HANDLER),y)
++ obj-y += ipmi/ipmi.o
++endif
++
+ include $(TOPDIR)/Rules.make
+
+ fastdep:
+--- linux-2.4.18-14orig/drivers/char/Config.in 2002-09-04 11:54:05.000000000 -0400
++++ linux-2.4.18-14/drivers/char/Config.in 2003-03-27 15:26:22.000000000 -0500
+@@ -175,6 +175,12 @@
+ fi
+ fi
+
++tristate 'IPMI top-level message handler' CONFIG_IPMI_HANDLER
++dep_mbool ' Generate a panic event to all BMCs on a panic' CONFIG_IPMI_PANIC_EVENT $CONFIG_IPMI_HANDLER
++dep_tristate ' Device interface for IPMI' CONFIG_IPMI_DEVICE_INTERFACE $CONFIG_IPMI_HANDLER
++dep_tristate ' IPMI KCS handler' CONFIG_IPMI_KCS $CONFIG_IPMI_HANDLER
++dep_tristate ' IPMI Watchdog Timer' CONFIG_IPMI_WATCHDOG $CONFIG_IPMI_HANDLER
++
+ mainmenu_option next_comment
+ comment 'Watchdog Cards'
+ bool 'Watchdog Timer Support' CONFIG_WATCHDOG
+--- linux-2.4.18-14orig/kernel/ksyms.c 2002-09-04 11:54:06.000000000 -0400
++++ linux-2.4.18-14/kernel/ksyms.c 2003-03-27 15:26:22.000000000 -0500
+@@ -70,6 +70,8 @@
+ extern int request_dma(unsigned int dmanr, char * deviceID);
+ extern void free_dma(unsigned int dmanr);
+ extern spinlock_t dma_spin_lock;
++extern int panic_timeout;
++
+
+ #ifdef CONFIG_MODVERSIONS
+ const struct module_symbol __export_Using_Versions
+@@ -507,6 +509,8 @@
+
+ /* misc */
+ EXPORT_SYMBOL(panic);
++EXPORT_SYMBOL(panic_notifier_list);
++EXPORT_SYMBOL(panic_timeout);
+ EXPORT_SYMBOL(__out_of_line_bug);
+ EXPORT_SYMBOL(sprintf);
+ EXPORT_SYMBOL(snprintf);
+--- /dev/null 2002-08-30 19:31:37.000000000 -0400
++++ linux-2.4.18-14/Documentation/IPMI.txt 2003-03-27 15:26:22.000000000 -0500
+@@ -0,0 +1,352 @@
++
++ The Linux IPMI Driver
++ ---------------------
++ Corey Minyard
++ <minyard@mvista.com>
++ <minyard@acm.org>
++
++This document describes how to use the IPMI driver for Linux. If you
++are not familiar with IPMI itself, see the web site at
++http://www.intel.com/design/servers/ipmi/index.htm. IPMI is a big
++subject and I can't cover it all here!
++
++Basic Design
++------------
++
++The Linux IPMI driver is designed to be very modular and flexible, you
++only need to take the pieces you need and you can use it in many
++different ways. Because of that, it's broken into many chunks of
++code. These chunks are:
++
++ipmi_msghandler - This is the central piece of software for the IPMI
++system. It handles all messages, message timing, and responses. The
++IPMI users tie into this, and the IPMI physical interfaces (called
++System Management Interfaces, or SMIs) also tie in here. This
++provides the kernelland interface for IPMI, but does not provide an
++interface for use by application processes.
++
++ipmi_devintf - This provides a userland IOCTL interface for the IPMI
++driver, each open file for this device ties in to the message handler
++as an IPMI user.
++
++ipmi_kcs_drv - A driver for the KCS SMI. Most system have a KCS
++interface for IPMI.
++
++
++Much documentation for the interface is in the include files. The
++IPMI include files are:
++
++ipmi.h - Contains the user interface and IOCTL interface for IPMI.
++
++ipmi_smi.h - Contains the interface for SMI drivers to use.
++
++ipmi_msgdefs.h - General definitions for base IPMI messaging.
++
++
++Addressing
++----------
++
++The IPMI addressing works much like IP addresses, you have an overlay
++to handle the different address types. The overlay is:
++
++ struct ipmi_addr
++ {
++ int addr_type;
++ short channel;
++ char data[IPMI_MAX_ADDR_SIZE];
++ };
++
++The addr_type determines what the address really is. The driver
++currently understands two different types of addresses.
++
++"System Interface" addresses are defined as:
++
++ struct ipmi_system_interface_addr
++ {
++ int addr_type;
++ short channel;
++ };
++
++and the type is IPMI_SYSTEM_INTERFACE_ADDR_TYPE. This is used for talking
++straight to the BMC on the current card. The channel must be
++IPMI_BMC_CHANNEL.
++
++Messages that are destined to go out on the IPMB bus use the
++IPMI_IPMB_ADDR_TYPE address type. The format is
++
++ struct ipmi_ipmb_addr
++ {
++ int addr_type;
++ short channel;
++ unsigned char slave_addr;
++ unsigned char lun;
++ };
++
++The "channel" here is generally zero, but some devices support more
++than one channel, it corresponds to the channel as defined in the IPMI
++spec.
++
++
++Messages
++--------
++
++Messages are defined as:
++
++struct ipmi_msg
++{
++ unsigned char netfn;
++ unsigned char lun;
++ unsigned char cmd;
++ unsigned char *data;
++ int data_len;
++};
++
++The driver takes care of adding/stripping the header information. The
++data portion is just the data to be send (do NOT put addressing info
++here) or the response. Note that the completion code of a response is
++the first item in "data", it is not stripped out because that is how
++all the messages are defined in the spec (and thus makes counting the
++offsets a little easier :-).
++
++When using the IOCTL interface from userland, you must provide a block
++of data for "data", fill it, and set data_len to the length of the
++block of data, even when receiving messages. Otherwise the driver
++will have no place to put the message.
++
++Messages coming up from the message handler in kernelland will come in
++as:
++
++ struct ipmi_recv_msg
++ {
++ struct list_head link;
++
++ /* The type of message as defined in the "Receive Types"
++ defines above. */
++ int recv_type;
++
++ ipmi_user_t *user;
++ struct ipmi_addr addr;
++ long msgid;
++ struct ipmi_msg msg;
++
++ /* Call this when done with the message. It will presumably free
++ the message and do any other necessary cleanup. */
++ void (*done)(struct ipmi_recv_msg *msg);
++
++ /* Place-holder for the data, don't make any assumptions about
++ the size or existence of this, since it may change. */
++ unsigned char msg_data[IPMI_MAX_MSG_LENGTH];
++ };
++
++You should look at the receive type and handle the message
++appropriately.
++
++
++The Upper Layer Interface (Message Handler)
++-------------------------------------------
++
++The upper layer of the interface provides the users with a consistent
++view of the IPMI interfaces. It allows multiple SMI interfaces to be
++addressed (because some boards actually have multiple BMCs on them)
++and the user should not have to care what type of SMI is below them.
++
++
++Creating the User
++
++To user the message handler, you must first create a user using
++ipmi_create_user. The interface number specifies which SMI you want
++to connect to, and you must supply callback functions to be called
++when data comes in. The callback function can run at interrupt level,
++so be careful using the callbacks. This also allows to you pass in a
++piece of data, the handler_data, that will be passed back to you on
++all calls.
++
++Once you are done, call ipmi_destroy_user() to get rid of the user.
++
++From userland, opening the device automatically creates a user, and
++closing the device automatically destroys the user.
++
++
++Messaging
++
++To send a message from kernel-land, the ipmi_request() call does
++pretty much all message handling. Most of the parameter are
++self-explanatory. However, it takes a "msgid" parameter. This is NOT
++the sequence number of messages. It is simply a long value that is
++passed back when the response for the message is returned. You may
++use it for anything you like.
++
++Responses come back in the function pointed to by the ipmi_recv_hndl
++field of the "handler" that you passed in to ipmi_create_user().
++Remember again, these may be running at interrupt level. Remember to
++look at the receive type, too.
++
++From userland, you fill out an ipmi_req_t structure and use the
++IPMICTL_SEND_COMMAND ioctl. For incoming stuff, you can use select()
++or poll() to wait for messages to come in. However, you cannot use
++read() to get them, you must call the IPMICTL_RECEIVE_MSG with the
++ipmi_recv_t structure to actually get the message. Remember that you
++must supply a pointer to a block of data in the msg.data field, and
++you must fill in the msg.data_len field with the size of the data.
++This gives the receiver a place to actually put the message.
++
++If the message cannot fit into the data you provide, you will get an
++EMSGSIZE error and the driver will leave the data in the receive
++queue. If you want to get it and have it truncate the message, us
++the IPMICTL_RECEIVE_MSG_TRUNC ioctl.
++
++When you send a command (which is defined by the lowest-order bit of
++the netfn per the IPMI spec) on the IPMB bus, the driver will
++automatically assign the sequence number to the command and save the
++command. If the response is not receive in the IPMI-specified 5
++seconds, it will generate a response automatically saying the command
++timed out. If an unsolicited response comes in (if it was after 5
++seconds, for instance), that response will be ignored.
++
++In kernelland, after you receive a message and are done with it, you
++MUST call ipmi_free_recv_msg() on it, or you will leak messages. Note
++that you should NEVER mess with the "done" field of a message, that is
++required to properly clean up the message.
++
++Note that when sending, there is an ipmi_request_supply_msgs() call
++that lets you supply the smi and receive message. This is useful for
++pieces of code that need to work even if the system is out of buffers
++(the watchdog timer uses this, for instance). You supply your own
++buffer and own free routines. This is not recommended for normal use,
++though, since it is tricky to manage your own buffers.
++
++
++Events and Incoming Commands
++
++The driver takes care of polling for IPMI events and receiving
++commands (commands are messages that are not responses, they are
++commands that other things on the IPMB bus have sent you). To receive
++these, you must register for them, they will not automatically be sent
++to you.
++
++To receive events, you must call ipmi_set_gets_events() and set the
++"val" to non-zero. Any events that have been received by the driver
++since startup will immediately be delivered to the first user that
++registers for events. After that, if multiple users are registered
++for events, they will all receive all events that come in.
++
++For receiving commands, you have to individually register commands you
++want to receive. Call ipmi_register_for_cmd() and supply the netfn
++and command name for each command you want to receive. Only one user
++may be registered for each netfn/cmd, but different users may register
++for different commands.
++
++From userland, equivalent IOCTLs are provided to do these functions.
++
++
++The Lower Layer (SMI) Interface
++-------------------------------
++
++As mentioned before, multiple SMI interfaces may be registered to the
++message handler, each of these is assigned an interface number when
++they register with the message handler. They are generally assigned
++in the order they register, although if an SMI unregisters and then
++another one registers, all bets are off.
++
++The ipmi_smi.h defines the interface for SMIs, see that for more
++details.
++
++
++The KCS Driver
++--------------
++
++The KCS driver allows up to 4 KCS interfaces to be configured in the
++system. By default, the driver will register one KCS interface at the
++spec-specified I/O port 0xca2 without interrupts. You can change this
++at module load time (for a module) with:
++
++ insmod ipmi_kcs_drv.o kcs_ports=<port1>,<port2>... kcs_addrs=<addr1>,<addr2>
++ kcs_irqs=<irq1>,<irq2>... kcs_trydefaults=[0|1]
++
++The KCS driver supports two types of interfaces, ports (for I/O port
++based KCS interfaces) and memory addresses (for KCS interfaces in
++memory). The driver will support both of them simultaneously, setting
++the port to zero (or just not specifying it) will allow the memory
++address to be used. The port will override the memory address if it
++is specified and non-zero. kcs_trydefaults sets whether the standard
++IPMI interface at 0xca2 and any interfaces specified by ACPE are
++tried. By default, the driver tries it, set this value to zero to
++turn this off.
++
++When compiled into the kernel, the addresses can be specified on the
++kernel command line as:
++
++ ipmi_kcs=<bmc1>:<irq1>,<bmc2>:<irq2>....,[nodefault]
++
++The <bmcx> values is either "p<port>" or "m<addr>" for port or memory
++addresses. So for instance, a KCS interface at port 0xca2 using
++interrupt 9 and a memory interface at address 0xf9827341 with no
++interrupt would be specified "ipmi_kcs=p0xca2:9,m0xf9827341".
++If you specify zero for in irq or don't specify it, the driver will
++run polled unless the software can detect the interrupt to use in the
++ACPI tables.
++
++By default, the driver will attempt to detect a KCS device at the
++spec-specified 0xca2 address and any address specified by ACPI. If
++you want to turn this off, use the "nodefault" option.
++
++If you have high-res timers compiled into the kernel, the driver will
++use them to provide much better performance. Note that if you do not
++have high-res timers enabled in the kernel and you don't have
++interrupts enabled, the driver will run VERY slowly. Don't blame me,
++the KCS interface sucks.
++
++
++Other Pieces
++------------
++
++Watchdog
++
++A watchdog timer is provided that implements the Linux-standard
++watchdog timer interface. It has three module parameters that can be
++used to control it:
++
++ insmod ipmi_watchdog timeout=<t> pretimeout=<t> action=<action type>
++ preaction=<preaction type> preop=<preop type>
++
++The timeout is the number of seconds to the action, and the pretimeout
++is the amount of seconds before the reset that the pre-timeout panic will
++occur (if pretimeout is zero, then pretimeout will not be enabled).
++
++The action may be "reset", "power_cycle", or "power_off", and
++specifies what to do when the timer times out, and defaults to
++"reset".
++
++The preaction may be "pre_smi" for an indication through the SMI
++interface, "pre_int" for an indication through the SMI with an
++interrupts, and "pre_nmi" for a NMI on a preaction. This is how
++the driver is informed of the pretimeout.
++
++The preop may be set to "preop_none" for no operation on a pretimeout,
++"preop_panic" to set the preoperation to panic, or "preop_give_data"
++to provide data to read from the watchdog device when the pretimeout
++occurs. A "pre_nmi" setting CANNOT be used with "preop_give_data"
++because you can't do data operations from an NMI.
++
++When preop is set to "preop_give_data", one byte comes ready to read
++on the device when the pretimeout occurs. Select and fasync work on
++the device, as well.
++
++When compiled into the kernel, the kernel command line is available
++for configuring the watchdog:
++
++ ipmi_wdog=<timeout>[,<pretimeout>[,<option>[,<options>....]]]
++
++The options are the actions and preaction above (if an option
++controlling the same thing is specified twice, the last is taken). An
++options "start_now" is also there, if included, the watchdog will
++start running immediately when all the drivers are ready, it doesn't
++have to have a user hooked up to start it.
++
++The watchdog will panic and start a 120 second reset timeout if it
++gets a pre-action. During a panic or a reboot, the watchdog will
++start a 120 timer if it is running to make sure the reboot occurs.
++
++Note that if you use the NMI preaction for the watchdog, you MUST
++NOT use nmi watchdog mode 1. If you use the NMI watchdog, you
++must use mode 2.
+--- /dev/null 2002-08-30 19:31:37.000000000 -0400
++++ linux-2.4.18-14/drivers/char/ipmi/Makefile 2003-03-27 15:26:22.000000000 -0500
+@@ -0,0 +1,20 @@
++#
++# Makefile for the ipmi drivers.
++#
++
++O_TARGET := ipmi.o
++
++export-objs := ipmi_msghandler.o ipmi_watchdog.o
++
++list-multi := ipmi_kcs_drv.o
++ipmi_kcs_drv-objs := ipmi_kcs_sm.o ipmi_kcs_intf.o
++
++obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o
++obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
++obj-$(CONFIG_IPMI_KCS) += ipmi_kcs_drv.o
++obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
++
++include $(TOPDIR)/Rules.make
++
++ipmi_kcs_drv.o: $(ipmi_kcs_drv-objs)
++ $(LD) -r -o $@ $(ipmi_kcs_drv-objs)
+--- /dev/null 2002-08-30 19:31:37.000000000 -0400
++++ linux-2.4.18-14/drivers/char/ipmi/ipmi_devintf.c 2003-03-27 15:26:22.000000000 -0500
+@@ -0,0 +1,532 @@
++/*
++ * ipmi_devintf.c
++ *
++ * Linux device interface for the IPMI message handler.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <asm/system.h>
++#include <linux/sched.h>
++#include <linux/poll.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/devfs_fs_kernel.h>
++#include <linux/ipmi.h>
++#include <asm/semaphore.h>
++#include <linux/init.h>
++
++struct ipmi_file_private
++{
++ ipmi_user_t user;
++ spinlock_t recv_msg_lock;
++ struct list_head recv_msgs;
++ struct file *file;
++ struct fasync_struct *fasync_queue;
++ wait_queue_head_t wait;
++ struct semaphore recv_sem;
++};
++
++static void file_receive_handler(struct ipmi_recv_msg *msg,
++ void *handler_data)
++{
++ struct ipmi_file_private *priv = handler_data;
++ int was_empty;
++ unsigned long flags;
++
++ spin_lock_irqsave(&(priv->recv_msg_lock), flags);
++
++ was_empty = list_empty(&(priv->recv_msgs));
++ list_add_tail(&(msg->link), &(priv->recv_msgs));
++
++ if (was_empty) {
++ wake_up_interruptible(&priv->wait);
++ kill_fasync(&priv->fasync_queue, SIGIO, POLL_IN);
++ }
++
++ spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
++}
++
++static unsigned int ipmi_poll(struct file *file, poll_table *wait)
++{
++ struct ipmi_file_private *priv = file->private_data;
++ unsigned int mask = 0;
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->recv_msg_lock, flags);
++
++ poll_wait(file, &priv->wait, wait);
++
++ if (! list_empty(&(priv->recv_msgs)))
++ mask |= (POLLIN | POLLRDNORM);
++
++ spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
++
++ return mask;
++}
++
++static int ipmi_fasync(int fd, struct file *file, int on)
++{
++ struct ipmi_file_private *priv = file->private_data;
++ int result;
++
++ result = fasync_helper(fd, file, on, &priv->fasync_queue);
++
++ return (result);
++}
++
++static struct ipmi_user_hndl ipmi_hndlrs =
++{
++ ipmi_recv_hndl : file_receive_handler
++};
++
++static int ipmi_open(struct inode *inode, struct file *file)
++{
++ int if_num = minor(inode->i_rdev);
++ int rv;
++ struct ipmi_file_private *priv;
++
++
++ priv = kmalloc(sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->file = file;
++
++ rv = ipmi_create_user(if_num,
++ &ipmi_hndlrs,
++ priv,
++ &(priv->user));
++ if (rv) {
++ kfree(priv);
++ return rv;
++ }
++
++ file->private_data = priv;
++
++ spin_lock_init(&(priv->recv_msg_lock));
++ INIT_LIST_HEAD(&(priv->recv_msgs));
++ init_waitqueue_head(&priv->wait);
++ priv->fasync_queue = NULL;
++ sema_init(&(priv->recv_sem), 1);
++
++ return 0;
++}
++
++static int ipmi_release(struct inode *inode, struct file *file)
++{
++ struct ipmi_file_private *priv = file->private_data;
++ int rv;
++
++ rv = ipmi_destroy_user(priv->user);
++ if (rv)
++ return rv;
++
++ ipmi_fasync (-1, file, 0);
++
++ /* FIXME - free the messages in the list. */
++ kfree(priv);
++
++ return 0;
++}
++
++static int ipmi_ioctl(struct inode *inode,
++ struct file *file,
++ unsigned int cmd,
++ unsigned long data)
++{
++ int rv = -EINVAL;
++ struct ipmi_file_private *priv = file->private_data;
++
++ switch (cmd)
++ {
++ case IPMICTL_SEND_COMMAND:
++ {
++ struct ipmi_req req;
++ struct ipmi_addr addr;
++ unsigned char msgdata[IPMI_MAX_MSG_LENGTH];
++
++ if (copy_from_user(&req, (void *) data, sizeof(req))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ if (req.addr_len > sizeof(struct ipmi_addr))
++ {
++ rv = -EINVAL;
++ break;
++ }
++
++ if (copy_from_user(&addr, req.addr, req.addr_len)) {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = ipmi_validate_addr(&addr, req.addr_len);
++ if (rv)
++ break;
++
++ if (req.msg.data != NULL) {
++ if (req.msg.data_len > IPMI_MAX_MSG_LENGTH) {
++ rv = -EMSGSIZE;
++ break;
++ }
++
++ if (copy_from_user(&msgdata,
++ req.msg.data,
++ req.msg.data_len))
++ {
++ rv = -EFAULT;
++ break;
++ }
++ } else {
++ req.msg.data_len = 0;
++ }
++
++ req.msg.data = msgdata;
++
++ rv = ipmi_request(priv->user,
++ &addr,
++ req.msgid,
++ &(req.msg),
++ 0);
++ break;
++ }
++
++ case IPMICTL_RECEIVE_MSG:
++ case IPMICTL_RECEIVE_MSG_TRUNC:
++ {
++ struct ipmi_recv rsp;
++ int addr_len;
++ struct list_head *entry;
++ struct ipmi_recv_msg *msg;
++ unsigned long flags;
++
++
++ rv = 0;
++ if (copy_from_user(&rsp, (void *) data, sizeof(rsp))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ /* We claim a semaphore because we don't want two
++ users getting something from the queue at a time.
++ Since we have to release the spinlock before we can
++ copy the data to the user, it's possible another
++ user will grab something from the queue, too. Then
++ the messages might get out of order if something
++ fails and the message gets put back onto the
++ queue. This semaphore prevents that problem. */
++ down(&(priv->recv_sem));
++
++ /* Grab the message off the list. */
++ spin_lock_irqsave(&(priv->recv_msg_lock), flags);
++ if (list_empty(&(priv->recv_msgs))) {
++ spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
++ rv = -EAGAIN;
++ goto recv_err;
++ }
++ entry = priv->recv_msgs.next;
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ list_del(entry);
++ spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
++
++ addr_len = ipmi_addr_length(msg->addr.addr_type);
++ if (rsp.addr_len < addr_len)
++ {
++ rv = -EINVAL;
++ goto recv_putback_on_err;
++ }
++
++ if (copy_to_user(rsp.addr, &(msg->addr), addr_len)) {
++ rv = -EFAULT;
++ goto recv_putback_on_err;
++ }
++ rsp.addr_len = addr_len;
++
++ rsp.recv_type = msg->recv_type;
++ rsp.msgid = msg->msgid;
++ rsp.msg.netfn = msg->msg.netfn;
++ rsp.msg.cmd = msg->msg.cmd;
++
++ if (msg->msg.data_len > 0) {
++ if (rsp.msg.data_len < msg->msg.data_len) {
++ rv = -EMSGSIZE;
++ if (cmd == IPMICTL_RECEIVE_MSG_TRUNC) {
++ msg->msg.data_len = rsp.msg.data_len;
++ } else {
++ goto recv_putback_on_err;
++ }
++ }
++
++ if (copy_to_user(rsp.msg.data,
++ msg->msg.data,
++ msg->msg.data_len))
++ {
++ rv = -EFAULT;
++ goto recv_putback_on_err;
++ }
++ rsp.msg.data_len = msg->msg.data_len;
++ } else {
++ rsp.msg.data_len = 0;
++ }
++
++ if (copy_to_user((void *) data, &rsp, sizeof(rsp))) {
++ rv = -EFAULT;
++ goto recv_putback_on_err;
++ }
++
++ up(&(priv->recv_sem));
++ ipmi_free_recv_msg(msg);
++ break;
++
++ recv_putback_on_err:
++ /* If we got an error, put the message back onto
++ the head of the queue. */
++ spin_lock_irqsave(&(priv->recv_msg_lock), flags);
++ list_add(entry, &(priv->recv_msgs));
++ spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
++ up(&(priv->recv_sem));
++ break;
++
++ recv_err:
++ up(&(priv->recv_sem));
++ break;
++ }
++
++ case IPMICTL_REGISTER_FOR_CMD:
++ {
++ struct ipmi_cmdspec val;
++
++ if (copy_from_user(&val, (void *) data, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd);
++ break;
++ }
++
++ case IPMICTL_UNREGISTER_FOR_CMD:
++ {
++ struct ipmi_cmdspec val;
++
++ if (copy_from_user(&val, (void *) data, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd);
++ break;
++ }
++
++ case IPMICTL_SET_GETS_EVENTS_CMD:
++ {
++ int val;
++
++ if (copy_from_user(&val, (void *) data, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ rv = ipmi_set_gets_events(priv->user, val);
++ break;
++ }
++
++ case IPMICTL_SET_MY_ADDRESS_CMD:
++ {
++ unsigned int val;
++
++ if (copy_from_user(&val, (void *) data, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ ipmi_set_my_address(priv->user, val);
++ rv = 0;
++ break;
++ }
++
++ case IPMICTL_GET_MY_ADDRESS_CMD:
++ {
++ unsigned int val;
++
++ val = ipmi_get_my_address(priv->user);
++
++ if (copy_to_user((void *) data, &val, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++ rv = 0;
++ break;
++ }
++
++ case IPMICTL_SET_MY_LUN_CMD:
++ {
++ unsigned int val;
++
++ if (copy_from_user(&val, (void *) data, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++
++ ipmi_set_my_LUN(priv->user, val);
++ rv = 0;
++ break;
++ }
++
++ case IPMICTL_GET_MY_LUN_CMD:
++ {
++ unsigned int val;
++
++ val = ipmi_get_my_LUN(priv->user);
++
++ if (copy_to_user((void *) data, &val, sizeof(val))) {
++ rv = -EFAULT;
++ break;
++ }
++ rv = 0;
++ break;
++ }
++
++ }
++
++ return rv;
++}
++
++
++static struct file_operations ipmi_fops = {
++ owner: THIS_MODULE,
++ ioctl: ipmi_ioctl,
++ open: ipmi_open,
++ release: ipmi_release,
++ fasync: ipmi_fasync,
++ poll: ipmi_poll
++};
++
++#define DEVICE_NAME "ipmidev"
++
++static int ipmi_major = 0;
++MODULE_PARM(ipmi_major, "i");
++
++static devfs_handle_t devfs_handle;
++
++#define MAX_DEVICES 10
++static devfs_handle_t handles[MAX_DEVICES];
++
++static void ipmi_new_smi(int if_num)
++{
++ char name[2];
++
++ if (if_num > MAX_DEVICES)
++ return;
++
++ name[0] = if_num + '0';
++ name[1] = '\0';
++
++ handles[if_num] = devfs_register(devfs_handle, name, DEVFS_FL_NONE,
++ ipmi_major, if_num,
++ S_IFCHR | S_IRUSR | S_IWUSR,
++ &ipmi_fops, NULL);
++}
++
++static void ipmi_smi_gone(int if_num)
++{
++ if (if_num > MAX_DEVICES)
++ return;
++
++ devfs_unregister(handles[if_num]);
++}
++
++static struct ipmi_smi_watcher smi_watcher =
++{
++ new_smi : ipmi_new_smi,
++ smi_gone : ipmi_smi_gone
++};
++
++static __init int init_ipmi_devintf(void)
++{
++ int rv;
++
++ if (ipmi_major < 0)
++ return -EINVAL;
++
++ rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
++ if (rv < 0) {
++ printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major);
++ return rv;
++ }
++
++ if (ipmi_major == 0) {
++ ipmi_major = rv;
++ }
++
++ devfs_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL);
++
++ rv = ipmi_smi_watcher_register(&smi_watcher);
++ if (rv) {
++ unregister_chrdev(ipmi_major, DEVICE_NAME);
++ printk(KERN_WARNING "ipmi: can't register smi watcher");
++ return rv;
++ }
++
++ printk(KERN_INFO "ipmi: device interface at char major %d\n",
++ ipmi_major);
++
++ return 0;
++}
++module_init(init_ipmi_devintf);
++
++static __exit void cleanup_ipmi(void)
++{
++ ipmi_smi_watcher_unregister(&smi_watcher);
++ devfs_unregister(devfs_handle);
++ unregister_chrdev(ipmi_major, DEVICE_NAME);
++}
++module_exit(cleanup_ipmi);
++#ifndef MODULE
++static __init int ipmi_setup (char *str)
++{
++ int x;
++
++ if (get_option (&str, &x)) {
++ /* ipmi=x sets the major number to x. */
++ ipmi_major = x;
++ } else if (!strcmp(str, "off")) {
++ ipmi_major = -1;
++ }
++
++ return 1;
++}
++#endif
++
++__setup("ipmi=", ipmi_setup);
++MODULE_LICENSE("GPL");
+--- /dev/null 2002-08-30 19:31:37.000000000 -0400
++++ linux-2.4.18-14/drivers/char/ipmi/ipmi_kcs_intf.c 2003-03-27 15:26:22.000000000 -0500
+@@ -0,0 +1,1243 @@
++/*
++ * ipmi_kcs_intf.c
++ *
++ * The interface to the IPMI driver for the KCS.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++/*
++ * This file holds the "policy" for the interface to the KCS state
++ * machine. It does the configuration, handles timers and interrupts,
++ * and drives the real KCS state machine.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <asm/system.h>
++#include <linux/sched.h>
++#include <linux/timer.h>
++#include <linux/errno.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/list.h>
++#include <linux/ioport.h>
++#ifdef CONFIG_HIGH_RES_TIMERS
++#include <linux/hrtime.h>
++#endif
++#include <linux/interrupt.h>
++#include <linux/ipmi_smi.h>
++#include <asm/io.h>
++#include "ipmi_kcs_sm.h"
++#include <linux/init.h>
++
++/* Measure times between events in the driver. */
++#undef DEBUG_TIMING
++
++#ifdef CONFIG_IPMI_KCS
++/* This forces a dependency to the config file for this option. */
++#endif
++
++enum kcs_intf_state {
++ KCS_NORMAL,
++ KCS_GETTING_FLAGS,
++ KCS_GETTING_EVENTS,
++ KCS_CLEARING_FLAGS,
++ KCS_CLEARING_FLAGS_THEN_SET_IRQ,
++ KCS_GETTING_MESSAGES,
++ KCS_ENABLE_INTERRUPTS1,
++ KCS_ENABLE_INTERRUPTS2
++ /* FIXME - add watchdog stuff. */
++};
++
++struct kcs_info
++{
++ ipmi_smi_t intf;
++ struct kcs_data *kcs_sm;
++ spinlock_t kcs_lock;
++ spinlock_t msg_lock;
++ struct list_head xmit_msgs;
++ struct list_head hp_xmit_msgs;
++ struct ipmi_smi_msg *curr_msg;
++ enum kcs_intf_state kcs_state;
++
++ /* Flags from the last GET_MSG_FLAGS command, used when an ATTN
++ is set to hold the flags until we are done handling everything
++ from the flags. */
++#define RECEIVE_MSG_AVAIL 0x01
++#define EVENT_MSG_BUFFER_FULL 0x02
++#define WDT_PRE_TIMEOUT_INT 0x08
++ unsigned char msg_flags;
++
++ /* If set to true, this will request events the next time the
++ state machine is idle. */
++ atomic_t req_events;
++
++ /* If true, run the state machine to completion on every send
++ call. Generally used after a panic to make sure stuff goes
++ out. */
++ int run_to_completion;
++
++ /* The I/O port of a KCS interface. */
++ int port;
++
++ /* zero if no irq; */
++ int irq;
++
++ /* The physical and remapped memory addresses of a KCS interface. */
++ unsigned long physaddr;
++ unsigned char *addr;
++
++ /* The timer for this kcs. */
++ struct timer_list kcs_timer;
++
++ /* The time (in jiffies) the last timeout occurred at. */
++ unsigned long last_timeout_jiffies;
++
++ /* Used to gracefully stop the timer without race conditions. */
++ volatile int stop_operation;
++ volatile int timer_stopped;
++
++ /* The driver will disable interrupts when it gets into a
++ situation where it cannot handle messages due to lack of
++ memory. Once that situation clears up, it will re-enable
++ interupts. */
++ int interrupt_disabled;
++};
++
++static void deliver_recv_msg(struct kcs_info *kcs_info, struct ipmi_smi_msg *msg)
++{
++ /* Deliver the message to the upper layer with the lock
++ released. */
++ spin_unlock(&(kcs_info->kcs_lock));
++ ipmi_smi_msg_received(kcs_info->intf, msg);
++ spin_lock(&(kcs_info->kcs_lock));
++}
++
++static void return_hosed_msg(struct kcs_info *kcs_info)
++{
++ struct ipmi_smi_msg *msg = kcs_info->curr_msg;
++
++ /* Make it a reponse */
++ msg->rsp[0] = msg->data[0] | 4;
++ msg->rsp[1] = msg->data[1];
++ msg->rsp[2] = 0xFF; /* Unknown error. */
++ msg->rsp_size = 3;
++
++ kcs_info->curr_msg = NULL;
++ deliver_recv_msg(kcs_info, msg);
++}
++
++static enum kcs_result start_next_msg(struct kcs_info *kcs_info)
++{
++ int rv;
++ struct list_head *entry = NULL;
++#ifdef DEBUG_TIMING
++ struct timeval t;
++#endif
++
++ /* No need to save flags, we aleady have interrupts off and we
++ already hold the KCS lock. */
++ spin_lock(&(kcs_info->msg_lock));
++
++ /* Pick the high priority queue first. */
++ if (! list_empty(&(kcs_info->hp_xmit_msgs))) {
++ entry = kcs_info->hp_xmit_msgs.next;
++ } else if (! list_empty(&(kcs_info->xmit_msgs))) {
++ entry = kcs_info->xmit_msgs.next;
++ }
++
++ if (!entry) {
++ kcs_info->curr_msg = NULL;
++ rv = KCS_SM_IDLE;
++ } else {
++ int err;
++
++ list_del(entry);
++ kcs_info->curr_msg = list_entry(entry,
++ struct ipmi_smi_msg,
++ link);
++#ifdef DEBUG_TIMING
++ do_gettimeofday(&t);
++ printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++ err = start_kcs_transaction(kcs_info->kcs_sm,
++ kcs_info->curr_msg->data,
++ kcs_info->curr_msg->data_size);
++ if (err) {
++ return_hosed_msg(kcs_info);
++ }
++
++ rv = KCS_CALL_WITHOUT_DELAY;
++ }
++ spin_unlock(&(kcs_info->msg_lock));
++
++ return rv;
++}
++
++static void start_enable_irq(struct kcs_info *kcs_info)
++{
++ unsigned char msg[2];
++
++ /* If we are enabling interrupts, we have to tell the
++ BMC to use them. */
++ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
++
++ start_kcs_transaction(kcs_info->kcs_sm, msg, 2);
++ kcs_info->kcs_state = KCS_ENABLE_INTERRUPTS1;
++}
++
++static void start_clear_flags(struct kcs_info *kcs_info)
++{
++ unsigned char msg[3];
++
++ /* Make sure the watchdog pre-timeout flag is not set at startup. */
++ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
++ msg[2] = WDT_PRE_TIMEOUT_INT;
++
++ start_kcs_transaction(kcs_info->kcs_sm, msg, 3);
++ kcs_info->kcs_state = KCS_CLEARING_FLAGS;
++}
++
++/* When we have a situtaion where we run out of memory and cannot
++ allocate messages, we just leave them in the BMC and run the system
++ polled until we can allocate some memory. Once we have some
++ memory, we will re-enable the interrupt. */
++static inline void disable_kcs_irq(struct kcs_info *kcs_info)
++{
++ if ((kcs_info->irq) && (!kcs_info->interrupt_disabled)) {
++ disable_irq_nosync(kcs_info->irq);
++ kcs_info->interrupt_disabled = 1;
++ }
++}
++
++static inline void enable_kcs_irq(struct kcs_info *kcs_info)
++{
++ if ((kcs_info->irq) && (kcs_info->interrupt_disabled)) {
++ enable_irq(kcs_info->irq);
++ kcs_info->interrupt_disabled = 0;
++ }
++}
++
++static void handle_flags(struct kcs_info *kcs_info)
++{
++ if (kcs_info->msg_flags & WDT_PRE_TIMEOUT_INT) {
++ /* Watchdog pre-timeout */
++ start_clear_flags(kcs_info);
++ kcs_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
++ spin_unlock(&(kcs_info->kcs_lock));
++ ipmi_smi_watchdog_pretimeout(kcs_info->intf);
++ spin_lock(&(kcs_info->kcs_lock));
++ } else if (kcs_info->msg_flags & RECEIVE_MSG_AVAIL) {
++ /* Messages available. */
++ kcs_info->curr_msg = ipmi_alloc_smi_msg();
++ if (!kcs_info->curr_msg) {
++ disable_kcs_irq(kcs_info);
++ kcs_info->kcs_state = KCS_NORMAL;
++ return;
++ }
++ enable_kcs_irq(kcs_info);
++
++ kcs_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ kcs_info->curr_msg->data[1] = IPMI_GET_MSG_CMD;
++ kcs_info->curr_msg->data_size = 2;
++
++ start_kcs_transaction(kcs_info->kcs_sm,
++ kcs_info->curr_msg->data,
++ kcs_info->curr_msg->data_size);
++ kcs_info->kcs_state = KCS_GETTING_MESSAGES;
++ } else if (kcs_info->msg_flags & EVENT_MSG_BUFFER_FULL) {
++ /* Events available. */
++ kcs_info->curr_msg = ipmi_alloc_smi_msg();
++ if (!kcs_info->curr_msg) {
++ disable_kcs_irq(kcs_info);
++ kcs_info->kcs_state = KCS_NORMAL;
++ return;
++ }
++ enable_kcs_irq(kcs_info);
++
++ kcs_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ kcs_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD;
++ kcs_info->curr_msg->data_size = 2;
++
++ start_kcs_transaction(kcs_info->kcs_sm,
++ kcs_info->curr_msg->data,
++ kcs_info->curr_msg->data_size);
++ kcs_info->kcs_state = KCS_GETTING_EVENTS;
++ } else {
++ kcs_info->kcs_state = KCS_NORMAL;
++ }
++}
++
++static void handle_transaction_done(struct kcs_info *kcs_info)
++{
++ struct ipmi_smi_msg *msg;
++#ifdef DEBUG_TIMING
++ struct timeval t;
++
++ do_gettimeofday(&t);
++ printk("**Done: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++ switch (kcs_info->kcs_state) {
++ case KCS_NORMAL:
++ kcs_info->curr_msg->rsp_size
++ = kcs_get_result(kcs_info->kcs_sm,
++ kcs_info->curr_msg->rsp,
++ IPMI_MAX_MSG_LENGTH);
++
++ /* Do this here becase deliver_recv_msg() releases the
++ lock, and a new message can be put in during the
++ time the lock is released. */
++ msg = kcs_info->curr_msg;
++ kcs_info->curr_msg = NULL;
++ deliver_recv_msg(kcs_info, msg);
++ break;
++
++ case KCS_GETTING_FLAGS:
++ {
++ unsigned char msg[4];
++ unsigned int len;
++
++ /* We got the flags from the KCS, now handle them. */
++ len = kcs_get_result(kcs_info->kcs_sm, msg, 4);
++ if (msg[2] != 0) {
++ /* Error fetching flags, just give up for
++ now. */
++ kcs_info->kcs_state = KCS_NORMAL;
++ } else if (len < 3) {
++ /* Hmm, no flags. That's technically illegal, but
++ don't use uninitialized data. */
++ kcs_info->kcs_state = KCS_NORMAL;
++ } else {
++ kcs_info->msg_flags = msg[3];
++ handle_flags(kcs_info);
++ }
++ break;
++ }
++
++ case KCS_CLEARING_FLAGS:
++ case KCS_CLEARING_FLAGS_THEN_SET_IRQ:
++ {
++ unsigned char msg[3];
++
++ /* We cleared the flags. */
++ kcs_get_result(kcs_info->kcs_sm, msg, 3);
++ if (msg[2] != 0) {
++ /* Error clearing flags */
++ printk(KERN_WARNING
++ "ipmi_kcs: Error clearing flags: %2.2x\n",
++ msg[2]);
++ }
++ if (kcs_info->kcs_state == KCS_CLEARING_FLAGS_THEN_SET_IRQ)
++ start_enable_irq(kcs_info);
++ else
++ kcs_info->kcs_state = KCS_NORMAL;
++ break;
++ }
++
++ case KCS_GETTING_EVENTS:
++ {
++ kcs_info->curr_msg->rsp_size
++ = kcs_get_result(kcs_info->kcs_sm,
++ kcs_info->curr_msg->rsp,
++ IPMI_MAX_MSG_LENGTH);
++
++ /* Do this here becase deliver_recv_msg() releases the
++ lock, and a new message can be put in during the
++ time the lock is released. */
++ msg = kcs_info->curr_msg;
++ kcs_info->curr_msg = NULL;
++ if (msg->rsp[2] != 0) {
++ /* Error getting event, probably done. */
++ msg->done(msg);
++
++ /* Take off the event flag. */
++ kcs_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
++ } else {
++ deliver_recv_msg(kcs_info, msg);
++ }
++ handle_flags(kcs_info);
++ break;
++ }
++
++ case KCS_GETTING_MESSAGES:
++ {
++ kcs_info->curr_msg->rsp_size
++ = kcs_get_result(kcs_info->kcs_sm,
++ kcs_info->curr_msg->rsp,
++ IPMI_MAX_MSG_LENGTH);
++
++ /* Do this here becase deliver_recv_msg() releases the
++ lock, and a new message can be put in during the
++ time the lock is released. */
++ msg = kcs_info->curr_msg;
++ kcs_info->curr_msg = NULL;
++ if (msg->rsp[2] != 0) {
++ /* Error getting event, probably done. */
++ msg->done(msg);
++
++ /* Take off the msg flag. */
++ kcs_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
++ } else {
++ deliver_recv_msg(kcs_info, msg);
++ }
++ handle_flags(kcs_info);
++ break;
++ }
++
++ case KCS_ENABLE_INTERRUPTS1:
++ {
++ unsigned char msg[4];
++
++ /* We got the flags from the KCS, now handle them. */
++ kcs_get_result(kcs_info->kcs_sm, msg, 4);
++ if (msg[2] != 0) {
++ printk(KERN_WARNING
++ "ipmi_kcs: Could not enable interrupts"
++ ", failed get, using polled mode.\n");
++ kcs_info->kcs_state = KCS_NORMAL;
++ } else {
++ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
++ msg[2] = msg[3] | 1; /* enable msg queue int */
++ start_kcs_transaction(kcs_info->kcs_sm, msg,3);
++ kcs_info->kcs_state = KCS_ENABLE_INTERRUPTS2;
++ }
++ break;
++ }
++
++ case KCS_ENABLE_INTERRUPTS2:
++ {
++ unsigned char msg[4];
++
++ /* We got the flags from the KCS, now handle them. */
++ kcs_get_result(kcs_info->kcs_sm, msg, 4);
++ if (msg[2] != 0) {
++ printk(KERN_WARNING
++ "ipmi_kcs: Could not enable interrupts"
++ ", failed set, using polled mode.\n");
++ }
++ kcs_info->kcs_state = KCS_NORMAL;
++ break;
++ }
++ }
++}
++
++/* Called on timeouts and events. Timeouts should pass the elapsed
++ time, interrupts should pass in zero. */
++static enum kcs_result kcs_event_handler(struct kcs_info *kcs_info, int time)
++{
++ enum kcs_result kcs_result;
++
++ restart:
++ /* There used to be a loop here that waited a little while
++ (around 25us) before giving up. That turned out to be
++ pointless, the minimum delays I was seeing were in the 300us
++ range, which is far too long to wait in an interrupt. So
++ we just run until the state machine tells us something
++ happened or it needs a delay. */
++ kcs_result = kcs_event(kcs_info->kcs_sm, time);
++ time = 0;
++ while (kcs_result == KCS_CALL_WITHOUT_DELAY)
++ {
++ kcs_result = kcs_event(kcs_info->kcs_sm, 0);
++ }
++
++ if (kcs_result == KCS_TRANSACTION_COMPLETE)
++ {
++ handle_transaction_done(kcs_info);
++ kcs_result = kcs_event(kcs_info->kcs_sm, 0);
++ }
++ else if (kcs_result == KCS_SM_HOSED)
++ {
++ if (kcs_info->curr_msg != NULL) {
++ /* If we were handling a user message, format
++ a response to send to the upper layer to
++ tell it about the error. */
++ return_hosed_msg(kcs_info);
++ }
++ kcs_result = kcs_event(kcs_info->kcs_sm, 0);
++ kcs_info->kcs_state = KCS_NORMAL;
++ }
++
++ /* We prefer handling attn over new messages. */
++ if (kcs_result == KCS_ATTN)
++ {
++ unsigned char msg[2];
++
++ /* Got a attn, send down a get message flags to see
++ what's causing it. It would be better to handle
++ this in the upper layer, but due to the way
++ interrupts work with the KCS, that's not really
++ possible. */
++ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg[1] = IPMI_GET_MSG_FLAGS_CMD;
++
++ start_kcs_transaction(kcs_info->kcs_sm, msg, 2);
++ kcs_info->kcs_state = KCS_GETTING_FLAGS;
++ goto restart;
++ }
++
++ /* If we are currently idle, try to start the next message. */
++ if (kcs_result == KCS_SM_IDLE) {
++ kcs_result = start_next_msg(kcs_info);
++ if (kcs_result != KCS_SM_IDLE)
++ goto restart;
++ }
++
++ if ((kcs_result == KCS_SM_IDLE)
++ && (atomic_read(&kcs_info->req_events)))
++ {
++ /* We are idle and the upper layer requested that I fetch
++ events, so do so. */
++ unsigned char msg[2];
++
++ atomic_set(&kcs_info->req_events, 0);
++ msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg[1] = IPMI_GET_MSG_FLAGS_CMD;
++
++ start_kcs_transaction(kcs_info->kcs_sm, msg, 2);
++ kcs_info->kcs_state = KCS_GETTING_FLAGS;
++ goto restart;
++ }
++
++ return kcs_result;
++}
++
++static void sender(void *send_info,
++ struct ipmi_smi_msg *msg,
++ int priority)
++{
++ struct kcs_info *kcs_info = (struct kcs_info *) send_info;
++ enum kcs_result result;
++ unsigned long flags;
++#ifdef DEBUG_TIMING
++ struct timeval t;
++#endif
++
++ spin_lock_irqsave(&(kcs_info->msg_lock), flags);
++#ifdef DEBUG_TIMING
++ do_gettimeofday(&t);
++ printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++
++ if (kcs_info->run_to_completion) {
++ /* If we are running to completion, then throw it in
++ the list and run transactions until everything is
++ clear. Priority doesn't matter here. */
++ list_add_tail(&(msg->link), &(kcs_info->xmit_msgs));
++
++ /* We have to release the msg lock and claim the kcs
++ lock in this case, because of race conditions. */
++ spin_unlock_irqrestore(&(kcs_info->msg_lock), flags);
++
++ spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
++ result = kcs_event_handler(kcs_info, 0);
++ while (result != KCS_SM_IDLE) {
++ udelay(500);
++ result = kcs_event_handler(kcs_info, 500);
++ }
++ spin_unlock_irqrestore(&(kcs_info->kcs_lock), flags);
++ return;
++ } else {
++ if (priority > 0) {
++ list_add_tail(&(msg->link), &(kcs_info->hp_xmit_msgs));
++ } else {
++ list_add_tail(&(msg->link), &(kcs_info->xmit_msgs));
++ }
++ }
++ spin_unlock_irqrestore(&(kcs_info->msg_lock), flags);
++
++ spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
++ if ((kcs_info->kcs_state == KCS_NORMAL)
++ && (kcs_info->curr_msg == NULL))
++ {
++ start_next_msg(kcs_info);
++ }
++ spin_unlock_irqrestore(&(kcs_info->kcs_lock), flags);
++}
++
++static void set_run_to_completion(void *send_info, int i_run_to_completion)
++{
++ struct kcs_info *kcs_info = (struct kcs_info *) send_info;
++ enum kcs_result result;
++ unsigned long flags;
++
++ spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
++
++ kcs_info->run_to_completion = i_run_to_completion;
++ if (i_run_to_completion) {
++ result = kcs_event_handler(kcs_info, 0);
++ while (result != KCS_SM_IDLE) {
++ udelay(500);
++ result = kcs_event_handler(kcs_info, 500);
++ }
++ }
++
++ spin_unlock_irqrestore(&(kcs_info->kcs_lock), flags);
++}
++
++static void request_events(void *send_info)
++{
++ struct kcs_info *kcs_info = (struct kcs_info *) send_info;
++
++ atomic_set(&kcs_info->req_events, 1);
++}
++
++static int new_user(void *send_info)
++{
++ if (!try_inc_mod_count(THIS_MODULE))
++ return -EBUSY;
++ return 0;
++}
++
++static void user_left(void *send_info)
++{
++ MOD_DEC_USE_COUNT;
++}
++
++/* Call every 10 ms. */
++#define KCS_TIMEOUT_TIME_USEC 10000
++#define KCS_USEC_PER_JIFFY (1000000/HZ)
++#define KCS_TIMEOUT_JIFFIES (KCS_TIMEOUT_TIME_USEC/KCS_USEC_PER_JIFFY)
++#define KCS_SHORT_TIMEOUT_USEC 500 /* .5ms when the SM request a
++ short timeout */
++static int initialized = 0;
++
++static void kcs_timeout(unsigned long data)
++{
++ struct kcs_info *kcs_info = (struct kcs_info *) data;
++ enum kcs_result kcs_result;
++ unsigned long flags;
++ unsigned long jiffies_now;
++ unsigned long time_diff;
++#ifdef DEBUG_TIMING
++ struct timeval t;
++#endif
++
++ if (kcs_info->stop_operation) {
++ kcs_info->timer_stopped = 1;
++ return;
++ }
++
++ spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
++#ifdef DEBUG_TIMING
++ do_gettimeofday(&t);
++ printk("**Timer: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++ jiffies_now = jiffies;
++ time_diff = ((jiffies_now - kcs_info->last_timeout_jiffies)
++ * KCS_USEC_PER_JIFFY);
++ kcs_result = kcs_event_handler(kcs_info, time_diff);
++
++ spin_unlock_irqrestore(&(kcs_info->kcs_lock), flags);
++
++ kcs_info->last_timeout_jiffies = jiffies_now;
++
++ if ((kcs_info->irq) && (! kcs_info->interrupt_disabled)) {
++ /* Running with interrupts, only do long timeouts. */
++ kcs_info->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES;
++ goto do_add_timer;
++ }
++
++ /* If the state machine asks for a short delay, then shorten
++ the timer timeout. */
++#ifdef CONFIG_HIGH_RES_TIMERS
++ if (kcs_result == KCS_CALL_WITH_DELAY) {
++ kcs_info->kcs_timer.sub_expires
++ += usec_to_arch_cycles(KCS_SHORT_TIMEOUT_USEC);
++ while (kcs_info->kcs_timer.sub_expires >= cycles_per_jiffies) {
++ kcs_info->kcs_timer.expires++;
++ kcs_info->kcs_timer.sub_expires -= cycles_per_jiffies;
++ }
++ } else {
++ kcs_info->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES;
++ }
++#else
++ /* If requested, take the shortest delay possible */
++ if (kcs_result == KCS_CALL_WITH_DELAY) {
++ kcs_info->kcs_timer.expires = jiffies + 1;
++ } else {
++ kcs_info->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES;
++ }
++#endif
++
++ do_add_timer:
++ add_timer(&(kcs_info->kcs_timer));
++}
++
++static void kcs_irq_handler(int irq, void *data, struct pt_regs *regs)
++{
++ struct kcs_info *kcs_info = (struct kcs_info *) data;
++ unsigned long flags;
++#ifdef DEBUG_TIMING
++ struct timeval t;
++#endif
++
++ spin_lock_irqsave(&(kcs_info->kcs_lock), flags);
++ if (kcs_info->stop_operation)
++ goto out;
++
++#ifdef DEBUG_TIMING
++ do_gettimeofday(&t);
++ printk("**Interrupt: %d.%9.9d\n", t.tv_sec, t.tv_usec);
++#endif
++ kcs_event_handler(kcs_info, 0);
++ out:
++ spin_unlock_irqrestore(&(kcs_info->kcs_lock), flags);
++}
++
++static struct ipmi_smi_handlers handlers =
++{
++ sender: sender,
++ request_events: request_events,
++ new_user: new_user,
++ user_left: user_left,
++ set_run_to_completion: set_run_to_completion
++};
++
++static unsigned char ipmi_kcs_dev_rev;
++static unsigned char ipmi_kcs_fw_rev_major;
++static unsigned char ipmi_kcs_fw_rev_minor;
++static unsigned char ipmi_version_major;
++static unsigned char ipmi_version_minor;
++
++extern int kcs_dbg;
++static int ipmi_kcs_detect_hardware(unsigned int port,
++ unsigned char *addr,
++ struct kcs_data *data)
++{
++ unsigned char msg[2];
++ unsigned char resp[IPMI_MAX_MSG_LENGTH];
++ unsigned long resp_len;
++ enum kcs_result kcs_result;
++
++ /* It's impossible for the KCS status register to be all 1's,
++ (assuming a properly functioning, self-initialized BMC)
++ but that's what you get from reading a bogus address, so we
++ test that first. */
++
++ if (port) {
++ if (inb(port+1) == 0xff) return -ENODEV;
++ } else {
++ if (readb(addr+1) == 0xff) return -ENODEV;
++ }
++
++ /* Do a Get Device ID command, since it comes back with some
++ useful info. */
++ msg[0] = IPMI_NETFN_APP_REQUEST << 2;
++ msg[1] = IPMI_GET_DEVICE_ID_CMD;
++ start_kcs_transaction(data, msg, 2);
++
++ kcs_result = kcs_event(data, 0);
++ for (;;)
++ {
++ if (kcs_result == KCS_CALL_WITH_DELAY) {
++ udelay(100);
++ kcs_result = kcs_event(data, 100);
++ }
++ else if (kcs_result == KCS_CALL_WITHOUT_DELAY)
++ {
++ kcs_result = kcs_event(data, 0);
++ }
++ else
++ break;
++ }
++ if (kcs_result == KCS_SM_HOSED) {
++ /* We couldn't get the state machine to run, so whatever's at
++ the port is probably not an IPMI KCS interface. */
++ return -ENODEV;
++ }
++ /* Otherwise, we got some data. */
++ resp_len = kcs_get_result(data, resp, IPMI_MAX_MSG_LENGTH);
++ if (resp_len < 6)
++ /* That's odd, it should be longer. */
++ return -EINVAL;
++
++ if ((resp[1] != IPMI_GET_DEVICE_ID_CMD) || (resp[2] != 0))
++ /* That's odd, it shouldn't be able to fail. */
++ return -EINVAL;
++
++ ipmi_kcs_dev_rev = resp[4] & 0xf;
++ ipmi_kcs_fw_rev_major = resp[5] & 0x7f;
++ ipmi_kcs_fw_rev_minor = resp[6];
++ ipmi_version_major = resp[7] & 0xf;
++ ipmi_version_minor = resp[7] >> 4;
++
++ return 0;
++}
++
++/* There can be 4 IO ports passed in (with or without IRQs), 4 addresses,
++ a default IO port, and 1 ACPI/SPMI address. That sets KCS_MAX_DRIVERS */
++
++#define KCS_MAX_PARMS 4
++#define KCS_MAX_DRIVERS ((KCS_MAX_PARMS * 2) + 2)
++static struct kcs_info *kcs_infos[KCS_MAX_DRIVERS] =
++{ NULL, NULL, NULL, NULL };
++
++#define DEVICE_NAME "ipmi_kcs"
++
++#define DEFAULT_IO_PORT 0xca2
++
++static int kcs_trydefaults = 1;
++static unsigned long kcs_addrs[KCS_MAX_PARMS] = { 0, 0, 0, 0 };
++static int kcs_ports[KCS_MAX_PARMS] = { 0, 0, 0, 0 };
++static int kcs_irqs[KCS_MAX_PARMS] = { 0, 0, 0, 0 };
++
++MODULE_PARM(kcs_trydefaults, "i");
++MODULE_PARM(kcs_addrs, "1-4l");
++MODULE_PARM(kcs_irqs, "1-4i");
++MODULE_PARM(kcs_ports, "1-4i");
++
++/* Returns 0 if initialized, or negative on an error. */
++static int init_one_kcs(int kcs_port,
++ int irq,
++ unsigned long kcs_physaddr,
++ struct kcs_info **kcs)
++{
++ int rv;
++ struct kcs_info *new_kcs;
++
++ /* Did anything get passed in at all? Both == zero disables the
++ driver. */
++
++ if (!(kcs_port || kcs_physaddr))
++ return -ENODEV;
++
++ /* Only initialize a port OR a physical address on this call.
++ Also, IRQs can go with either ports or addresses. */
++
++ if (kcs_port && kcs_physaddr)
++ return -EINVAL;
++
++ new_kcs = kmalloc(kcs_size(), GFP_KERNEL);
++ if (!new_kcs) {
++ printk(KERN_ERR "ipmi_kcs: out of memory\n");
++ return -ENOMEM;
++ }
++
++ /* So we know not to free it unless we have allocated one. */
++ new_kcs->kcs_sm = NULL;
++
++ new_kcs->addr = NULL;
++ new_kcs->physaddr = kcs_physaddr;
++ new_kcs->port = kcs_port;
++
++ if (kcs_port) {
++ if (request_region(kcs_port, 2, DEVICE_NAME) == NULL) {
++ kfree(new_kcs);
++ printk(KERN_ERR
++ "ipmi_kcs: can't reserve port @ 0x%4.4x\n",
++ kcs_port);
++ return -EIO;
++ }
++ } else {
++ if (request_mem_region(kcs_physaddr, 2, DEVICE_NAME) == NULL) {
++ kfree(new_kcs);
++ printk(KERN_ERR
++ "ipmi_kcs: can't reserve memory @ 0x%lx\n",
++ kcs_physaddr);
++ return -EIO;
++ }
++ if ((new_kcs->addr = ioremap(kcs_physaddr, 2)) == NULL) {
++ kfree(new_kcs);
++ printk(KERN_ERR
++ "ipmi_kcs: can't remap memory at 0x%lx\n",
++ kcs_physaddr);
++ return -EIO;
++ }
++ }
++
++ new_kcs->kcs_sm = kmalloc(kcs_size(), GFP_KERNEL);
++ if (!new_kcs->kcs_sm) {
++ printk(KERN_ERR "ipmi_kcs: out of memory\n");
++ rv = -ENOMEM;
++ goto out_err;
++ }
++ init_kcs_data(new_kcs->kcs_sm, kcs_port, new_kcs->addr);
++ spin_lock_init(&(new_kcs->kcs_lock));
++ spin_lock_init(&(new_kcs->msg_lock));
++
++ rv = ipmi_kcs_detect_hardware(kcs_port, new_kcs->addr, new_kcs->kcs_sm);
++ if (rv) {
++ if (kcs_port)
++ printk(KERN_ERR
++ "ipmi_kcs: No KCS @ port 0x%4.4x\n",
++ kcs_port);
++ else
++ printk(KERN_ERR
++ "ipmi_kcs: No KCS @ addr 0x%lx\n",
++ kcs_physaddr);
++ goto out_err;
++ }
++
++ if (irq != 0) {
++ rv = request_irq(irq,
++ kcs_irq_handler,
++ SA_INTERRUPT,
++ DEVICE_NAME,
++ new_kcs);
++ if (rv) {
++ printk(KERN_WARNING
++ "ipmi_kcs: %s unable to claim interrupt %d,"
++ " running polled\n",
++ DEVICE_NAME, irq);
++ irq = 0;
++ }
++ }
++ new_kcs->irq = irq;
++
++ INIT_LIST_HEAD(&(new_kcs->xmit_msgs));
++ INIT_LIST_HEAD(&(new_kcs->hp_xmit_msgs));
++ new_kcs->curr_msg = NULL;
++ atomic_set(&new_kcs->req_events, 0);
++ new_kcs->run_to_completion = 0;
++
++ start_clear_flags(new_kcs);
++
++ if (irq) {
++ new_kcs->kcs_state = KCS_CLEARING_FLAGS_THEN_SET_IRQ;
++
++ printk(KERN_INFO
++ "ipmi_kcs: Acquiring BMC @ port=0x%x irq=%d\n",
++ kcs_port, irq);
++
++ } else {
++ if (kcs_port)
++ printk(KERN_INFO
++ "ipmi_kcs: Acquiring BMC @ port=0x%x\n",
++ kcs_port);
++ else
++ printk(KERN_INFO
++ "ipmi_kcs: Acquiring BMC @ addr=0x%lx\n",
++ kcs_physaddr);
++ }
++
++ rv = ipmi_register_smi(&handlers,
++ new_kcs,
++ ipmi_version_major,
++ ipmi_version_minor,
++ &(new_kcs->intf));
++ if (rv) {
++ free_irq(irq, new_kcs);
++ printk(KERN_ERR
++ "ipmi_kcs: Unable to register device: error %d\n",
++ rv);
++ goto out_err;
++ }
++
++ new_kcs->interrupt_disabled = 0;
++ new_kcs->timer_stopped = 0;
++ new_kcs->stop_operation = 0;
++
++ init_timer(&(new_kcs->kcs_timer));
++ new_kcs->kcs_timer.data = (long) new_kcs;
++ new_kcs->kcs_timer.function = kcs_timeout;
++ new_kcs->last_timeout_jiffies = jiffies;
++ new_kcs->kcs_timer.expires = jiffies + KCS_TIMEOUT_JIFFIES;
++ add_timer(&(new_kcs->kcs_timer));
++
++ *kcs = new_kcs;
++
++ return 0;
++
++ out_err:
++ if (kcs_port)
++ release_region (kcs_port, 2);
++ if (new_kcs->addr)
++ iounmap(new_kcs->addr);
++ if (kcs_physaddr)
++ release_mem_region(kcs_physaddr, 2);
++ if (new_kcs->kcs_sm)
++ kfree(new_kcs->kcs_sm);
++ kfree(new_kcs);
++ return rv;
++}
++
++#ifdef CONFIG_ACPI
++
++/* Retrieve the base physical address from ACPI tables. Originally
++ from Hewlett-Packard simple bmc.c, a GPL KCS driver. */
++
++#include <linux/acpi.h>
++/* A real hack, but everything's not there yet in 2.4. */
++#define COMPILER_DEPENDENT_UINT64 unsigned long
++#include <../drivers/acpi/include/acpi.h>
++#include <../drivers/acpi/include/actypes.h>
++
++struct SPMITable {
++ s8 Signature[4];
++ u32 Length;
++ u8 Revision;
++ u8 Checksum;
++ s8 OEMID[6];
++ s8 OEMTableID[8];
++ s8 OEMRevision[4];
++ s8 CreatorID[4];
++ s8 CreatorRevision[4];
++ s16 InterfaceType;
++ s16 SpecificationRevision;
++ u8 InterruptType;
++ u8 GPE;
++ s16 Reserved;
++ u64 GlobalSystemInterrupt;
++ u8 BaseAddress[12];
++ u8 UID[4];
++} __attribute__ ((packed));
++
++static unsigned long acpi_find_bmc(void)
++{
++ acpi_status status;
++ acpi_table_header *spmi;
++ static unsigned long io_base = 0;
++
++ if (io_base != 0)
++ return io_base;
++
++ status = acpi_get_firmware_table("SPMI", 1,
++ ACPI_LOGICAL_ADDRESSING, &spmi);
++
++ if (status != AE_OK) {
++ printk(KERN_ERR "ipmi_kcs: SPMI table not found.\n");
++ return 0;
++ }
++
++ memcpy(&io_base, ((struct SPMITable *)spmi)->BaseAddress,
++ sizeof(io_base));
++
++ return io_base;
++}
++#endif
++
++static __init int init_ipmi_kcs(void)
++{
++ int rv = 0;
++ int pos = 0;
++ int i = 0;
++#ifdef CONFIG_ACPI
++ unsigned long physaddr = 0;
++#endif
++
++ if (initialized)
++ return 0;
++ initialized = 1;
++
++ /* First do the "command-line" parameters */
++
++ for (i=0; i < KCS_MAX_PARMS; i++) {
++ rv = init_one_kcs(kcs_ports[i],
++ kcs_irqs[i],
++ 0,
++ &(kcs_infos[pos]));
++ if (rv == 0)
++ pos++;
++
++ rv = init_one_kcs(0,
++ kcs_irqs[i],
++ kcs_addrs[i],
++ &(kcs_infos[pos]));
++ if (rv == 0)
++ pos++;
++ }
++
++ /* Only try the defaults if enabled and resources are available
++ (because they weren't already specified above). */
++
++ if (kcs_trydefaults) {
++#ifdef CONFIG_ACPI
++ if ((physaddr = acpi_find_bmc())) {
++ if (!check_mem_region(physaddr, 2)) {
++ rv = init_one_kcs(0,
++ 0,
++ physaddr,
++ &(kcs_infos[pos]));
++ if (rv == 0)
++ pos++;
++ }
++ }
++#endif
++ if (!check_region(DEFAULT_IO_PORT, 2)) {
++ rv = init_one_kcs(DEFAULT_IO_PORT,
++ 0,
++ 0,
++ &(kcs_infos[pos]));
++ if (rv == 0)
++ pos++;
++ }
++ }
++
++ if (kcs_infos[0] == NULL) {
++ printk("ipmi_kcs: Unable to find any KCS interfaces\n");
++ return -ENODEV;
++ }
++
++ return 0;
++}
++module_init(init_ipmi_kcs);
++
++#ifdef MODULE
++void __exit cleanup_one_kcs(struct kcs_info *to_clean)
++{
++ int rv;
++ unsigned long flags;
++
++ if (! to_clean)
++ return;
++
++ /* Tell the timer and interrupt handlers that we are shutting
++ down. */
++ spin_lock_irqsave(&(to_clean->kcs_lock), flags);
++ spin_lock(&(to_clean->msg_lock));
++
++ to_clean->stop_operation = 1;
++
++ if (to_clean->irq != 0)
++ free_irq(to_clean->irq, to_clean);
++ if (to_clean->port) {
++ printk(KERN_INFO
++ "ipmi_kcs: Releasing BMC @ port=0x%x\n",
++ to_clean->port);
++ release_region (to_clean->port, 2);
++ }
++ if (to_clean->addr) {
++ printk(KERN_INFO
++ "ipmi_kcs: Releasing BMC @ addr=0x%lx\n",
++ to_clean->physaddr);
++ iounmap(to_clean->addr);
++ release_mem_region(to_clean->physaddr, 2);
++ }
++
++ spin_unlock(&(to_clean->msg_lock));
++ spin_unlock_irqrestore(&(to_clean->kcs_lock), flags);
++
++ /* Wait for the timer to stop. This avoids problems with race
++ conditions removing the timer here. Hopefully this will be
++ long enough to avoid problems with interrupts still
++ running. */
++ schedule_timeout(2);
++ while (!to_clean->timer_stopped) {
++ schedule_timeout(1);
++ }
++
++ rv = ipmi_unregister_smi(to_clean->intf);
++ if (rv) {
++ printk(KERN_ERR
++ "ipmi_kcs: Unable to unregister device: errno=%d\n",
++ rv);
++ }
++
++ initialized = 0;
++
++ kfree(to_clean->kcs_sm);
++ kfree(to_clean);
++}
++
++static __exit void cleanup_ipmi_kcs(void)
++{
++ int i;
++
++ if (!initialized)
++ return;
++
++ for (i=0; i<KCS_MAX_DRIVERS; i++) {
++ cleanup_one_kcs(kcs_infos[i]);
++ }
++}
++module_exit(cleanup_ipmi_kcs);
++#else
++
++/* Unfortunately, cmdline::get_options() only returns integers, not
++ longs. Since we need ulongs (64-bit physical addresses) parse the
++ comma-separated list manually. Arguments can be one of these forms:
++ m0xaabbccddeeff A physical memory address without an IRQ
++ m0xaabbccddeeff:cc A physical memory address with an IRQ
++ p0xaabb An IO port without an IRQ
++ p0xaabb:cc An IO port with an IRQ
++ nodefaults Suppress trying the default IO port or ACPI address
++
++ For example, to pass one IO port with an IRQ, one address, and
++ suppress the use of the default IO port and ACPI address,
++ use this option string: ipmi_kcs=p0xCA2:5,m0xFF5B0022,nodefaults
++
++ Remember, ipmi_kcs_setup() is passed the string after the equal sign. */
++
++static int __init ipmi_kcs_setup(char *str)
++{
++ unsigned long val;
++ char *cur, *colon;
++ int pos;
++
++ pos = 0;
++
++ cur = strsep(&str, ",");
++ while ((cur) && (*cur) && (pos < KCS_MAX_PARMS)) {
++ switch (*cur) {
++ case 'n':
++ if (strcmp(cur, "nodefaults") == 0)
++ kcs_trydefaults = 0;
++ else
++ printk(KERN_INFO
++ "ipmi_kcs: bad parameter value %s\n",
++ cur);
++ break;
++
++ case 'm':
++ case 'p':
++ val = simple_strtoul(cur + 1,
++ &colon,
++ 0);
++ if (*cur == 'p')
++ kcs_ports[pos] = val;
++ else
++ kcs_addrs[pos] = val;
++ if (*colon == ':') {
++ val = simple_strtoul(colon + 1,
++ &colon,
++ 0);
++ kcs_irqs[pos] = val;
++ }
++ pos++;
++ break;
++
++ default:
++ printk(KERN_INFO
++ "ipmi_kcs: bad parameter value %s\n",
++ cur);
++ }
++ cur = strsep(&str, ",");
++ }
++
++ return 1;
++}
++__setup("ipmi_kcs=", ipmi_kcs_setup);
++#endif
++
++MODULE_LICENSE("GPL");
+--- /dev/null 2002-08-30 19:31:37.000000000 -0400
++++ linux-2.4.18-14/drivers/char/ipmi/ipmi_kcs_sm.c 2003-03-27 15:26:22.000000000 -0500
+@@ -0,0 +1,485 @@
++/*
++ * ipmi_kcs_sm.c
++ *
++ * State machine for handling IPMI KCS interfaces.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++/*
++ * This state machine is taken from the state machine in the IPMI spec,
++ * pretty much verbatim. If you have questions about the states, see
++ * that document.
++ */
++
++#include <asm/io.h>
++#include <asm/string.h> /* Gets rid of memcpy warning */
++
++#include "ipmi_kcs_sm.h"
++
++/* Set this if you want a printout of why the state machine was hosed
++ when it gets hosed. */
++#define DEBUG_HOSED_REASON
++
++/* Print the state machine state on entry every time. */
++#undef DEBUG_STATE
++
++/* The states the KCS driver may be in. */
++enum kcs_states {
++ KCS_IDLE, /* The KCS interface is currently
++ doing nothing. */
++ KCS_START_OP, /* We are starting an operation. The
++ data is in the output buffer, but
++ nothing has been done to the
++ interface yet. This was added to
++ the state machine in the spec to
++ wait for the initial IBF. */
++ KCS_WAIT_WRITE_START, /* We have written a write cmd to the
++ interface. */
++ KCS_WAIT_WRITE, /* We are writing bytes to the
++ interface. */
++ KCS_WAIT_WRITE_END, /* We have written the write end cmd
++ to the interface, and still need to
++ write the last byte. */
++ KCS_WAIT_READ, /* We are waiting to read data from
++ the interface. */
++ KCS_ERROR0, /* State to transition to the error
++ handler, this was added to the
++ state machine in the spec to be
++ sure IBF was there. */
++ KCS_ERROR1, /* First stage error handler, wait for
++ the interface to respond. */
++ KCS_ERROR2, /* The abort cmd has been written,
++ wait for the interface to
++ respond. */
++ KCS_ERROR3, /* We wrote some data to the
++ interface, wait for it to switch to
++ read mode. */
++ KCS_HOSED /* The hardware failed to follow the
++ state machine. */
++};
++
++#define MAX_KCS_READ_SIZE 80
++#define MAX_KCS_WRITE_SIZE 80
++
++/* Timeouts in microseconds. */
++#define IBF_RETRY_TIMEOUT 1000000
++#define OBF_RETRY_TIMEOUT 1000000
++#define MAX_ERROR_RETRIES 10
++
++#define IPMI_ERR_MSG_TRUNCATED 0xc6
++#define IPMI_ERR_UNSPECIFIED 0xff
++
++struct kcs_data
++{
++ enum kcs_states state;
++ unsigned int port;
++ unsigned char *addr;
++ unsigned char write_data[MAX_KCS_WRITE_SIZE];
++ int write_pos;
++ int write_count;
++ int orig_write_count;
++ unsigned char read_data[MAX_KCS_READ_SIZE];
++ int read_pos;
++ int truncated;
++
++ unsigned int error_retries;
++ long ibf_timeout;
++ long obf_timeout;
++};
++
++void init_kcs_data(struct kcs_data *kcs, unsigned int port, unsigned char *addr)
++{
++ kcs->state = KCS_IDLE;
++ kcs->port = port;
++ kcs->addr = addr;
++ kcs->write_pos = 0;
++ kcs->write_count = 0;
++ kcs->orig_write_count = 0;
++ kcs->read_pos = 0;
++ kcs->error_retries = 0;
++ kcs->truncated = 0;
++ kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
++ kcs->obf_timeout = OBF_RETRY_TIMEOUT;
++}
++
++/* Remember, init_one_kcs() insured port and addr can't both be set */
++
++static inline unsigned char read_status(struct kcs_data *kcs)
++{
++ if (kcs->port)
++ return inb(kcs->port + 1);
++ else
++ return readb(kcs->addr + 1);
++}
++
++static inline unsigned char read_data(struct kcs_data *kcs)
++{
++ if (kcs->port)
++ return inb(kcs->port + 0);
++ else
++ return readb(kcs->addr + 0);
++}
++
++static inline void write_cmd(struct kcs_data *kcs, unsigned char data)
++{
++ if (kcs->port)
++ outb(data, kcs->port + 1);
++ else
++ writeb(data, kcs->addr + 1);
++}
++
++static inline void write_data(struct kcs_data *kcs, unsigned char data)
++{
++ if (kcs->port)
++ outb(data, kcs->port + 0);
++ else
++ writeb(data, kcs->addr + 0);
++}
++
++/* Control codes. */
++#define KCS_GET_STATUS_ABORT 0x60
++#define KCS_WRITE_START 0x61
++#define KCS_WRITE_END 0x62
++#define KCS_READ_BYTE 0x68
++
++/* Status bits. */
++#define GET_STATUS_STATE(status) (((status) >> 6) & 0x03)
++#define KCS_IDLE_STATE 0
++#define KCS_READ_STATE 1
++#define KCS_WRITE_STATE 2
++#define KCS_ERROR_STATE 3
++#define GET_STATUS_ATN(status) ((status) & 0x04)
++#define GET_STATUS_IBF(status) ((status) & 0x02)
++#define GET_STATUS_OBF(status) ((status) & 0x01)
++
++
++static inline void write_next_byte(struct kcs_data *kcs)
++{
++ write_data(kcs, kcs->write_data[kcs->write_pos]);
++ (kcs->write_pos)++;
++ (kcs->write_count)--;
++}
++
++static inline void start_error_recovery(struct kcs_data *kcs, char *reason)
++{
++ (kcs->error_retries)++;
++ if (kcs->error_retries > MAX_ERROR_RETRIES) {
++#ifdef DEBUG_HOSED_REASON
++ printk("ipmi_kcs_sm: kcs hosed: %s\n", reason);
++#endif
++ kcs->state = KCS_HOSED;
++ } else {
++ kcs->state = KCS_ERROR0;
++ }
++}
++
++static inline void read_next_byte(struct kcs_data *kcs)
++{
++ if (kcs->read_pos >= MAX_KCS_READ_SIZE) {
++ /* Throw the data away and mark it truncated. */
++ read_data(kcs);
++ kcs->truncated = 1;
++ } else {
++ kcs->read_data[kcs->read_pos] = read_data(kcs);
++ (kcs->read_pos)++;
++ }
++ write_data(kcs, KCS_READ_BYTE);
++}
++
++static inline int check_ibf(struct kcs_data *kcs,
++ unsigned char status,
++ long time)
++{
++ if (GET_STATUS_IBF(status)) {
++ kcs->ibf_timeout -= time;
++ if (kcs->ibf_timeout < 0) {
++ start_error_recovery(kcs, "IBF not ready in time");
++ kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
++ return 1;
++ }
++ return 0;
++ }
++ kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
++ return 1;
++}
++
++static inline int check_obf(struct kcs_data *kcs,
++ unsigned char status,
++ long time)
++{
++ if (! GET_STATUS_OBF(status)) {
++ kcs->obf_timeout -= time;
++ if (kcs->obf_timeout < 0) {
++ start_error_recovery(kcs, "OBF not ready in time");
++ return 1;
++ }
++ return 0;
++ }
++ kcs->obf_timeout = OBF_RETRY_TIMEOUT;
++ return 1;
++}
++
++static void clear_obf(struct kcs_data *kcs, unsigned char status)
++{
++ if (GET_STATUS_OBF(status))
++ read_data(kcs);
++}
++
++static void restart_kcs_transaction(struct kcs_data *kcs)
++{
++ kcs->write_count = kcs->orig_write_count;
++ kcs->write_pos = 0;
++ kcs->read_pos = 0;
++ kcs->state = KCS_WAIT_WRITE_START;
++ kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
++ kcs->obf_timeout = OBF_RETRY_TIMEOUT;
++ write_cmd(kcs, KCS_WRITE_START);
++}
++
++int start_kcs_transaction(struct kcs_data *kcs, char *data, unsigned int size)
++{
++ if ((size < 2) || (size > MAX_KCS_WRITE_SIZE)) {
++ return -1;
++ }
++
++ if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED)) {
++ return -2;
++ }
++
++ kcs->error_retries = 0;
++ memcpy(kcs->write_data, data, size);
++ kcs->write_count = size;
++ kcs->orig_write_count = size;
++ kcs->write_pos = 0;
++ kcs->read_pos = 0;
++ kcs->state = KCS_START_OP;
++ kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
++ kcs->obf_timeout = OBF_RETRY_TIMEOUT;
++ return 0;
++}
++
++int kcs_get_result(struct kcs_data *kcs, unsigned char *data, int length)
++{
++ if (length < kcs->read_pos) {
++ kcs->read_pos = length;
++ kcs->truncated = 1;
++ }
++
++ memcpy(data, kcs->read_data, kcs->read_pos);
++
++ if ((length >= 3) && (kcs->read_pos < 3)) {
++ /* Guarantee that we return at least 3 bytes, with an
++ error in the third byte if it is too short. */
++ data[2] = IPMI_ERR_UNSPECIFIED;
++ kcs->read_pos = 3;
++ }
++ if (kcs->truncated) {
++ /* Report a truncated error. We might overwrite
++ another error, but that's too bad, the user needs
++ to know it was truncated. */
++ data[2] = IPMI_ERR_MSG_TRUNCATED;
++ kcs->truncated = 0;
++ }
++
++ return kcs->read_pos;
++}
++
++/* This implements the state machine defined in the IPMI manual, see
++ that for details on how this works. Divide that flowchart into
++ sections delimited by "Wait for IBF" and this will become clear. */
++enum kcs_result kcs_event(struct kcs_data *kcs, long time)
++{
++ unsigned char status;
++ unsigned char state;
++
++ status = read_status(kcs);
++
++#ifdef DEBUG_STATE
++ printk(" State = %d, %x\n", kcs->state, status);
++#endif
++ /* All states wait for ibf, so just do it here. */
++ if (!check_ibf(kcs, status, time))
++ return KCS_CALL_WITH_DELAY;
++
++ /* Just about everything looks at the KCS state, so grab that, too. */
++ state = GET_STATUS_STATE(status);
++
++ switch (kcs->state) {
++ case KCS_IDLE:
++ /* If there's and interrupt source, turn it off. */
++ clear_obf(kcs, status);
++
++ if (GET_STATUS_ATN(status))
++ return KCS_ATTN;
++ else
++ return KCS_SM_IDLE;
++
++ case KCS_START_OP:
++ if (state != KCS_IDLE) {
++ start_error_recovery(kcs,
++ "State machine not idle at start");
++ break;
++ }
++
++ clear_obf(kcs, status);
++ write_cmd(kcs, KCS_WRITE_START);
++ kcs->state = KCS_WAIT_WRITE_START;
++ break;
++
++ case KCS_WAIT_WRITE_START:
++ if (state != KCS_WRITE_STATE) {
++ start_error_recovery(
++ kcs,
++ "Not in write state at write start");
++ break;
++ }
++ read_data(kcs);
++ if (kcs->write_count == 1) {
++ write_cmd(kcs, KCS_WRITE_END);
++ kcs->state = KCS_WAIT_WRITE_END;
++ } else {
++ write_next_byte(kcs);
++ kcs->state = KCS_WAIT_WRITE;
++ }
++ break;
++
++ case KCS_WAIT_WRITE:
++ if (state != KCS_WRITE_STATE) {
++ start_error_recovery(kcs,
++ "Not in write state for write");
++ break;
++ }
++ clear_obf(kcs, status);
++ if (kcs->write_count == 1) {
++ write_cmd(kcs, KCS_WRITE_END);
++ kcs->state = KCS_WAIT_WRITE_END;
++ } else {
++ write_next_byte(kcs);
++ }
++ break;
++
++ case KCS_WAIT_WRITE_END:
++ if (state != KCS_WRITE_STATE) {
++ start_error_recovery(kcs,
++ "Not in write state for write end");
++ break;
++ }
++ clear_obf(kcs, status);
++ write_next_byte(kcs);
++ kcs->state = KCS_WAIT_READ;
++ break;
++
++ case KCS_WAIT_READ:
++ if ((state != KCS_READ_STATE) && (state != KCS_IDLE_STATE)) {
++ start_error_recovery(
++ kcs,
++ "Not in read or idle in read state");
++ break;
++ }
++
++ if (state == KCS_READ_STATE) {
++ if (! check_obf(kcs, status, time))
++ return KCS_CALL_WITH_DELAY;
++ read_next_byte(kcs);
++ } else {
++ /* We don't implement this exactly like the state
++ machine in the spec. Some broken hardware
++ does not write the final dummy byte to the
++ read register. Thus obf will never go high
++ here. We just go straight to idle, and we
++ handle clearing out obf in idle state if it
++ happens to come in. */
++ clear_obf(kcs, status);
++ kcs->orig_write_count = 0;
++ kcs->state = KCS_IDLE;
++ return KCS_TRANSACTION_COMPLETE;
++ }
++ break;
++
++ case KCS_ERROR0:
++ clear_obf(kcs, status);
++ write_cmd(kcs, KCS_GET_STATUS_ABORT);
++ kcs->state = KCS_ERROR1;
++ break;
++
++ case KCS_ERROR1:
++ clear_obf(kcs, status);
++ write_data(kcs, 0);
++ kcs->state = KCS_ERROR2;
++ break;
++
++ case KCS_ERROR2:
++ if (state != KCS_READ_STATE) {
++ start_error_recovery(kcs,
++ "Not in read state for error2");
++ break;
++ }
++ if (! check_obf(kcs, status, time))
++ return KCS_CALL_WITH_DELAY;
++
++ clear_obf(kcs, status);
++ write_data(kcs, KCS_READ_BYTE);
++ kcs->state = KCS_ERROR3;
++ break;
++
++ case KCS_ERROR3:
++ if (state != KCS_IDLE_STATE) {
++ start_error_recovery(kcs,
++ "Not in idle state for error3");
++ break;
++ }
++
++ if (! check_obf(kcs, status, time))
++ return KCS_CALL_WITH_DELAY;
++
++ clear_obf(kcs, status);
++ if (kcs->orig_write_count) {
++ restart_kcs_transaction(kcs);
++ } else {
++ kcs->state = KCS_IDLE;
++ return KCS_TRANSACTION_COMPLETE;
++ }
++ break;
++
++ case KCS_HOSED:
++ return KCS_SM_HOSED;
++ }
++
++ if (kcs->state == KCS_HOSED) {
++ init_kcs_data(kcs, kcs->port, kcs->addr);
++ return KCS_SM_HOSED;
++ }
++
++ return KCS_CALL_WITHOUT_DELAY;
++}
++
++int kcs_size(void)
++{
++ return sizeof(struct kcs_data);
++}
+--- /dev/null 2002-08-30 19:31:37.000000000 -0400
++++ linux-2.4.18-14/drivers/char/ipmi/ipmi_kcs_sm.h 2003-03-27 15:26:22.000000000 -0500
+@@ -0,0 +1,70 @@
++/*
++ * ipmi_kcs_sm.h
++ *
++ * State machine for handling IPMI KCS interfaces.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++struct kcs_data;
++
++void init_kcs_data(struct kcs_data *kcs,
++ unsigned int port,
++ unsigned char *addr);
++
++/* Start a new transaction in the state machine. This will return -2
++ if the state machine is not idle, -1 if the size is invalid (to
++ large or too small), or 0 if the transaction is successfully
++ completed. */
++int start_kcs_transaction(struct kcs_data *kcs, char *data, unsigned int size);
++
++/* Return the results after the transaction. This will return -1 if
++ the buffer is too small, zero if no transaction is present, or the
++ actual length of the result data. */
++int kcs_get_result(struct kcs_data *kcs, unsigned char *data, int length);
++
++enum kcs_result
++{
++ KCS_CALL_WITHOUT_DELAY, /* Call the driver again immediately */
++ KCS_CALL_WITH_DELAY, /* Delay some before calling again. */
++ KCS_TRANSACTION_COMPLETE, /* A transaction is finished. */
++ KCS_SM_IDLE, /* The SM is in idle state. */
++ KCS_SM_HOSED, /* The hardware violated the state machine. */
++ KCS_ATTN /* The hardware is asserting attn and the
++ state machine is idle. */
++};
++
++/* Call this periodically (for a polled interface) or upon receiving
++ an interrupt (for a interrupt-driven interface). If interrupt
++ driven, you should probably poll this periodically when not in idle
++ state. This should be called with the time that passed since the
++ last call, if it is significant. Time is in microseconds. */
++enum kcs_result kcs_event(struct kcs_data *kcs, long time);
++
++/* Return the size of the KCS structure in bytes. */
++int kcs_size(void);
+--- /dev/null 2002-08-30 19:31:37.000000000 -0400
++++ linux-2.4.18-14/drivers/char/ipmi/ipmi_msghandler.c 2003-03-27 15:26:22.000000000 -0500
+@@ -0,0 +1,1984 @@
++/*
++ * ipmi_msghandler.c
++ *
++ * Incoming and outgoing message routing for an IPMI interface.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <asm/system.h>
++#include <linux/sched.h>
++#include <linux/poll.h>
++#include <linux/spinlock.h>
++#include <linux/rwsem.h>
++#include <linux/slab.h>
++#include <linux/ipmi.h>
++#include <linux/ipmi_smi.h>
++#include <linux/notifier.h>
++#include <linux/init.h>
++
++struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
++static int ipmi_init_msghandler(void);
++
++static int initialized = 0;
++
++#define MAX_EVENTS_IN_QUEUE 25
++
++/* Don't let a message sit in a queue forever, always time it with at lest
++ the max message timer. */
++#define MAX_MSG_TIMEOUT 60000
++
++struct ipmi_user
++{
++ struct list_head link;
++
++ /* The upper layer that handles receive messages. */
++ struct ipmi_user_hndl *handler;
++ void *handler_data;
++
++ /* The interface this user is bound to. */
++ ipmi_smi_t intf;
++
++ /* Does this interface receive IPMI events? */
++ int gets_events;
++};
++
++struct cmd_rcvr
++{
++ struct list_head link;
++
++ ipmi_user_t user;
++ unsigned char netfn;
++ unsigned char cmd;
++};
++
++struct seq_table
++{
++ int inuse : 1;
++
++ unsigned long timeout;
++ unsigned long orig_timeout;
++ unsigned int retries_left;
++
++ /* To verify on an incoming send message response that this is
++ the message that the response is for, we keep a sequence id
++ and increment it every time we send a message. */
++ long seqid;
++
++ /* This is held so we can properly respond to the message on a
++ timeout, and it is used to hold the temporary data for
++ retransmission, too. */
++ struct ipmi_recv_msg *recv_msg;
++};
++
++/* Store the information in a msgid (long) to allow us to find a
++ sequence table entry from the msgid. */
++#define STORE_SEQ_IN_MSGID(seq, seqid) (((seq&0xff)<<26) | (seqid&0x3ffffff))
++
++#define GET_SEQ_FROM_MSGID(msgid, seq, seqid) \
++ do { \
++ seq = ((msgid >> 26) & 0x3f); \
++ seqid = (msgid & 0x3fffff); \
++ } while(0)
++
++#define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3fffff)
++
++
++#define IPMI_IPMB_NUM_SEQ 64
++struct ipmi_smi
++{
++ /* The list of upper layers that are using me. We read-lock
++ this when delivering messages to the upper layer to keep
++ the user from going away while we are processing the
++ message. This means that you cannot add or delete a user
++ from the receive callback. */
++ rwlock_t users_lock;
++ struct list_head users;
++
++ /* The IPMI version of the BMC on the other end. */
++ unsigned char version_major;
++ unsigned char version_minor;
++
++ /* This is the lower-layer's sender routine. */
++ struct ipmi_smi_handlers *handlers;
++ void *send_info;
++
++ /* A table of sequence numbers for this interface. We use the
++ sequence numbers for IPMB messages that go out of the
++ interface to match them up with their responses. A routine
++ is called periodically to time the items in this list. */
++ spinlock_t seq_lock;
++ struct seq_table seq_table[IPMI_IPMB_NUM_SEQ];
++ int curr_seq;
++
++ /* Messages that were delayed for some reason (out of memory,
++ for instance), will go in here to be processed later in a
++ periodic timer interrupt. */
++ spinlock_t waiting_msgs_lock;
++ struct list_head waiting_msgs;
++
++ /* The list of command receivers that are registered for commands
++ on this interface. */
++ rwlock_t cmd_rcvr_lock;
++ struct list_head cmd_rcvrs;
++
++ /* Events that were queues because no one was there to receive
++ them. */
++ spinlock_t events_lock; /* For dealing with event stuff. */
++ struct list_head waiting_events;
++ unsigned int waiting_events_count; /* How many events in queue? */
++
++ /* This will be non-null if someone registers to receive all
++ IPMI commands (this is for interface emulation). There
++ may not be any things in the cmd_rcvrs list above when
++ this is registered. */
++ ipmi_user_t all_cmd_rcvr;
++
++ /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR,
++ but may be changed by the user. */
++ unsigned char my_address;
++
++ /* My LUN. This should generally stay the SMS LUN, but just in
++ case... */
++ unsigned char my_lun;
++};
++
++int
++ipmi_register_all_cmd_rcvr(ipmi_user_t user)
++{
++ int flags;
++ int rv = -EBUSY;
++
++ write_lock_irqsave(&(user->intf->users_lock), flags);
++ write_lock(&(user->intf->cmd_rcvr_lock));
++ if ((user->intf->all_cmd_rcvr == NULL)
++ && (list_empty(&(user->intf->cmd_rcvrs))))
++ {
++ user->intf->all_cmd_rcvr = user;
++ rv = 0;
++ }
++ write_unlock(&(user->intf->cmd_rcvr_lock));
++ write_unlock_irqrestore(&(user->intf->users_lock), flags);
++ return rv;
++}
++
++int
++ipmi_unregister_all_cmd_rcvr(ipmi_user_t user)
++{
++ int flags;
++ int rv = -EINVAL;
++
++ write_lock_irqsave(&(user->intf->users_lock), flags);
++ write_lock(&(user->intf->cmd_rcvr_lock));
++ if (user->intf->all_cmd_rcvr == user)
++ {
++ user->intf->all_cmd_rcvr = NULL;
++ rv = 0;
++ }
++ write_unlock(&(user->intf->cmd_rcvr_lock));
++ write_unlock_irqrestore(&(user->intf->users_lock), flags);
++ return rv;
++}
++
++
++#define MAX_IPMI_INTERFACES 4
++static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES];
++
++/* Used to keep interfaces from going away while operations are
++ operating on interfaces. Grab read if you are not modifying the
++ interfaces, write if you are. */
++static DECLARE_RWSEM(interfaces_sem);
++
++/* Directly protects the ipmi_interfaces data structure. This is
++ claimed in the timer interrupt. */
++static spinlock_t interfaces_lock = SPIN_LOCK_UNLOCKED;
++
++/* List of watchers that want to know when smi's are added and
++ deleted. */
++static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers);
++static DECLARE_RWSEM(smi_watchers_sem);
++
++int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
++{
++ int i;
++
++ down_read(&interfaces_sem);
++ down_write(&smi_watchers_sem);
++ list_add(&(watcher->link), &smi_watchers);
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ if (ipmi_interfaces[i] != NULL) {
++ watcher->new_smi(i);
++ }
++ }
++ up_write(&smi_watchers_sem);
++ up_read(&interfaces_sem);
++ return 0;
++}
++
++int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher)
++{
++ down_write(&smi_watchers_sem);
++ list_del(&(watcher->link));
++ up_write(&smi_watchers_sem);
++ return 0;
++}
++
++int
++ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2)
++{
++ if (addr1->addr_type != addr2->addr_type)
++ return 0;
++
++ if (addr1->channel != addr2->channel)
++ return 0;
++
++ if (addr1->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {
++ struct ipmi_system_interface_addr *smi_addr1
++ = (struct ipmi_system_interface_addr *) addr1;
++ struct ipmi_system_interface_addr *smi_addr2
++ = (struct ipmi_system_interface_addr *) addr2;
++ return (smi_addr1->lun == smi_addr2->lun);
++ }
++
++ if ((addr1->addr_type == IPMI_IPMB_ADDR_TYPE)
++ || (addr1->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
++ {
++ struct ipmi_ipmb_addr *ipmb_addr1
++ = (struct ipmi_ipmb_addr *) addr1;
++ struct ipmi_ipmb_addr *ipmb_addr2
++ = (struct ipmi_ipmb_addr *) addr2;
++
++ return ((ipmb_addr1->slave_addr == ipmb_addr2->slave_addr)
++ && (ipmb_addr1->lun == ipmb_addr2->lun));
++ }
++
++ return 1;
++}
++
++int ipmi_validate_addr(struct ipmi_addr *addr, int len)
++{
++ if (len < sizeof(struct ipmi_system_interface_addr)) {
++ return -EINVAL;
++ }
++
++ if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {
++ if (addr->channel != IPMI_BMC_CHANNEL)
++ return -EINVAL;
++ return 0;
++ }
++
++ if ((addr->channel == IPMI_BMC_CHANNEL)
++ || (addr->channel >= IPMI_NUM_CHANNELS)
++ || (addr->channel < 0))
++ return -EINVAL;
++
++ if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)
++ || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
++ {
++ if (len < sizeof(struct ipmi_ipmb_addr)) {
++ return -EINVAL;
++ }
++ return 0;
++ }
++
++ return -EINVAL;
++}
++
++unsigned int ipmi_addr_length(int addr_type)
++{
++ if (addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
++ return sizeof(struct ipmi_system_interface_addr);
++
++ if ((addr_type == IPMI_IPMB_ADDR_TYPE)
++ || (addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
++ {
++ return sizeof(struct ipmi_ipmb_addr);
++ }
++
++ return 0;
++}
++
++static void deliver_response(struct ipmi_recv_msg *msg)
++{
++ msg->user->handler->ipmi_recv_hndl(msg, msg->user->handler_data);
++}
++
++/* Find the next sequence number not being used and add the given
++ message with the given timeout to the sequence table. This must be
++ called with the interface's seq_lock held. */
++static int intf_next_seq(ipmi_smi_t intf,
++ struct ipmi_recv_msg *recv_msg,
++ unsigned long timeout,
++ int retries,
++ unsigned char *seq,
++ long *seqid)
++{
++ int rv = 0;
++ unsigned int i;
++
++ for (i=intf->curr_seq;
++ i!=(intf->curr_seq-1);
++ i=(i+1)%IPMI_IPMB_NUM_SEQ)
++ {
++ if (! intf->seq_table[i].inuse)
++ break;
++ }
++
++ if (! intf->seq_table[i].inuse) {
++ intf->seq_table[i].recv_msg = recv_msg;
++
++ /* Start with the maximum timeout, when the send response
++ comes in we will start the real timer. */
++ intf->seq_table[i].timeout = MAX_MSG_TIMEOUT;
++ intf->seq_table[i].orig_timeout = timeout;
++ intf->seq_table[i].retries_left = retries;
++ intf->seq_table[i].inuse = 1;
++ intf->seq_table[i].seqid = NEXT_SEQID(intf->seq_table[i].seqid);
++ *seq = i;
++ *seqid = intf->seq_table[i].seqid;
++ intf->curr_seq = (i+1)%IPMI_IPMB_NUM_SEQ;
++ } else {
++ rv = -EAGAIN;
++ }
++
++ return rv;
++}
++
++/* Return the receive message for the given sequence number and
++ release the sequence number so it can be reused. Some other data
++ is passed in to be sure the message matches up correctly (to help
++ guard against message coming in after their timeout and the
++ sequence number being reused). */
++static int intf_find_seq(ipmi_smi_t intf,
++ unsigned char seq,
++ short channel,
++ unsigned char cmd,
++ unsigned char netfn,
++ struct ipmi_addr *addr,
++ struct ipmi_recv_msg **recv_msg)
++{
++ int rv = -ENODEV;
++ unsigned long flags;
++
++ if (seq >= IPMI_IPMB_NUM_SEQ)
++ return -EINVAL;
++
++ spin_lock_irqsave(&(intf->seq_lock), flags);
++ if (intf->seq_table[seq].inuse) {
++ struct ipmi_recv_msg *msg = intf->seq_table[seq].recv_msg;
++
++ if ((msg->addr.channel == channel)
++ && (msg->msg.cmd == cmd)
++ && (msg->msg.netfn == netfn)
++ && (ipmi_addr_equal(addr, &(msg->addr))))
++ {
++ *recv_msg = msg;
++ intf->seq_table[seq].inuse = 0;
++ rv = 0;
++ }
++ }
++ spin_unlock_irqrestore(&(intf->seq_lock), flags);
++
++ return rv;
++}
++
++
++/* Start the timer for a specific sequence table entry. */
++static int intf_start_seq_timer(ipmi_smi_t intf,
++ long msgid)
++{
++ int rv = -ENODEV;
++ unsigned long flags;
++ unsigned char seq;
++ unsigned long seqid;
++
++
++ GET_SEQ_FROM_MSGID(msgid, seq, seqid);
++
++ spin_lock_irqsave(&(intf->seq_lock), flags);
++ /* We do this verification because the user can be deleted
++ while a message is outstanding. */
++ if ((intf->seq_table[seq].inuse)
++ && (intf->seq_table[seq].seqid == seqid))
++ {
++ struct seq_table *ent = &(intf->seq_table[seq]);
++ ent->timeout = ent->orig_timeout;
++ }
++ spin_unlock_irqrestore(&(intf->seq_lock), flags);
++
++ return rv;
++}
++
++
++int ipmi_create_user(unsigned int if_num,
++ struct ipmi_user_hndl *handler,
++ void *handler_data,
++ ipmi_user_t *user)
++{
++ unsigned long flags;
++ ipmi_user_t new_user;
++ int rv = 0;
++
++ /* There is no module usecount here, because it's not
++ required. Since this can only be used by and called from
++ other modules, they will implicitly use this module, and
++ thus this can't be removed unless the other modules are
++ removed. */
++
++ if (handler == NULL)
++ return -EINVAL;
++
++ /* Make sure the driver is actually initialized, this handles
++ problems with initialization order. */
++ if (!initialized) {
++ rv = ipmi_init_msghandler();
++ if (rv)
++ return rv;
++
++ /* The init code doesn't return an error if it was turned
++ off, but it won't initialize. Check that. */
++ if (!initialized)
++ return -ENODEV;
++ }
++
++ new_user = kmalloc(sizeof(*new_user), GFP_KERNEL);
++ if (! new_user)
++ return -ENOMEM;
++
++ down_read(&interfaces_sem);
++ if ((if_num > MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)
++ {
++ rv = -EINVAL;
++ goto out_unlock;
++ }
++
++ new_user->handler = handler;
++ new_user->handler_data = handler_data;
++ new_user->intf = ipmi_interfaces[if_num];
++ new_user->gets_events = 0;
++
++ rv = new_user->intf->handlers->new_user(new_user->intf->send_info);
++ if (rv)
++ goto out_unlock;
++
++ write_lock_irqsave(&(new_user->intf->users_lock), flags);
++ list_add_tail(&(new_user->link), &(new_user->intf->users));
++ write_unlock_irqrestore(&(new_user->intf->users_lock), flags);
++
++ out_unlock:
++ if (rv) {
++ kfree(new_user);
++ } else {
++ *user = new_user;
++ }
++
++ up_read(&interfaces_sem);
++ return rv;
++}
++
++static int ipmi_destroy_user_nolock(ipmi_user_t user)
++{
++ int rv = -ENODEV;
++ ipmi_user_t t_user;
++ struct list_head *entry, *entry2;
++ int i;
++ unsigned long flags;
++
++ /* Find the user and delete them from the list. */
++ list_for_each(entry, &(user->intf->users)) {
++ t_user = list_entry(entry, struct ipmi_user, link);
++ if (t_user == user) {
++ list_del(entry);
++ rv = 0;
++ break;
++ }
++ }
++
++ if (rv) {
++ goto out_unlock;
++ }
++
++ /* Remove the user from the interfaces sequence table. */
++ spin_lock_irqsave(&(user->intf->seq_lock), flags);
++ for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) {
++ if (user->intf->seq_table[i].inuse
++ && (user->intf->seq_table[i].recv_msg->user == user))
++ {
++ user->intf->seq_table[i].inuse = 0;
++ }
++ }
++ spin_unlock_irqrestore(&(user->intf->seq_lock), flags);
++
++ /* Remove the user from the command receiver's table. */
++ write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
++ list_for_each_safe(entry, entry2, &(user->intf->cmd_rcvrs)) {
++ struct cmd_rcvr *rcvr;
++ rcvr = list_entry(entry, struct cmd_rcvr, link);
++ if (rcvr->user == user) {
++ list_del(entry);
++ kfree(rcvr);
++ }
++ }
++ write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
++
++ kfree(user);
++
++ out_unlock:
++
++ return rv;
++}
++
++int ipmi_destroy_user(ipmi_user_t user)
++{
++ int rv;
++ ipmi_smi_t intf = user->intf;
++ unsigned long flags;
++
++ down_read(&interfaces_sem);
++ write_lock_irqsave(&(intf->users_lock), flags);
++ rv = ipmi_destroy_user_nolock(user);
++ if (!rv)
++ intf->handlers->user_left(intf->send_info);
++
++ write_unlock_irqrestore(&(intf->users_lock), flags);
++ up_read(&interfaces_sem);
++ return rv;
++}
++
++void ipmi_get_version(ipmi_user_t user,
++ unsigned char *major,
++ unsigned char *minor)
++{
++ *major = user->intf->version_major;
++ *minor = user->intf->version_minor;
++}
++
++void ipmi_set_my_address(ipmi_user_t user,
++ unsigned char address)
++{
++ user->intf->my_address = address;
++}
++
++unsigned char ipmi_get_my_address(ipmi_user_t user)
++{
++ return user->intf->my_address;
++}
++
++void ipmi_set_my_LUN(ipmi_user_t user,
++ unsigned char LUN)
++{
++ user->intf->my_lun = LUN & 0x3;
++}
++
++unsigned char ipmi_get_my_LUN(ipmi_user_t user)
++{
++ return user->intf->my_lun;
++}
++
++int ipmi_set_gets_events(ipmi_user_t user, int val)
++{
++ unsigned long flags;
++ struct list_head *e, *e2;
++ struct ipmi_recv_msg *msg;
++
++ read_lock(&(user->intf->users_lock));
++ spin_lock_irqsave(&(user->intf->events_lock), flags);
++ user->gets_events = val;
++
++ if (val) {
++ /* Deliver any queued events. */
++ list_for_each_safe(e, e2, &(user->intf->waiting_events)) {
++ msg = list_entry(e, struct ipmi_recv_msg, link);
++ list_del(e);
++ msg->user = user;
++ deliver_response(msg);
++ }
++ }
++
++ spin_unlock_irqrestore(&(user->intf->events_lock), flags);
++ read_unlock(&(user->intf->users_lock));
++
++ return 0;
++}
++
++int ipmi_register_for_cmd(ipmi_user_t user,
++ unsigned char netfn,
++ unsigned char cmd)
++{
++ struct list_head *entry;
++ unsigned long flags;
++ struct cmd_rcvr *rcvr;
++ int rv = 0;
++
++
++ rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL);
++ if (! rcvr)
++ return -ENOMEM;
++
++ read_lock(&(user->intf->users_lock));
++ write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
++ if (user->intf->all_cmd_rcvr != NULL) {
++ rv = -EBUSY;
++ goto out_unlock;
++ }
++
++ /* Make sure the command/netfn is not already registered. */
++ list_for_each(entry, &(user->intf->cmd_rcvrs)) {
++ struct cmd_rcvr *cmp;
++ cmp = list_entry(entry, struct cmd_rcvr, link);
++ if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) {
++ rv = -EBUSY;
++ break;
++ }
++ }
++
++ if (! rv) {
++ rcvr->cmd = cmd;
++ rcvr->netfn = netfn;
++ rcvr->user = user;
++ list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs));
++ }
++ out_unlock:
++ write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
++ read_unlock(&(user->intf->users_lock));
++
++ if (rv)
++ kfree(rcvr);
++
++ return rv;
++}
++
++int ipmi_unregister_for_cmd(ipmi_user_t user,
++ unsigned char netfn,
++ unsigned char cmd)
++{
++ struct list_head *entry;
++ unsigned long flags;
++ struct cmd_rcvr *rcvr;
++ int rv = -ENOENT;
++
++ read_lock(&(user->intf->users_lock));
++ write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
++ /* Make sure the command/netfn is not already registered. */
++ list_for_each(entry, &(user->intf->cmd_rcvrs)) {
++ rcvr = list_entry(entry, struct cmd_rcvr, link);
++ if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
++ rv = 0;
++ list_del(entry);
++ kfree(rcvr);
++ break;
++ }
++ }
++ write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
++ read_unlock(&(user->intf->users_lock));
++
++ return rv;
++}
++
++static unsigned char
++ipmb_checksum(unsigned char *data, int size)
++{
++ unsigned char csum = 0;
++
++ for (; size > 0; size--, data++)
++ csum += *data;
++
++ return -csum;
++}
++
++static inline void format_ipmb_msg(struct ipmi_smi_msg *smi_msg,
++ struct ipmi_msg *msg,
++ struct ipmi_ipmb_addr *ipmb_addr,
++ long msgid,
++ unsigned char ipmb_seq,
++ int broadcast,
++ unsigned char source_address,
++ unsigned char source_lun)
++{
++ int i = broadcast;
++
++ /* Format the IPMB header data. */
++ smi_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ smi_msg->data[1] = IPMI_SEND_MSG_CMD;
++ smi_msg->data[2] = ipmb_addr->channel;
++ if (broadcast)
++ smi_msg->data[3] = 0;
++ smi_msg->data[i+3] = ipmb_addr->slave_addr;
++ smi_msg->data[i+4] = (msg->netfn << 2) | (ipmb_addr->lun & 0x3);
++ smi_msg->data[i+5] = ipmb_checksum(&(smi_msg->data[i+3]), 2);
++ smi_msg->data[i+6] = source_address;
++ smi_msg->data[i+7] = (ipmb_seq << 2) | source_lun;
++ smi_msg->data[i+8] = msg->cmd;
++
++ /* Now tack on the data to the message. */
++ if (msg->data_len > 0)
++ memcpy(&(smi_msg->data[i+9]), msg->data,
++ msg->data_len);
++ smi_msg->data_size = msg->data_len + 9;
++
++ /* Now calculate the checksum and tack it on. */
++ smi_msg->data[i+smi_msg->data_size]
++ = ipmb_checksum(&(smi_msg->data[i+6]),
++ smi_msg->data_size-6);
++
++ /* Add on the checksum size and the offset from the
++ broadcast. */
++ smi_msg->data_size += 1 + i;
++
++ smi_msg->msgid = msgid;
++}
++
++/* Separate from ipmi_request so that the user does not have to be
++ supplied in certain circumstances (mainly at panic time). If
++ messages are supplied, they will be freed, even if an error
++ occurs. */
++static inline int i_ipmi_request(ipmi_user_t user,
++ ipmi_smi_t intf,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ void *supplied_smi,
++ struct ipmi_recv_msg *supplied_recv,
++ int priority,
++ unsigned char source_address,
++ unsigned char source_lun)
++{
++ int rv = 0;
++ struct ipmi_smi_msg *smi_msg;
++ struct ipmi_recv_msg *recv_msg;
++ unsigned long flags;
++
++
++ if (supplied_recv) {
++ recv_msg = supplied_recv;
++ } else {
++ recv_msg = ipmi_alloc_recv_msg();
++ if (recv_msg == NULL) {
++ return -ENOMEM;
++ }
++ }
++
++ if (supplied_smi) {
++ smi_msg = (struct ipmi_smi_msg *) supplied_smi;
++ } else {
++ smi_msg = ipmi_alloc_smi_msg();
++ if (smi_msg == NULL) {
++ ipmi_free_recv_msg(recv_msg);
++ return -ENOMEM;
++ }
++ }
++
++ if (addr->channel > IPMI_NUM_CHANNELS) {
++ rv = -EINVAL;
++ goto out_err;
++ }
++
++ recv_msg->user = user;
++ recv_msg->msgid = msgid;
++ /* Store the message to send in the receive message so timeout
++ responses can get the proper response data. */
++ recv_msg->msg = *msg;
++
++ if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {
++ struct ipmi_system_interface_addr *smi_addr;
++
++
++ smi_addr = (struct ipmi_system_interface_addr *) addr;
++ if (smi_addr->lun > 3)
++ return -EINVAL;
++
++ memcpy(&recv_msg->addr, smi_addr, sizeof(*smi_addr));
++
++ if ((msg->netfn == IPMI_NETFN_APP_REQUEST)
++ && ((msg->cmd == IPMI_SEND_MSG_CMD)
++ || (msg->cmd == IPMI_GET_MSG_CMD)
++ || (msg->cmd == IPMI_READ_EVENT_MSG_BUFFER_CMD)))
++ {
++ /* We don't let the user do these, since we manage
++ the sequence numbers. */
++ rv = -EINVAL;
++ goto out_err;
++ }
++
++ if ((msg->data_len + 2) > IPMI_MAX_MSG_LENGTH) {
++ rv = -EMSGSIZE;
++ goto out_err;
++ }
++
++ smi_msg->data[0] = (msg->netfn << 2) | (smi_addr->lun & 0x3);
++ smi_msg->data[1] = msg->cmd;
++ smi_msg->msgid = msgid;
++ smi_msg->user_data = recv_msg;
++ if (msg->data_len > 0)
++ memcpy(&(smi_msg->data[2]), msg->data, msg->data_len);
++ smi_msg->data_size = msg->data_len + 2;
++ } else if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)
++ || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
++ {
++ struct ipmi_ipmb_addr *ipmb_addr;
++ unsigned char ipmb_seq;
++ long seqid;
++ int broadcast;
++ int retries;
++
++ if (addr == NULL) {
++ rv = -EINVAL;
++ goto out_err;
++ }
++
++ if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE) {
++ /* Broadcasts add a zero at the beginning of the
++ message, but otherwise is the same as an IPMB
++ address. */
++ addr->addr_type = IPMI_IPMB_ADDR_TYPE;
++ broadcast = 1;
++ retries = 0; /* Don't retry broadcasts. */
++ } else {
++ broadcast = 0;
++ retries = 4;
++ }
++
++ /* 9 for the header and 1 for the checksum, plus
++ possibly one for the broadcast. */
++ if ((msg->data_len + 10 + broadcast) > IPMI_MAX_MSG_LENGTH) {
++ rv = -EMSGSIZE;
++ goto out_err;
++ }
++
++ ipmb_addr = (struct ipmi_ipmb_addr *) addr;
++ if (ipmb_addr->lun > 3) {
++ rv = -EINVAL;
++ goto out_err;
++ }
++
++ memcpy(&recv_msg->addr, ipmb_addr, sizeof(*ipmb_addr));
++
++ if (recv_msg->msg.netfn & 0x1) {
++ /* It's a response, so use the user's sequence
++ from msgid. */
++ format_ipmb_msg(smi_msg, msg, ipmb_addr, msgid,
++ msgid, broadcast,
++ source_address, source_lun);
++ } else {
++ /* It's a command, so get a sequence for it. */
++
++ spin_lock_irqsave(&(intf->seq_lock), flags);
++
++ /* Create a sequence number with a 1 second
++ timeout and 4 retries. */
++ /* FIXME - magic number for the timeout. */
++ rv = intf_next_seq(intf,
++ recv_msg,
++ 1000,
++ retries,
++ &ipmb_seq,
++ &seqid);
++ if (rv) {
++ /* We have used up all the sequence numbers,
++ probably, so abort. */
++ spin_unlock_irqrestore(&(intf->seq_lock),
++ flags);
++ ipmi_free_recv_msg(recv_msg);
++ ipmi_free_smi_msg(smi_msg);
++ goto out_err;
++ }
++
++ /* Store the sequence number in the message,
++ so that when the send message response
++ comes back we can start the timer. */
++ format_ipmb_msg(smi_msg, msg, ipmb_addr,
++ STORE_SEQ_IN_MSGID(ipmb_seq, seqid),
++ ipmb_seq, broadcast,
++ source_address, source_lun);
++
++ /* Copy the message into the recv message data, so we
++ can retransmit it later if necessary. */
++ memcpy(recv_msg->msg_data, smi_msg->data,
++ smi_msg->data_size);
++ recv_msg->msg.data = recv_msg->msg_data;
++ recv_msg->msg.data_len = smi_msg->data_size;
++
++ /* We don't unlock until here, because we need
++ to copy the completed message into the
++ recv_msg before we release the lock.
++ Otherwise, race conditions may bite us. I
++ know that's pretty paranoid, but I prefer
++ to be correct. */
++ spin_unlock_irqrestore(&(intf->seq_lock), flags);
++ }
++ } else {
++ /* Unknown address type. */
++ rv = -EINVAL;
++ goto out_err;
++ }
++
++#if DEBUG_MSGING
++ {
++ int m;
++ for (m=0; m<smi_msg->data_size; m++)
++ printk(" %2.2x", smi_msg->data[m]);
++ printk("\n");
++ }
++#endif
++ intf->handlers->sender(intf->send_info, smi_msg, priority);
++
++ return 0;
++
++ out_err:
++ ipmi_free_smi_msg(smi_msg);
++ ipmi_free_recv_msg(recv_msg);
++ return rv;
++}
++
++int ipmi_request(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ int priority)
++{
++ return i_ipmi_request(user,
++ user->intf,
++ addr,
++ msgid,
++ msg,
++ NULL, NULL,
++ priority,
++ user->intf->my_address,
++ user->intf->my_lun);
++}
++
++int ipmi_request_supply_msgs(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ void *supplied_smi,
++ struct ipmi_recv_msg *supplied_recv,
++ int priority)
++{
++ return i_ipmi_request(user,
++ user->intf,
++ addr,
++ msgid,
++ msg,
++ supplied_smi,
++ supplied_recv,
++ priority,
++ user->intf->my_address,
++ user->intf->my_lun);
++}
++
++int ipmi_request_with_source(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ int priority,
++ unsigned char source_address,
++ unsigned char source_lun)
++{
++ return i_ipmi_request(user,
++ user->intf,
++ addr,
++ msgid,
++ msg,
++ NULL, NULL,
++ priority,
++ source_address,
++ source_lun);
++}
++
++int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
++ void *send_info,
++ unsigned char version_major,
++ unsigned char version_minor,
++ ipmi_smi_t *intf)
++{
++ int i, j;
++ int rv;
++ ipmi_smi_t new_intf;
++ struct list_head *entry;
++ unsigned int flags;
++
++
++ /* Make sure the driver is actually initialized, this handles
++ problems with initialization order. */
++ if (!initialized) {
++ rv = ipmi_init_msghandler();
++ if (rv)
++ return rv;
++ /* The init code doesn't return an error if it was turned
++ off, but it won't initialize. Check that. */
++ if (!initialized)
++ return -ENODEV;
++ }
++
++ new_intf = kmalloc(sizeof(*new_intf), GFP_KERNEL);
++ if (!new_intf)
++ return -ENOMEM;
++
++ rv = -ENOMEM;
++
++ down_write(&interfaces_sem);
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ if (ipmi_interfaces[i] == NULL) {
++ new_intf->version_major = version_major;
++ new_intf->version_minor = version_minor;
++ new_intf->my_address = IPMI_BMC_SLAVE_ADDR;
++ new_intf->my_lun = 2; /* the SMS LUN. */
++ rwlock_init(&(new_intf->users_lock));
++ INIT_LIST_HEAD(&(new_intf->users));
++ new_intf->handlers = handlers;
++ new_intf->send_info = send_info;
++ spin_lock_init(&(new_intf->seq_lock));
++ for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) {
++ new_intf->seq_table[j].inuse = 0;
++ new_intf->seq_table[j].seqid = 0;
++ }
++ new_intf->curr_seq = 0;
++ spin_lock_init(&(new_intf->waiting_msgs_lock));
++ INIT_LIST_HEAD(&(new_intf->waiting_msgs));
++ spin_lock_init(&(new_intf->events_lock));
++ INIT_LIST_HEAD(&(new_intf->waiting_events));
++ new_intf->waiting_events_count = 0;
++ rwlock_init(&(new_intf->cmd_rcvr_lock));
++ INIT_LIST_HEAD(&(new_intf->cmd_rcvrs));
++ new_intf->all_cmd_rcvr = NULL;
++
++ spin_lock_irqsave(&interfaces_lock, flags);
++ ipmi_interfaces[i] = new_intf;
++ spin_unlock_irqrestore(&interfaces_lock, flags);
++
++ rv = 0;
++ *intf = new_intf;
++ break;
++ }
++ }
++
++ /* We convert to a read semaphore here. It's possible the
++ interface was removed between the calls, we have to recheck
++ afterwards. */
++ up_write(&interfaces_sem);
++ down_read(&interfaces_sem);
++
++ if (ipmi_interfaces[i] != new_intf)
++ /* Well, it went away. Just return. */
++ goto out;
++
++ if (rv == 0) {
++ /* Call all the watcher interfaces to tell them that a
++ new interface is available. */
++ down_read(&smi_watchers_sem);
++ list_for_each(entry, &smi_watchers) {
++ struct ipmi_smi_watcher *w;
++ w = list_entry(entry, struct ipmi_smi_watcher, link);
++ w->new_smi(i);
++ }
++ up_read(&smi_watchers_sem);
++ }
++
++ out:
++ up_read(&interfaces_sem);
++
++ if (rv)
++ kfree(new_intf);
++
++ return rv;
++}
++
++static void free_recv_msg_list(struct list_head *q)
++{
++ struct list_head *entry, *entry2;
++ struct ipmi_recv_msg *msg;
++
++ list_for_each_safe(entry, entry2, q) {
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ list_del(entry);
++ ipmi_free_recv_msg(msg);
++ }
++}
++
++static void free_cmd_rcvr_list(struct list_head *q)
++{
++ struct list_head *entry, *entry2;
++ struct cmd_rcvr *rcvr;
++
++ list_for_each_safe(entry, entry2, q) {
++ rcvr = list_entry(entry, struct cmd_rcvr, link);
++ list_del(entry);
++ kfree(rcvr);
++ }
++}
++
++static void clean_up_interface_data(ipmi_smi_t intf)
++{
++ int i;
++
++ free_recv_msg_list(&(intf->waiting_msgs));
++ free_recv_msg_list(&(intf->waiting_events));
++ free_cmd_rcvr_list(&(intf->cmd_rcvrs));
++
++ for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) {
++ if ((intf->seq_table[i].inuse)
++ && (intf->seq_table[i].recv_msg))
++ {
++ ipmi_free_recv_msg(intf->seq_table[i].recv_msg);
++ }
++ }
++}
++
++int ipmi_unregister_smi(ipmi_smi_t intf)
++{
++ int rv = -ENODEV;
++ int i;
++ struct list_head *entry;
++ unsigned int flags;
++
++ down_write(&interfaces_sem);
++ if (list_empty(&(intf->users)))
++ {
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ if (ipmi_interfaces[i] == intf) {
++ spin_lock_irqsave(&interfaces_lock, flags);
++ ipmi_interfaces[i] = NULL;
++ clean_up_interface_data(intf);
++ spin_unlock_irqrestore(&interfaces_lock,flags);
++ kfree(intf);
++ rv = 0;
++ goto out_call_watcher;
++ }
++ }
++ } else {
++ rv = -EBUSY;
++ }
++ up_write(&interfaces_sem);
++
++ return rv;
++
++ out_call_watcher:
++ /* Convert to a read semaphore so callbacks don't bite us. */
++ up_write(&interfaces_sem);
++ down_read(&interfaces_sem);
++
++ /* Call all the watcher interfaces to tell them that
++ an interface is gone. */
++ down_read(&smi_watchers_sem);
++ list_for_each(entry, &smi_watchers) {
++ struct ipmi_smi_watcher *w;
++ w = list_entry(entry,
++ struct ipmi_smi_watcher,
++ link);
++ w->smi_gone(i);
++ }
++ up_read(&smi_watchers_sem);
++ up_read(&interfaces_sem);
++ return 0;
++}
++
++static int handle_get_msg_rsp(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ struct ipmi_ipmb_addr ipmb_addr;
++ struct ipmi_recv_msg *recv_msg;
++
++
++ if (msg->rsp_size < 11)
++ /* Message not big enough, just ignore it. */
++ return 0;
++
++ if (msg->rsp[2] != 0)
++ /* An error getting the response, just ignore it. */
++ return 0;
++
++ ipmb_addr.addr_type = IPMI_IPMB_ADDR_TYPE;
++ ipmb_addr.slave_addr = msg->rsp[6];
++ ipmb_addr.channel = msg->rsp[3] & 0x0f;
++ ipmb_addr.lun = msg->rsp[7] & 3;
++
++ /* It's a response from a remote entity. Look up the sequence
++ number and handle the response. */
++ if (intf_find_seq(intf,
++ msg->rsp[7] >> 2,
++ msg->rsp[3] & 0x0f,
++ msg->rsp[8],
++ (msg->rsp[4] >> 2) & (~1),
++ (struct ipmi_addr *) &(ipmb_addr),
++ &recv_msg))
++ {
++ /* We were unable to find the sequence number,
++ so just nuke the message. */
++ return 0;
++ }
++
++ memcpy(recv_msg->msg_data,
++ &(msg->rsp[9]),
++ msg->rsp_size - 9);
++ /* THe other fields matched, so no need to set them, except
++ for netfn, which needs to be the response that was
++ returned, not the request value. */
++ recv_msg->msg.netfn = msg->rsp[4] >> 2;
++ recv_msg->msg.data = recv_msg->msg_data;
++ recv_msg->msg.data_len = msg->rsp_size - 10;
++ recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
++ deliver_response(recv_msg);
++
++ return 0;
++}
++
++static int handle_get_msg_cmd(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ struct list_head *entry;
++ struct cmd_rcvr *rcvr;
++ int rv = 0;
++ unsigned char netfn;
++ unsigned char cmd;
++ ipmi_user_t user = NULL;
++ struct ipmi_ipmb_addr *ipmb_addr;
++ struct ipmi_recv_msg *recv_msg;
++
++ if (msg->rsp_size < 10)
++ /* Message not big enough, just ignore it. */
++ return 0;
++
++ if (msg->rsp[2] != 0) {
++ /* An error getting the response, just ignore it. */
++ return 0;
++ }
++
++ netfn = msg->rsp[4] >> 2;
++ cmd = msg->rsp[8];
++
++ read_lock(&(intf->cmd_rcvr_lock));
++
++ if (intf->all_cmd_rcvr) {
++ user = intf->all_cmd_rcvr;
++ } else {
++ /* Find the command/netfn. */
++ list_for_each(entry, &(intf->cmd_rcvrs)) {
++ rcvr = list_entry(entry, struct cmd_rcvr, link);
++ if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
++ user = rcvr->user;
++ break;
++ }
++ }
++ }
++ read_unlock(&(intf->cmd_rcvr_lock));
++
++ if (user == NULL) {
++ /* We didn't find a user, deliver an error response. */
++ msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
++ msg->data[1] = IPMI_SEND_MSG_CMD;
++ msg->data[2] = msg->rsp[3];
++ msg->data[3] = msg->rsp[6];
++ msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3);
++ msg->data[5] = ipmb_checksum(&(msg->data[3]), 2);
++ msg->data[6] = intf->my_address;
++ /* rqseq/lun */
++ msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3);
++ msg->data[8] = msg->rsp[8]; /* cmd */
++ msg->data[9] = IPMI_INVALID_CMD_COMPLETION_CODE;
++ msg->data[10] = ipmb_checksum(&(msg->data[6]), 4);
++ msg->data_size = 11;
++
++ intf->handlers->sender(intf->send_info, msg, 0);
++
++ rv = -1; /* We used the message, so return the value that
++ causes it to not be freed or queued. */
++ } else {
++ /* Deliver the message to the user. */
++ recv_msg = ipmi_alloc_recv_msg();
++ if (! recv_msg) {
++ /* We couldn't allocate memory for the
++ message, so requeue it for handling
++ later. */
++ rv = 1;
++ } else {
++ ipmb_addr = (struct ipmi_ipmb_addr *) &recv_msg->addr;
++ ipmb_addr->addr_type = IPMI_IPMB_ADDR_TYPE;
++ ipmb_addr->slave_addr = msg->rsp[6];
++ ipmb_addr->lun = msg->rsp[7] & 3;
++ ipmb_addr->channel = msg->rsp[3];
++
++ recv_msg->user = user;
++ recv_msg->recv_type = IPMI_CMD_RECV_TYPE;
++ recv_msg->msgid = msg->rsp[7] >> 2;
++ recv_msg->msg.netfn = msg->rsp[4] >> 2;
++ recv_msg->msg.cmd = msg->rsp[8];
++ recv_msg->msg.data = recv_msg->msg_data;
++ recv_msg->msg.data_len = msg->rsp_size - 10;
++ memcpy(recv_msg->msg_data,
++ &(msg->rsp[9]),
++ msg->rsp_size - 10);
++ deliver_response(recv_msg);
++ }
++ }
++
++ return rv;
++}
++
++static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg,
++ struct ipmi_smi_msg *msg)
++{
++ struct ipmi_system_interface_addr *smi_addr;
++
++ recv_msg->msgid = 0;
++ smi_addr = (struct ipmi_system_interface_addr *) &(recv_msg->addr);
++ smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr->channel = IPMI_BMC_CHANNEL;
++ smi_addr->lun = msg->rsp[0] & 3;
++ recv_msg->recv_type = IPMI_ASYNC_EVENT_RECV_TYPE;
++ recv_msg->msg.netfn = msg->rsp[0] >> 2;
++ recv_msg->msg.cmd = msg->rsp[1];
++ memcpy(recv_msg->msg_data, &(msg->rsp[3]), msg->rsp_size - 3);
++ recv_msg->msg.data = recv_msg->msg_data;
++ recv_msg->msg.data_len = msg->rsp_size - 3;
++}
++
++/* This will be called with the intf->users_lock read-locked, so no need
++ to do that here. */
++static int handle_read_event_rsp(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ struct ipmi_recv_msg *recv_msg;
++ struct list_head msgs;
++ struct list_head *entry, *entry2;
++ ipmi_user_t user;
++ int rv = 0;
++ int deliver_count = 0;
++ unsigned long flags;
++
++ if (msg->rsp_size < 19) {
++ /* Message is too small to be an IPMB event. */
++ return 0;
++ }
++
++ if (msg->rsp[2] != 0) {
++ /* An error getting the event, just ignore it. */
++ return 0;
++ }
++
++ INIT_LIST_HEAD(&msgs);
++
++ spin_lock_irqsave(&(intf->events_lock), flags);
++
++ /* Allocate and fill in one message for every user that is getting
++ events. */
++ list_for_each(entry, &(intf->users)) {
++ user = list_entry(entry, struct ipmi_user, link);
++
++ if (! user->gets_events)
++ continue;
++
++ recv_msg = ipmi_alloc_recv_msg();
++ if (! recv_msg) {
++ list_for_each_safe(entry, entry2, &msgs) {
++ recv_msg = list_entry(entry,
++ struct ipmi_recv_msg,
++ link);
++ list_del(entry);
++ ipmi_free_recv_msg(recv_msg);
++ }
++ /* We couldn't allocate memory for the
++ message, so requeue it for handling
++ later. */
++ rv = 1;
++ goto out;
++ }
++
++ deliver_count++;
++
++ copy_event_into_recv_msg(recv_msg, msg);
++ recv_msg->user = user;
++ list_add_tail(&(recv_msg->link), &msgs);
++ }
++
++ if (deliver_count) {
++ /* Now deliver all the messages. */
++ list_for_each_safe(entry, entry2, &msgs) {
++ recv_msg = list_entry(entry,
++ struct ipmi_recv_msg,
++ link);
++ list_del(entry);
++ deliver_response(recv_msg);
++ }
++ } else if (intf->waiting_events_count < MAX_EVENTS_IN_QUEUE) {
++ /* No one to receive the message, put it in queue if there's
++ not already too many things in the queue. */
++ recv_msg = ipmi_alloc_recv_msg();
++ if (! recv_msg) {
++ /* We couldn't allocate memory for the
++ message, so requeue it for handling
++ later. */
++ rv = 1;
++ goto out;
++ }
++
++ copy_event_into_recv_msg(recv_msg, msg);
++ list_add_tail(&(recv_msg->link), &(intf->waiting_events));
++ } else {
++ /* There's too many things in the queue, discard this
++ message. */
++ printk(KERN_WARNING "ipmi: Event queue full, discarding an"
++ " incoming event\n");
++ }
++
++ out:
++ spin_unlock_irqrestore(&(intf->events_lock), flags);
++
++ return rv;
++}
++
++static int handle_bmc_rsp(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ struct ipmi_recv_msg *recv_msg;
++ int found = 0;
++ struct list_head *entry;
++
++ recv_msg = (struct ipmi_recv_msg *) msg->user_data;
++
++ /* Make sure the user still exists. */
++ list_for_each(entry, &(intf->users)) {
++ if (list_entry(entry, struct ipmi_user, link)
++ == recv_msg->user)
++ {
++ /* Found it, so we can deliver it */
++ found = 1;
++ break;
++ }
++ }
++
++ if (!found) {
++ /* The user for the message went away, so give up. */
++ ipmi_free_recv_msg(recv_msg);
++ } else {
++ struct ipmi_system_interface_addr *smi_addr;
++
++ recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
++ recv_msg->msgid = msg->msgid;
++ smi_addr = ((struct ipmi_system_interface_addr *)
++ &(recv_msg->addr));
++ smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ smi_addr->channel = IPMI_BMC_CHANNEL;
++ smi_addr->lun = msg->rsp[0] & 3;
++ recv_msg->msg.netfn = msg->rsp[0] >> 2;
++ recv_msg->msg.cmd = msg->rsp[1];
++ memcpy(recv_msg->msg_data,
++ &(msg->rsp[2]),
++ msg->rsp_size - 2);
++ recv_msg->msg.data = recv_msg->msg_data;
++ recv_msg->msg.data_len = msg->rsp_size - 2;
++ deliver_response(recv_msg);
++ }
++
++ return 0;
++}
++
++/* Handle a new message. Return 1 if the message should be requeued,
++ 0 if the message should be freed, or -1 if the message should not
++ be freed or requeued. */
++static int handle_new_recv_msg(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ int requeue;
++
++ if (msg->rsp_size < 2) {
++ /* Message is too small to be correct. */
++ requeue = 0;
++ } else if (msg->rsp[1] == IPMI_GET_MSG_CMD) {
++#if DEBUG_MSGING
++ int m;
++ printk("Response:");
++ for (m=0; m<msg->rsp_size; m++)
++ printk(" %2.2x", msg->rsp[m]);
++ printk("\n");
++#endif
++ /* It's from the receive queue. */
++ if (msg->rsp[4] & 0x04) {
++ /* It's a response, so find the
++ requesting message and send it up. */
++ requeue = handle_get_msg_rsp(intf, msg);
++ } else {
++ /* It's a command to the SMS from some other
++ entity. Handle that. */
++ requeue = handle_get_msg_cmd(intf, msg);
++ }
++ } else if (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD) {
++ /* It's an asyncronous event. */
++ requeue = handle_read_event_rsp(intf, msg);
++ } else {
++ /* It's a response from the local BMC. */
++ requeue = handle_bmc_rsp(intf, msg);
++ }
++
++ return requeue;
++}
++
++/* Handle a new message from the lower layer. */
++void ipmi_smi_msg_received(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg)
++{
++ unsigned long flags;
++ int rv;
++
++
++ /* Lock the user lock so the user can't go away while we are
++ working on it. */
++ read_lock(&(intf->users_lock));
++
++ if ((msg->data_size >= 2) && (msg->data[1] == IPMI_SEND_MSG_CMD)) {
++ /* This is the local response to a send, start the
++ timer for these. */
++ intf_start_seq_timer(intf, msg->msgid);
++ ipmi_free_smi_msg(msg);
++ goto out_unlock;
++ }
++
++ /* To preserve message order, if the list is not empty, we
++ tack this message onto the end of the list. */
++ spin_lock_irqsave(&(intf->waiting_msgs_lock), flags);
++ if (!list_empty(&(intf->waiting_msgs))) {
++ list_add_tail(&(msg->link), &(intf->waiting_msgs));
++ spin_unlock(&(intf->waiting_msgs_lock));
++ goto out_unlock;
++ }
++ spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
++
++ rv = handle_new_recv_msg(intf, msg);
++ if (rv > 0) {
++ /* Could not handle the message now, just add it to a
++ list to handle later. */
++ spin_lock(&(intf->waiting_msgs_lock));
++ list_add_tail(&(msg->link), &(intf->waiting_msgs));
++ spin_unlock(&(intf->waiting_msgs_lock));
++ } else if (rv == 0) {
++ ipmi_free_smi_msg(msg);
++ }
++
++ out_unlock:
++ read_unlock(&(intf->users_lock));
++}
++
++void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf)
++{
++ struct list_head *entry;
++ ipmi_user_t user;
++
++ read_lock(&(intf->users_lock));
++ list_for_each(entry, &(intf->users)) {
++ user = list_entry(entry, struct ipmi_user, link);
++
++ if (! user->handler->ipmi_watchdog_pretimeout)
++ continue;
++
++ user->handler->ipmi_watchdog_pretimeout(user->handler_data);
++ }
++ read_unlock(&(intf->users_lock));
++}
++
++static void
++handle_msg_timeout(struct ipmi_recv_msg *msg)
++{
++ msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
++ msg->msg_data[0] = IPMI_TIMEOUT_COMPLETION_CODE;
++ msg->msg.netfn |= 1; /* Convert to a response. */
++ msg->msg.data_len = 1;
++ msg->msg.data = msg->msg_data;
++ deliver_response(msg);
++}
++
++static void
++send_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
++ struct ipmi_smi_msg *smi_msg,
++ unsigned char seq, long seqid)
++{
++ if (!smi_msg)
++ smi_msg = ipmi_alloc_smi_msg();
++ if (!smi_msg)
++ /* If we can't allocate the message, then just return, we
++ get 4 retries, so this should be ok. */
++ return;
++
++ memcpy(smi_msg->data, recv_msg->msg.data, recv_msg->msg.data_len);
++ smi_msg->data_size = recv_msg->msg.data_len;
++ smi_msg->msgid = STORE_SEQ_IN_MSGID(seq, seqid);
++
++ /* Send the new message. We send with a zero priority. It
++ timed out, I doubt time is that critical now, and high
++ priority messages are really only for messages to the local
++ MC, which don't get resent. */
++ intf->handlers->sender(intf->send_info, smi_msg, 0);
++
++#if DEBUG_MSGING
++ {
++ int m;
++ printk("Resend: ");
++ for (m=0; m<smi_msg->data_size; m++)
++ printk(" %2.2x", smi_msg->data[m]);
++ printk("\n");
++ }
++#endif
++}
++
++static void
++ipmi_timeout_handler(long timeout_period)
++{
++ ipmi_smi_t intf;
++ struct list_head timeouts;
++ struct ipmi_recv_msg *msg;
++ struct ipmi_smi_msg *smi_msg;
++ unsigned long flags;
++ struct list_head *entry, *entry2;
++ int i, j;
++
++ INIT_LIST_HEAD(&timeouts);
++
++ spin_lock(&interfaces_lock);
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ intf = ipmi_interfaces[i];
++ if (intf == NULL)
++ continue;
++
++ read_lock(&(intf->users_lock));
++
++ /* See if any waiting messages need to be processed. */
++ spin_lock_irqsave(&(intf->waiting_msgs_lock), flags);
++ list_for_each_safe(entry, entry2, &(intf->waiting_msgs)) {
++ smi_msg = list_entry(entry, struct ipmi_smi_msg, link);
++ if (! handle_new_recv_msg(intf, smi_msg)) {
++ list_del(entry);
++ ipmi_free_smi_msg(smi_msg);
++ } else {
++ /* To preserve message order, quit if we
++ can't handle a message. */
++ break;
++ }
++ }
++ spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
++
++ /* Go through the seq table and find any messages that
++ have timed out, putting them in the timeouts
++ list. */
++ spin_lock_irqsave(&(intf->seq_lock), flags);
++ for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) {
++ struct seq_table *ent = &(intf->seq_table[j]);
++ if (!ent->inuse)
++ continue;
++
++ ent->timeout -= timeout_period;
++ if (ent->timeout > 0)
++ continue;
++
++ if (ent->retries_left == 0) {
++ /* The message has used all its retries. */
++ ent->inuse = 0;
++ msg = ent->recv_msg;
++ list_add_tail(&(msg->link), &timeouts);
++ } else {
++ /* More retries, send again. */
++
++ /* Start with the max timer, set to normal
++ timer after the message is sent. */
++ ent->timeout = MAX_MSG_TIMEOUT;
++ ent->retries_left--;
++ send_from_recv_msg(intf, ent->recv_msg, NULL,
++ j, ent->seqid);
++ }
++ }
++ spin_unlock_irqrestore(&(intf->seq_lock), flags);
++
++ list_for_each_safe(entry, entry2, &timeouts) {
++ msg = list_entry(entry, struct ipmi_recv_msg, link);
++ handle_msg_timeout(msg);
++ }
++
++ read_unlock(&(intf->users_lock));
++ }
++ spin_unlock(&interfaces_lock);
++}
++
++static void ipmi_request_event(void)
++{
++ ipmi_smi_t intf;
++ int i;
++
++ spin_lock(&interfaces_lock);
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ intf = ipmi_interfaces[i];
++ if (intf == NULL)
++ continue;
++
++ intf->handlers->request_events(intf->send_info);
++ }
++ spin_unlock(&interfaces_lock);
++}
++
++static struct timer_list ipmi_timer;
++
++/* Call every 100 ms. */
++#define IPMI_TIMEOUT_TIME 100
++#define IPMI_TIMEOUT_JIFFIES (IPMI_TIMEOUT_TIME/(1000/HZ))
++
++/* Request events from the queue every second. Hopefully, in the
++ future, IPMI will add a way to know immediately if an event is
++ in the queue. */
++#define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME))
++
++static volatile int stop_operation = 0;
++static volatile int timer_stopped = 0;
++static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
++
++static void ipmi_timeout(unsigned long data)
++{
++ if (stop_operation) {
++ timer_stopped = 1;
++ return;
++ }
++
++ ticks_to_req_ev--;
++ if (ticks_to_req_ev == 0) {
++ ipmi_request_event();
++ ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
++ }
++
++ ipmi_timeout_handler(IPMI_TIMEOUT_TIME);
++
++ ipmi_timer.expires += IPMI_TIMEOUT_JIFFIES;
++ add_timer(&ipmi_timer);
++}
++
++
++/* FIXME - convert these to slabs. */
++static void free_smi_msg(struct ipmi_smi_msg *msg)
++{
++ kfree(msg);
++}
++
++struct ipmi_smi_msg *ipmi_alloc_smi_msg(void)
++{
++ struct ipmi_smi_msg *rv;
++ rv = kmalloc(sizeof(struct ipmi_smi_msg), GFP_ATOMIC);
++ if (rv)
++ rv->done = free_smi_msg;
++ return rv;
++}
++
++static void free_recv_msg(struct ipmi_recv_msg *msg)
++{
++ kfree(msg);
++}
++
++struct ipmi_recv_msg *ipmi_alloc_recv_msg(void)
++{
++ struct ipmi_recv_msg *rv;
++
++ rv = kmalloc(sizeof(struct ipmi_recv_msg), GFP_ATOMIC);
++ if (rv)
++ rv->done = free_recv_msg;
++ return rv;
++}
++
++#ifdef CONFIG_IPMI_PANIC_EVENT
++
++static void dummy_smi_done_handler(struct ipmi_smi_msg *msg)
++{
++}
++
++static void dummy_recv_done_handler(struct ipmi_recv_msg *msg)
++{
++}
++
++static void send_panic_events(void)
++{
++ struct ipmi_msg msg;
++ ipmi_smi_t intf;
++ unsigned char data[8];
++ int i;
++ struct ipmi_system_interface_addr addr;
++ struct ipmi_smi_msg smi_msg;
++ struct ipmi_recv_msg recv_msg;
++
++ addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ addr.channel = IPMI_BMC_CHANNEL;
++
++ /* Fill in an event telling that we have failed. */
++ msg.netfn = 0x04; /* Sensor or Event. */
++ msg.cmd = 2; /* Platform event command. */
++ msg.data = data;
++ msg.data_len = 8;
++ data[0] = 0x21; /* Kernel generator ID, IPMI table 5-4 */
++ data[1] = 0x03; /* This is for IPMI 1.0. */
++ data[2] = 0x20; /* OS Critical Stop, IPMI table 36-3 */
++ data[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
++ data[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
++
++ /* These used to have the first three bytes of the panic string,
++ but not only is that not terribly useful, it's not available
++ any more. */
++ data[3] = 0;
++ data[6] = 0;
++ data[7] = 0;
++
++ smi_msg.done = dummy_smi_done_handler;
++ recv_msg.done = dummy_recv_done_handler;
++
++ /* For every registered interface, send the event. */
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ intf = ipmi_interfaces[i];
++ if (intf == NULL)
++ continue;
++
++ intf->handlers->set_run_to_completion(intf->send_info, 1);
++ i_ipmi_request(NULL,
++ intf,
++ (struct ipmi_addr *) &addr,
++ 0,
++ &msg,
++ &smi_msg,
++ &recv_msg,
++ 0,
++ intf->my_address,
++ intf->my_lun);
++ }
++}
++#endif /* CONFIG_IPMI_PANIC_EVENT */
++
++static int has_paniced = 0;
++
++static int panic_event(struct notifier_block *this,
++ unsigned long event,
++ void *ptr)
++{
++ int i;
++ ipmi_smi_t intf;
++
++ if (has_paniced)
++ return NOTIFY_DONE;
++ has_paniced = 1;
++
++ /* For every registered interface, set it to run to completion. */
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ intf = ipmi_interfaces[i];
++ if (intf == NULL)
++ continue;
++
++ intf->handlers->set_run_to_completion(intf->send_info, 1);
++ }
++
++#ifdef CONFIG_IPMI_PANIC_EVENT
++ send_panic_events();
++#endif
++
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block panic_block = {
++ panic_event,
++ NULL,
++ 200 /* priority: INT_MAX >= x >= 0 */
++};
++
++
++static __init int ipmi_init_msghandler(void)
++{
++ int i;
++
++ if (initialized)
++ return 0;
++
++ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
++ ipmi_interfaces[i] = NULL;
++ }
++
++ init_timer(&ipmi_timer);
++ ipmi_timer.data = 0;
++ ipmi_timer.function = ipmi_timeout;
++ ipmi_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES;
++ add_timer(&ipmi_timer);
++
++ notifier_chain_register(&panic_notifier_list, &panic_block);
++
++ initialized = 1;
++
++ printk(KERN_INFO "ipmi: message handler initialized\n");
++
++ return 0;
++}
++
++static __exit void cleanup_ipmi(void)
++{
++ if (!initialized)
++ return;
++
++ notifier_chain_unregister(&panic_notifier_list, &panic_block);
++
++ /* This can't be called if any interfaces exist, so no worry about
++ shutting down the interfaces. */
++
++ /* Tell the timer to stop, then wait for it to stop. This avoids
++ problems with race conditions removing the timer here. */
++ stop_operation = 1;
++ while (!timer_stopped) {
++ schedule_timeout(1);
++ }
++
++ initialized = 0;
++}
++module_exit(cleanup_ipmi);
++
++module_init(ipmi_init_msghandler);
++MODULE_LICENSE("GPL");
++
++EXPORT_SYMBOL(ipmi_alloc_recv_msg);
++EXPORT_SYMBOL(ipmi_create_user);
++EXPORT_SYMBOL(ipmi_destroy_user);
++EXPORT_SYMBOL(ipmi_get_version);
++EXPORT_SYMBOL(ipmi_request);
++EXPORT_SYMBOL(ipmi_request_supply_msgs);
++EXPORT_SYMBOL(ipmi_request_with_source);
++EXPORT_SYMBOL(ipmi_register_smi);
++EXPORT_SYMBOL(ipmi_unregister_smi);
++EXPORT_SYMBOL(ipmi_register_for_cmd);
++EXPORT_SYMBOL(ipmi_unregister_for_cmd);
++EXPORT_SYMBOL(ipmi_smi_msg_received);
++EXPORT_SYMBOL(ipmi_smi_watchdog_pretimeout);
++EXPORT_SYMBOL(ipmi_alloc_smi_msg);
++EXPORT_SYMBOL(ipmi_register_all_cmd_rcvr);
++EXPORT_SYMBOL(ipmi_unregister_all_cmd_rcvr);
++EXPORT_SYMBOL(ipmi_addr_length);
++EXPORT_SYMBOL(ipmi_validate_addr);
++EXPORT_SYMBOL(ipmi_set_gets_events);
++EXPORT_SYMBOL(ipmi_addr_equal);
++EXPORT_SYMBOL(ipmi_smi_watcher_register);
++EXPORT_SYMBOL(ipmi_smi_watcher_unregister);
++EXPORT_SYMBOL(ipmi_set_my_address);
++EXPORT_SYMBOL(ipmi_get_my_address);
++EXPORT_SYMBOL(ipmi_set_my_LUN);
++EXPORT_SYMBOL(ipmi_get_my_LUN);
+--- /dev/null 2002-08-30 19:31:37.000000000 -0400
++++ linux-2.4.18-14/drivers/char/ipmi/ipmi_watchdog.c 2003-03-27 15:26:22.000000000 -0500
+@@ -0,0 +1,1113 @@
++/*
++ * ipmi_watchdog.c
++ *
++ * A watchdog timer based upon the IPMI interface.
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/ipmi.h>
++#include <linux/ipmi_smi.h>
++#include <linux/watchdog.h>
++#include <linux/miscdevice.h>
++#include <linux/init.h>
++#include <linux/rwsem.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <linux/notifier.h>
++#include <linux/nmi.h>
++#include <linux/reboot.h>
++#include <linux/wait.h>
++#include <linux/poll.h>
++#ifdef CONFIG_X86_LOCAL_APIC
++#include <asm/apic.h>
++#endif
++
++/*
++ * The IPMI command/response information for the watchdog timer.
++ */
++
++/* values for byte 1 of the set command, byte 2 of the get response. */
++#define WDOG_DONT_LOG (1 << 7)
++#define WDOG_DONT_STOP_ON_SET (1 << 6)
++#define WDOG_SET_TIMER_USE(byte, use) \
++ byte = ((byte) & 0xf8) | ((use) & 0x7)
++#define WDOG_GET_TIMER_USE(byte) ((byte) & 0x7)
++#define WDOG_TIMER_USE_BIOS_FRB2 1
++#define WDOG_TIMER_USE_BIOS_POST 2
++#define WDOG_TIMER_USE_OS_LOAD 3
++#define WDOG_TIMER_USE_SMS_OS 4
++#define WDOG_TIMER_USE_OEM 5
++
++/* values for byte 2 of the set command, byte 3 of the get response. */
++#define WDOG_SET_PRETIMEOUT_ACT(byte, use) \
++ byte = ((byte) & 0x8f) | (((use) & 0x7) << 4)
++#define WDOG_GET_PRETIMEOUT_ACT(byte) (((byte) >> 4) & 0x7)
++#define WDOG_PRETIMEOUT_NONE 0
++#define WDOG_PRETIMEOUT_SMI 1
++#define WDOG_PRETIMEOUT_NMI 2
++#define WDOG_PRETIMEOUT_MSG_INT 3
++
++/* Operations that can be performed on a pretimout. */
++#define WDOG_PREOP_NONE 0
++#define WDOG_PREOP_PANIC 1
++#define WDOG_PREOP_GIVE_DATA 2 /* Cause data to be available to
++ read. Doesn't work in NMI
++ mode. */
++
++/* Actions to perform on a full timeout. */
++#define WDOG_SET_TIMEOUT_ACT(byte, use) \
++ byte = ((byte) & 0xf8) | ((use) & 0x7)
++#define WDOG_GET_TIMEOUT_ACT(byte) ((byte) & 0x7)
++#define WDOG_TIMEOUT_NONE 0
++#define WDOG_TIMEOUT_RESET 1
++#define WDOG_TIMEOUT_POWER_DOWN 2
++#define WDOG_TIMEOUT_POWER_CYCLE 3
++
++/* Byte 3 of the get command, byte 4 of the get response is the
++ pre-timeout in seconds. */
++
++/* Bits for setting byte 4 of the set command, byte 5 of the get response. */
++#define WDOG_EXPIRE_CLEAR_BIOS_FRB2 (1 << 1)
++#define WDOG_EXPIRE_CLEAR_BIOS_POST (1 << 2)
++#define WDOG_EXPIRE_CLEAR_OS_LOAD (1 << 3)
++#define WDOG_EXPIRE_CLEAR_SMS_OS (1 << 4)
++#define WDOG_EXPIRE_CLEAR_OEM (1 << 5)
++
++/* Setting/getting the watchdog timer value. This is for bytes 5 and
++ 6 (the timeout time) of the set command, and bytes 6 and 7 (the
++ timeout time) and 8 and 9 (the current countdown value) of the
++ response. The timeout value is given in seconds (in the command it
++ is 100ms intervals). */
++#define WDOG_SET_TIMEOUT(byte1, byte2, val) \
++ (byte1) = (((val) * 10) & 0xff), (byte2) = (((val) * 10) >> 8)
++#define WDOG_GET_TIMEOUT(byte1, byte2) \
++ (((byte1) | ((byte2) << 8)) / 10)
++
++#define IPMI_WDOG_RESET_TIMER 0x22
++#define IPMI_WDOG_SET_TIMER 0x24
++#define IPMI_WDOG_GET_TIMER 0x25
++
++/* These are here until the real ones get into the watchdog.h interface. */
++#ifndef WDIOC_GETTIMEOUT
++#define WDIOC_GETTIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 20, int)
++#endif
++#ifndef WDIOC_SET_PRETIMEOUT
++#define WDIOC_SET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 21, int)
++#endif
++#ifndef WDIOC_GET_PRETIMEOUT
++#define WDIOC_GET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 22, int)
++#endif
++
++static ipmi_user_t watchdog_user = NULL;
++
++/* Default the timeout to 10 seconds. */
++static int timeout = 10;
++
++/* The pre-timeout is disabled by default. */
++static int pretimeout = 0;
++
++/* Default action is to reset the board on a timeout. */
++static unsigned char action_val = WDOG_TIMEOUT_RESET;
++
++static char *action = "reset";
++
++static unsigned char preaction_val = WDOG_PRETIMEOUT_NONE;
++
++static char *preaction = "pre_none";
++
++static unsigned char preop_val = WDOG_PREOP_NONE;
++
++static char *preop = "preop_none";
++static spinlock_t ipmi_read_lock = SPIN_LOCK_UNLOCKED;
++static char data_to_read = 0;
++static DECLARE_WAIT_QUEUE_HEAD(read_q);
++static struct fasync_struct *fasync_q = NULL;
++static char pretimeout_since_last_heartbeat = 0;
++
++MODULE_PARM(timeout, "i");
++MODULE_PARM(pretimeout, "i");
++MODULE_PARM(action, "s");
++MODULE_PARM(preaction, "s");
++MODULE_PARM(preop, "s");
++
++/* Default state of the timer. */
++static unsigned char ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
++
++/* If shutting down via IPMI, we ignore the heartbeat. */
++static int ipmi_ignore_heartbeat = 0;
++
++/* Is someone using the watchdog? Only one user is allowed. */
++static int ipmi_wdog_open = 0;
++
++/* If true, the driver will start running as soon as it is configured
++ and ready. */
++static int start_now = 0;
++
++/* If set to 1, the heartbeat command will set the state to reset and
++ start the timer. The timer doesn't normally run when the driver is
++ first opened until the heartbeat is set the first time, this
++ variable is used to accomplish this. */
++static int ipmi_start_timer_on_heartbeat = 0;
++
++/* IPMI version of the BMC. */
++static unsigned char ipmi_version_major;
++static unsigned char ipmi_version_minor;
++
++
++static int ipmi_heartbeat(void);
++static void panic_halt_ipmi_heartbeat(void);
++
++
++/* We use a semaphore to make sure that only one thing can send a set
++ timeout at one time, because we only have one copy of the data.
++ The semaphore is claimed when the set_timeout is sent and freed
++ when both messages are free. */
++static atomic_t set_timeout_tofree = ATOMIC_INIT(0);
++static DECLARE_MUTEX(set_timeout_lock);
++static void set_timeout_free_smi(struct ipmi_smi_msg *msg)
++{
++ if (atomic_dec_and_test(&set_timeout_tofree))
++ up(&set_timeout_lock);
++}
++static void set_timeout_free_recv(struct ipmi_recv_msg *msg)
++{
++ if (atomic_dec_and_test(&set_timeout_tofree))
++ up(&set_timeout_lock);
++}
++static struct ipmi_smi_msg set_timeout_smi_msg =
++{
++ .done = set_timeout_free_smi
++};
++static struct ipmi_recv_msg set_timeout_recv_msg =
++{
++ .done = set_timeout_free_recv
++};
++
++static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
++ struct ipmi_recv_msg *recv_msg,
++ int *send_heartbeat_now)
++{
++ struct ipmi_msg msg;
++ unsigned char data[6];
++ int rv;
++ struct ipmi_system_interface_addr addr;
++
++
++ *send_heartbeat_now = 0;
++ data[0] = 0;
++ WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);
++
++ if ((ipmi_version_major > 1)
++ || ((ipmi_version_major == 1) && (ipmi_version_minor >= 5)))
++ {
++ /* This is an IPMI 1.5-only feature. */
++ data[0] |= WDOG_DONT_STOP_ON_SET;
++ } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
++ /* In ipmi 1.0, setting the timer stops the watchdog, we
++ need to start it back up again. */
++ *send_heartbeat_now = 1;
++ }
++
++ data[1] = 0;
++ WDOG_SET_TIMEOUT_ACT(data[1], ipmi_watchdog_state);
++ if (pretimeout > 0) {
++ WDOG_SET_PRETIMEOUT_ACT(data[1], preaction_val);
++ data[2] = pretimeout;
++ } else {
++ WDOG_SET_PRETIMEOUT_ACT(data[1], WDOG_PRETIMEOUT_NONE);
++ data[2] = 0; /* No pretimeout. */
++ }
++ data[3] = 0;
++ WDOG_SET_TIMEOUT(data[4], data[5], timeout);
++
++ addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ addr.channel = IPMI_BMC_CHANNEL;
++ addr.lun = 0;
++
++ msg.netfn = 0x06;
++ msg.cmd = IPMI_WDOG_SET_TIMER;
++ msg.data = data;
++ msg.data_len = sizeof(data);
++ rv = ipmi_request_supply_msgs(watchdog_user,
++ (struct ipmi_addr *) &addr,
++ 0,
++ &msg,
++ smi_msg,
++ recv_msg,
++ 1);
++ if (rv) {
++ printk(KERN_WARNING "IPMI Watchdog, set timeout error: %d\n",
++ rv);
++ }
++
++ return rv;
++}
++
++static int ipmi_set_timeout(void)
++{
++ int send_heartbeat_now;
++ int rv;
++
++
++ /* We can only send one of these at a time. */
++ down(&set_timeout_lock);
++
++ atomic_set(&set_timeout_tofree, 2);
++
++ rv = i_ipmi_set_timeout(&set_timeout_smi_msg,
++ &set_timeout_recv_msg,
++ &send_heartbeat_now);
++ if (rv) {
++ up(&set_timeout_lock);
++ } else {
++ if (send_heartbeat_now)
++ rv = ipmi_heartbeat();
++ }
++
++ return rv;
++}
++
++static void dummy_smi_free(struct ipmi_smi_msg *msg)
++{
++}
++static void dummy_recv_free(struct ipmi_recv_msg *msg)
++{
++}
++static struct ipmi_smi_msg panic_halt_smi_msg =
++{
++ .done = dummy_smi_free
++};
++static struct ipmi_recv_msg panic_halt_recv_msg =
++{
++ .done = dummy_recv_free
++};
++
++/* Special call, doesn't claim any locks. This is only to be called
++ at panic or halt time, in run-to-completion mode, when the caller
++ is the only CPU and the only thing that will be going IPMI
++ calls. */
++static void panic_halt_ipmi_set_timeout(void)
++{
++ int send_heartbeat_now;
++ int rv;
++
++ rv = i_ipmi_set_timeout(&panic_halt_smi_msg,
++ &panic_halt_recv_msg,
++ &send_heartbeat_now);
++ if (!rv) {
++ if (send_heartbeat_now)
++ panic_halt_ipmi_heartbeat();
++ }
++}
++
++/* Do a delayed shutdown, with the delay in milliseconds. If power_off is
++ false, do a reset. If power_off is true, do a power down. This is
++ primarily for the IMB code's shutdown. */
++void ipmi_delayed_shutdown(long delay, int power_off)
++{
++ ipmi_ignore_heartbeat = 1;
++ if (power_off)
++ ipmi_watchdog_state = WDOG_TIMEOUT_POWER_DOWN;
++ else
++ ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
++ timeout = delay;
++ ipmi_set_timeout();
++}
++
++/* We use a semaphore to make sure that only one thing can send a
++ heartbeat at one time, because we only have one copy of the data.
++ The semaphore is claimed when the set_timeout is sent and freed
++ when both messages are free. */
++static atomic_t heartbeat_tofree = ATOMIC_INIT(0);
++static DECLARE_MUTEX(heartbeat_lock);
++static DECLARE_MUTEX_LOCKED(heartbeat_wait_lock);
++static void heartbeat_free_smi(struct ipmi_smi_msg *msg)
++{
++ if (atomic_dec_and_test(&heartbeat_tofree))
++ up(&heartbeat_wait_lock);
++}
++static void heartbeat_free_recv(struct ipmi_recv_msg *msg)
++{
++ if (atomic_dec_and_test(&heartbeat_tofree))
++ up(&heartbeat_wait_lock);
++}
++static struct ipmi_smi_msg heartbeat_smi_msg =
++{
++ .done = heartbeat_free_smi
++};
++static struct ipmi_recv_msg heartbeat_recv_msg =
++{
++ .done = heartbeat_free_recv
++};
++
++static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg =
++{
++ .done = dummy_smi_free
++};
++static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
++{
++ .done = dummy_recv_free
++};
++
++static int ipmi_heartbeat(void)
++{
++ struct ipmi_msg msg;
++ int rv;
++ struct ipmi_system_interface_addr addr;
++
++ if (ipmi_ignore_heartbeat) {
++ return 0;
++ }
++
++ if (ipmi_start_timer_on_heartbeat) {
++ ipmi_start_timer_on_heartbeat = 0;
++ ipmi_watchdog_state = action_val;
++ return ipmi_set_timeout();
++ }
++
++ if (pretimeout_since_last_heartbeat) {
++ /* A pretimeout occurred, make sure we set the timeout.
++ We don't want to set the action, though, we want to
++ leave that alone (thus it can't be combined with the
++ above operation. */
++ pretimeout_since_last_heartbeat = 0;
++ return ipmi_set_timeout();
++ }
++
++ down(&heartbeat_lock);
++
++ atomic_set(&heartbeat_tofree, 2);
++
++ /* Don't reset the timer if we have the timer turned off, that
++ re-enables the watchdog. */
++ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) {
++ up(&heartbeat_lock);
++ return 0;
++ }
++
++ addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ addr.channel = IPMI_BMC_CHANNEL;
++ addr.lun = 0;
++
++ msg.netfn = 0x06;
++ msg.cmd = IPMI_WDOG_RESET_TIMER;
++ msg.data = NULL;
++ msg.data_len = 0;
++ rv = ipmi_request_supply_msgs(watchdog_user,
++ (struct ipmi_addr *) &addr,
++ 0,
++ &msg,
++ &heartbeat_smi_msg,
++ &heartbeat_recv_msg,
++ 1);
++ if (rv) {
++ up(&heartbeat_lock);
++ printk(KERN_WARNING "IPMI Watchdog, heartbeat failure: %d\n",
++ rv);
++ return rv;
++ }
++
++ /* Wait for the heartbeat to be sent. */
++ down(&heartbeat_wait_lock);
++
++ if (heartbeat_recv_msg.msg.data[0] != 0) {
++ /* Got an error in the heartbeat response. It was already
++ reported in ipmi_wdog_msg_handler, but we should return
++ an error here. */
++ rv = -EINVAL;
++ }
++
++ up(&heartbeat_lock);
++
++ return rv;
++}
++
++static void panic_halt_ipmi_heartbeat(void)
++{
++ struct ipmi_msg msg;
++ struct ipmi_system_interface_addr addr;
++
++
++ /* Don't reset the timer if we have the timer turned off, that
++ re-enables the watchdog. */
++ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
++ return;
++
++ addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
++ addr.channel = IPMI_BMC_CHANNEL;
++ addr.lun = 0;
++
++ msg.netfn = 0x06;
++ msg.cmd = IPMI_WDOG_RESET_TIMER;
++ msg.data = NULL;
++ msg.data_len = 0;
++ ipmi_request_supply_msgs(watchdog_user,
++ (struct ipmi_addr *) &addr,
++ 0,
++ &msg,
++ &panic_halt_heartbeat_smi_msg,
++ &panic_halt_heartbeat_recv_msg,
++ 1);
++}
++
++static struct watchdog_info ident=
++{
++ 0, /* WDIOF_SETTIMEOUT, */
++ 1,
++ "IPMI"
++};
++
++static int ipmi_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ int i;
++ int val;
++
++ switch(cmd) {
++ case WDIOC_GETSUPPORT:
++ i = copy_to_user((void*)arg, &ident, sizeof(ident));
++ return i ? -EFAULT : 0;
++
++ case WDIOC_SETTIMEOUT:
++ i = copy_from_user(&val, (void *) arg, sizeof(int));
++ if (i)
++ return -EFAULT;
++ timeout = val;
++ return ipmi_set_timeout();
++
++ case WDIOC_GETTIMEOUT:
++ i = copy_to_user((void *) arg,
++ &timeout,
++ sizeof(timeout));
++ if (i)
++ return -EFAULT;
++ return 0;
++
++ case WDIOC_SET_PRETIMEOUT:
++ i = copy_from_user(&val, (void *) arg, sizeof(int));
++ if (i)
++ return -EFAULT;
++ pretimeout = val;
++ return ipmi_set_timeout();
++
++ case WDIOC_GET_PRETIMEOUT:
++ i = copy_to_user((void *) arg,
++ &pretimeout,
++ sizeof(pretimeout));
++ if (i)
++ return -EFAULT;
++ return 0;
++
++ case WDIOC_KEEPALIVE:
++ return ipmi_heartbeat();
++
++ case WDIOC_SETOPTIONS:
++ i = copy_from_user(&val, (void *) arg, sizeof(int));
++ if (i)
++ return -EFAULT;
++ if (val & WDIOS_DISABLECARD)
++ {
++ ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
++ ipmi_set_timeout();
++ ipmi_start_timer_on_heartbeat = 0;
++ }
++
++ if (val & WDIOS_ENABLECARD)
++ {
++ ipmi_watchdog_state = action_val;
++ ipmi_set_timeout();
++ }
++ return 0;
++
++ case WDIOC_GETSTATUS:
++ val = 0;
++ return copy_to_user((void *) arg, &val, sizeof(val));
++
++ default:
++ return -ENOIOCTLCMD;
++ }
++}
++
++static ssize_t ipmi_write(struct file *file,
++ const char *buf,
++ size_t len,
++ loff_t *ppos)
++{
++ int rv;
++
++ /* Can't seek (pwrite) on this device */
++ if (ppos != &file->f_pos)
++ return -ESPIPE;
++
++ if (len) {
++ rv = ipmi_heartbeat();
++ if (rv)
++ return rv;
++ return 1;
++ }
++ return 0;
++}
++
++static ssize_t ipmi_read(struct file *file,
++ char *buf,
++ size_t count,
++ loff_t *ppos)
++{
++ int rv = 0;
++ wait_queue_t wait;
++
++ /* Can't seek (pread) on this device */
++ if (ppos != &file->f_pos)
++ return -ESPIPE;
++
++ if (count <= 0)
++ return 0;
++
++ /* Reading returns if the pretimeout has gone off, and it only does
++ it once per pretimeout. */
++ spin_lock(&ipmi_read_lock);
++ if (!data_to_read) {
++ if (file->f_flags & O_NONBLOCK) {
++ rv = -EAGAIN;
++ goto out;
++ }
++
++ init_waitqueue_entry(&wait, current);
++ add_wait_queue(&read_q, &wait);
++ while (!data_to_read) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ spin_unlock(&ipmi_read_lock);
++ schedule();
++ spin_lock(&ipmi_read_lock);
++ }
++ remove_wait_queue(&read_q, &wait);
++
++ if (signal_pending(current)) {
++ rv = -ERESTARTSYS;
++ goto out;
++ }
++ }
++ data_to_read = 0;
++
++ out:
++ spin_unlock(&ipmi_read_lock);
++
++ if (rv == 0) {
++ if (copy_to_user(buf, &data_to_read, 1))
++ rv = -EFAULT;
++ else
++ rv = 1;
++ }
++
++ return rv;
++}
++
++static int ipmi_open(struct inode *ino, struct file *filep)
++{
++ switch (minor(ino->i_rdev))
++ {
++ case WATCHDOG_MINOR:
++ if (ipmi_wdog_open)
++ return -EBUSY;
++
++ ipmi_wdog_open = 1;
++
++ /* Don't start the timer now, let it start on the
++ first heartbeat. */
++ ipmi_start_timer_on_heartbeat = 1;
++ return(0);
++
++ default:
++ return (-ENODEV);
++ }
++}
++
++static unsigned int ipmi_poll(struct file *file, poll_table *wait)
++{
++ unsigned int mask = 0;
++
++ poll_wait(file, &read_q, wait);
++
++ spin_lock(&ipmi_read_lock);
++ if (data_to_read)
++ mask |= (POLLIN | POLLRDNORM);
++ spin_unlock(&ipmi_read_lock);
++
++ return mask;
++}
++
++static int ipmi_fasync(int fd, struct file *file, int on)
++{
++ int result;
++
++ result = fasync_helper(fd, file, on, &fasync_q);
++
++ return (result);
++}
++
++static int ipmi_close(struct inode *ino, struct file *filep)
++{
++ if (minor(ino->i_rdev)==WATCHDOG_MINOR)
++ {
++#ifndef CONFIG_WATCHDOG_NOWAYOUT
++ ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
++ ipmi_set_timeout();
++#endif
++ ipmi_wdog_open = 0;
++ }
++
++ ipmi_fasync (-1, filep, 0);
++
++ return 0;
++}
++
++static struct file_operations ipmi_wdog_fops = {
++ .owner = THIS_MODULE,
++ .read = ipmi_read,
++ .poll = ipmi_poll,
++ .write = ipmi_write,
++ .ioctl = ipmi_ioctl,
++ .open = ipmi_open,
++ .release = ipmi_close,
++ .fasync = ipmi_fasync,
++};
++
++static struct miscdevice ipmi_wdog_miscdev = {
++ WATCHDOG_MINOR,
++ "watchdog",
++ &ipmi_wdog_fops
++};
++
++static DECLARE_RWSEM(register_sem);
++
++static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
++ void *handler_data)
++{
++ if (msg->msg.data[0] != 0) {
++ printk(KERN_ERR "IPMI Watchdog response: Error %x on cmd %x\n",
++ msg->msg.data[0],
++ msg->msg.cmd);
++ }
++
++ ipmi_free_recv_msg(msg);
++}
++
++static void ipmi_wdog_pretimeout_handler(void *handler_data)
++{
++ if (preaction_val != WDOG_PRETIMEOUT_NONE) {
++ if (preop_val == WDOG_PREOP_PANIC)
++ panic("Watchdog pre-timeout");
++ else if (preop_val == WDOG_PREOP_GIVE_DATA) {
++ spin_lock(&ipmi_read_lock);
++ data_to_read = 1;
++ wake_up_interruptible(&read_q);
++ kill_fasync(&fasync_q, SIGIO, POLL_IN);
++
++ /* On some machines, the heartbeat will give
++ an error and not work unless we re-enable
++ the timer. So do so. */
++ pretimeout_since_last_heartbeat = 1;
++
++ spin_unlock(&ipmi_read_lock);
++ }
++ }
++}
++
++static struct ipmi_user_hndl ipmi_hndlrs =
++{
++ .ipmi_recv_hndl = ipmi_wdog_msg_handler,
++ .ipmi_watchdog_pretimeout = ipmi_wdog_pretimeout_handler
++};
++
++static void ipmi_register_watchdog(int ipmi_intf)
++{
++ int rv = -EBUSY;
++
++ down_read(&register_sem);
++ if (watchdog_user)
++ goto out;
++
++ rv = ipmi_create_user(ipmi_intf, &ipmi_hndlrs, NULL, &watchdog_user);
++ if (rv < 0) {
++ printk("IPMI watchdog: Unable to register with ipmi\n");
++ goto out;
++ }
++
++ ipmi_get_version(watchdog_user,
++ &ipmi_version_major,
++ &ipmi_version_minor);
++
++ rv = misc_register(&ipmi_wdog_miscdev);
++ if (rv < 0) {
++ ipmi_destroy_user(watchdog_user);
++ watchdog_user = NULL;
++ printk("IPMI watchdog: Unable to register misc device\n");
++ }
++
++ out:
++ up_write(&register_sem);
++
++ if ((start_now) && (rv == 0)) {
++ /* Run from startup, so start the timer now. */
++ start_now = 0; /* Disable this function after first startup. */
++ ipmi_watchdog_state = action_val;
++ ipmi_set_timeout();
++ printk("Starting IPMI Watchdog now!\n");
++ }
++}
++
++#ifdef HAVE_NMI_HANDLER
++static int
++ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled)
++{
++ /* If no one else handled the NMI, we assume it was the IPMI
++ watchdog. */
++ if ((!handled) && (preop_val == WDOG_PREOP_PANIC))
++ panic("IPMI watchdog pre-timeout");
++ return NOTIFY_DONE;
++}
++
++static struct nmi_handler ipmi_nmi_handler =
++{
++ .dev_name = "ipmi_watchdog",
++ .dev_id = NULL,
++ .handler = ipmi_nmi,
++ .priority = 0, /* Call us last. */
++};
++#endif
++
++static int wdog_reboot_handler(struct notifier_block *this,
++ unsigned long code,
++ void *unused)
++{
++ static int reboot_event_handled = 0;
++
++ if ((watchdog_user) && (!reboot_event_handled)) {
++ /* Make sure we only do this once. */
++ reboot_event_handled = 1;
++
++ if (code == SYS_DOWN || code == SYS_HALT) {
++ /* Disable the WDT if we are shutting down. */
++ ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
++ panic_halt_ipmi_set_timeout();
++ } else {
++ /* Set a long timer to let the reboot happens, but
++ reboot if it hangs. */
++ timeout = 120;
++ pretimeout = 0;
++ ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
++ panic_halt_ipmi_set_timeout();
++ }
++ }
++ return NOTIFY_OK;
++}
++
++static struct notifier_block wdog_reboot_notifier = {
++ wdog_reboot_handler,
++ NULL,
++ 0
++};
++
++extern int panic_timeout; /* Why isn't this defined anywhere? */
++
++static int wdog_panic_handler(struct notifier_block *this,
++ unsigned long event,
++ void *unused)
++{
++ static int panic_event_handled = 0;
++
++ /* On a panic, if we have a panic timeout, make sure that the thing
++ reboots, even if it hangs during that panic. */
++ if (watchdog_user && !panic_event_handled && (panic_timeout > 0)) {
++ /* Make sure the panic doesn't hang, and make sure we
++ do this only once. */
++ panic_event_handled = 1;
++
++ timeout = panic_timeout + 120;
++ if (timeout > 255)
++ timeout = 255;
++ pretimeout = 0;
++ ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
++ panic_halt_ipmi_set_timeout();
++ }
++
++ return NOTIFY_OK;
++}
++
++static struct notifier_block wdog_panic_notifier = {
++ wdog_panic_handler,
++ NULL,
++ 150 /* priority: INT_MAX >= x >= 0 */
++};
++
++
++static void ipmi_new_smi(int if_num)
++{
++ ipmi_register_watchdog(if_num);
++}
++
++static void ipmi_smi_gone(int if_num)
++{
++ /* This can never be called, because once the watchdog is
++ registered, the interface can't go away until the watchdog
++ is unregistered. */
++}
++
++static struct ipmi_smi_watcher smi_watcher =
++{
++ .new_smi = ipmi_new_smi,
++ .smi_gone = ipmi_smi_gone
++};
++
++static int __init ipmi_wdog_init(void)
++{
++ int rv;
++
++ if (strcmp(action, "reset") == 0) {
++ action_val = WDOG_TIMEOUT_RESET;
++ } else if (strcmp(action, "none") == 0) {
++ action_val = WDOG_TIMEOUT_NONE;
++ } else if (strcmp(action, "power_cycle") == 0) {
++ action_val = WDOG_TIMEOUT_POWER_CYCLE;
++ } else if (strcmp(action, "power_off") == 0) {
++ action_val = WDOG_TIMEOUT_POWER_DOWN;
++ } else {
++ action_val = WDOG_TIMEOUT_RESET;
++ printk("ipmi_watchdog: Unknown action '%s', defaulting to"
++ " reset\n", action);
++ }
++
++ if (strcmp(preaction, "pre_none") == 0) {
++ preaction_val = WDOG_PRETIMEOUT_NONE;
++ } else if (strcmp(preaction, "pre_smi") == 0) {
++ preaction_val = WDOG_PRETIMEOUT_SMI;
++#ifdef HAVE_NMI_HANDLER
++ } else if (strcmp(preaction, "pre_nmi") == 0) {
++ preaction_val = WDOG_PRETIMEOUT_NMI;
++#endif
++ } else if (strcmp(preaction, "pre_int") == 0) {
++ preaction_val = WDOG_PRETIMEOUT_MSG_INT;
++ } else {
++ action_val = WDOG_PRETIMEOUT_NONE;
++ printk("ipmi_watchdog: Unknown preaction '%s', defaulting to"
++ " none\n", preaction);
++ }
++
++ if (strcmp(preop, "preop_none") == 0) {
++ preop_val = WDOG_PREOP_NONE;
++ } else if (strcmp(preop, "preop_panic") == 0) {
++ preop_val = WDOG_PREOP_PANIC;
++ } else if (strcmp(preop, "preop_give_data") == 0) {
++ preop_val = WDOG_PREOP_GIVE_DATA;
++ } else {
++ action_val = WDOG_PREOP_NONE;
++ printk("ipmi_watchdog: Unknown preop '%s', defaulting to"
++ " none\n", preop);
++ }
++
++#ifdef HAVE_NMI_HANDLER
++ if (preaction_val == WDOG_PRETIMEOUT_NMI) {
++ if (preop_val == WDOG_PREOP_GIVE_DATA) {
++ printk(KERN_WARNING
++ "ipmi_watchdog: Pretimeout op is to give data"
++ " but NMI pretimeout is enabled, setting"
++ " pretimeout op to none\n");
++ preop_val = WDOG_PREOP_NONE;
++ }
++#ifdef CONFIG_X86_LOCAL_APIC
++ if (nmi_watchdog == NMI_IO_APIC) {
++ printk(KERN_WARNING
++ "ipmi_watchdog: nmi_watchdog is set to IO APIC"
++ " mode (value is %d), that is incompatible"
++ " with using NMI in the IPMI watchdog."
++ " Disabling IPMI nmi pretimeout.\n",
++ nmi_watchdog);
++ preaction_val = WDOG_PRETIMEOUT_NONE;
++ } else {
++#endif
++ rv = request_nmi(&ipmi_nmi_handler);
++ if (rv) {
++ printk(KERN_WARNING
++ "ipmi_watchdog: Can't register nmi handler\n");
++ return rv;
++ }
++#ifdef CONFIG_X86_LOCAL_APIC
++ }
++#endif
++ }
++#endif
++
++ rv = ipmi_smi_watcher_register(&smi_watcher);
++ if (rv) {
++#ifdef HAVE_NMI_HANDLER
++ if (preaction_val == WDOG_PRETIMEOUT_NMI)
++ release_nmi(&ipmi_nmi_handler);
++#endif
++ printk(KERN_WARNING
++ "ipmi_watchdog: can't register smi watcher\n");
++ return rv;
++ }
++
++ register_reboot_notifier(&wdog_reboot_notifier);
++ notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier);
++
++ printk(KERN_INFO "IPMI watchdog by "
++ "Corey Minyard (minyard@mvista.com)\n");
++
++ return 0;
++}
++
++#ifdef MODULE
++static void ipmi_unregister_watchdog(void)
++{
++ int rv;
++
++ down_write(&register_sem);
++
++#ifdef HAVE_NMI_HANDLER
++ if (preaction_val == WDOG_PRETIMEOUT_NMI)
++ release_nmi(&ipmi_nmi_handler);
++#endif
++
++ notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier);
++ unregister_reboot_notifier(&wdog_reboot_notifier);
++
++ if (! watchdog_user)
++ goto out;
++
++ /* Make sure no one can call us any more. */
++ misc_deregister(&ipmi_wdog_miscdev);
++
++ /* Disable the timer. */
++ ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
++ ipmi_set_timeout();
++
++ /* Wait to make sure the message makes it out. The lower layer has
++ pointers to our buffers, we want to make sure they are done before
++ we release our memory. */
++ while (atomic_read(&set_timeout_tofree)) {
++ schedule_timeout(1);
++ }
++
++ /* Disconnect from IPMI. */
++ rv = ipmi_destroy_user(watchdog_user);
++ if (rv) {
++ printk(KERN_WARNING
++ "IPMI Watchdog, error unlinking from IPMI: %d\n",
++ rv);
++ }
++ watchdog_user = NULL;
++
++ out:
++ up_write(&register_sem);
++}
++
++static void __exit ipmi_wdog_exit(void)
++{
++ ipmi_smi_watcher_unregister(&smi_watcher);
++ ipmi_unregister_watchdog();
++}
++module_exit(ipmi_wdog_exit);
++#else
++static int __init ipmi_wdog_setup(char *str)
++{
++ int val;
++ int rv;
++ char *option;
++
++ rv = get_option(&str, &val);
++ if (rv == 0)
++ return 1;
++ if (val > 0)
++ timeout = val;
++ if (rv == 1)
++ return 1;
++
++ rv = get_option(&str, &val);
++ if (rv == 0)
++ return 1;
++ if (val >= 0)
++ pretimeout = val;
++ if (rv == 1)
++ return 1;
++
++ while ((option = strsep(&str, ",")) != NULL) {
++ if (strcmp(option, "reset") == 0) {
++ action = "reset";
++ }
++ else if (strcmp(option, "none") == 0) {
++ action = "none";
++ }
++ else if (strcmp(option, "power_cycle") == 0) {
++ action = "power_cycle";
++ }
++ else if (strcmp(option, "power_off") == 0) {
++ action = "power_off";
++ }
++ else if (strcmp(option, "pre_none") == 0) {
++ preaction = "pre_none";
++ }
++ else if (strcmp(option, "pre_smi") == 0) {
++ preaction = "pre_smi";
++ }
++#ifdef HAVE_NMI_HANDLER
++ else if (strcmp(option, "pre_nmi") == 0) {
++ preaction = "pre_nmi";
++ }
++#endif
++ else if (strcmp(option, "pre_int") == 0) {
++ preaction = "pre_int";
++ }
++ else if (strcmp(option, "start_now") == 0) {
++ start_now = 1;
++ }
++ else if (strcmp(option, "preop_none") == 0) {
++ preop = "preop_none";
++ }
++ else if (strcmp(option, "preop_panic") == 0) {
++ preop = "preop_panic";
++ }
++ else if (strcmp(option, "preop_none") == 0) {
++ preop = "preop_give_data";
++ } else {
++ printk("Unknown IPMI watchdog option: '%s'\n", option);
++ }
++ }
++
++ return 1;
++}
++__setup("ipmi_wdog=", ipmi_wdog_setup);
++#endif
++
++EXPORT_SYMBOL(ipmi_delayed_shutdown);
++
++module_init(ipmi_wdog_init);
++MODULE_LICENSE("GPL");
+--- /dev/null 2002-08-30 19:31:37.000000000 -0400
++++ linux-2.4.18-14/include/linux/ipmi.h 2003-03-27 15:26:22.000000000 -0500
+@@ -0,0 +1,516 @@
++/*
++ * ipmi.h
++ *
++ * MontaVista IPMI interface
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __LINUX_IPMI_H
++#define __LINUX_IPMI_H
++
++#include <linux/ipmi_msgdefs.h>
++
++/*
++ * This file describes an interface to an IPMI driver. You have to
++ * have a fairly good understanding of IPMI to use this, so go read
++ * the specs first before actually trying to do anything.
++ *
++ * With that said, this driver provides a multi-user interface to the
++ * IPMI driver, and it allows multiple IPMI physical interfaces below
++ * the driver. The physical interfaces bind as a lower layer on the
++ * driver. They appear as interfaces to the application using this
++ * interface.
++ *
++ * Multi-user means that multiple applications may use the driver,
++ * send commands, receive responses, etc. The driver keeps track of
++ * commands the user sends and tracks the responses. The responses
++ * will go back to the application that send the command. If the
++ * response doesn't come back in time, the driver will return a
++ * timeout error response to the application. Asynchronous events
++ * from the BMC event queue will go to all users bound to the driver.
++ * The incoming event queue in the BMC will automatically be flushed
++ * if it becomes full and it is queried once a second to see if
++ * anything is in it. Incoming commands to the driver will get
++ * delivered as commands.
++ *
++ * This driver provides two main interfaces: one for in-kernel
++ * applications and another for userland applications. The
++ * capabilities are basically the same for both interface, although
++ * the interfaces are somewhat different. The stuff in the
++ * #ifdef KERNEL below is the in-kernel interface. The userland
++ * interface is defined later in the file. */
++
++
++
++/*
++ * This is an overlay for all the address types, so it's easy to
++ * determine the actual address type. This is kind of like addresses
++ * work for sockets.
++ */
++#define IPMI_MAX_ADDR_SIZE 32
++struct ipmi_addr
++{
++ /* Try to take these from the "Channel Medium Type" table
++ in section 6.5 of the IPMI 1.5 manual. */
++ int addr_type;
++ short channel;
++ char data[IPMI_MAX_ADDR_SIZE];
++};
++
++/*
++ * When the address is not used, the type will be set to this value.
++ * The channel is the BMC's channel number for the channel (usually
++ * 0), or IPMC_BMC_CHANNEL if communicating directly with the BMC.
++ */
++#define IPMI_SYSTEM_INTERFACE_ADDR_TYPE 0x0c
++struct ipmi_system_interface_addr
++{
++ int addr_type;
++ short channel;
++ unsigned char lun;
++};
++
++/* An IPMB Address. */
++#define IPMI_IPMB_ADDR_TYPE 0x01
++/* Used for broadcast get device id as described in section 17.9 of the
++ IPMI 1.5 manual. */
++#define IPMI_IPMB_BROADCAST_ADDR_TYPE 0x41
++struct ipmi_ipmb_addr
++{
++ int addr_type;
++ short channel;
++ unsigned char slave_addr;
++ unsigned char lun;
++};
++
++
++/*
++ * Channel for talking directly with the BMC. When using this
++ * channel, This is for the system interface address type only. FIXME
++ * - is this right, or should we use -1?
++ */
++#define IPMI_BMC_CHANNEL 0xf
++#define IPMI_NUM_CHANNELS 0x10
++
++
++/*
++ * A raw IPMI message without any addressing. This covers both
++ * commands and responses. The completion code is always the first
++ * byte of data in the response (as the spec shows the messages laid
++ * out).
++ */
++struct ipmi_msg
++{
++ unsigned char netfn;
++ unsigned char cmd;
++ unsigned short data_len;
++ unsigned char *data;
++};
++
++/*
++ * Various defines that are useful for IPMI applications.
++ */
++#define IPMI_INVALID_CMD_COMPLETION_CODE 0xC1
++#define IPMI_TIMEOUT_COMPLETION_CODE 0xC3
++#define IPMI_UNKNOWN_ERR_COMPLETION_CODE 0xff
++
++
++/*
++ * Receive types for messages coming from the receive interface. This
++ * is used for the receive in-kernel interface and in the receive
++ * IOCTL.
++ */
++#define IPMI_RESPONSE_RECV_TYPE 1 /* A response to a command */
++#define IPMI_ASYNC_EVENT_RECV_TYPE 2 /* Something from the event queue */
++#define IPMI_CMD_RECV_TYPE 3 /* A command from somewhere else */
++/* Note that async events and received commands do not have a completion
++ code as the first byte of the incoming data, unlike a response. */
++
++
++
++#ifdef __KERNEL__
++
++/*
++ * The in-kernel interface.
++ */
++#include <linux/list.h>
++
++/* Opaque type for a IPMI message user. One of these is needed to
++ send and receive messages. */
++typedef struct ipmi_user *ipmi_user_t;
++
++/*
++ * Stuff coming from the recieve interface comes as one of these.
++ * They are allocated, the receiver must free them with
++ * ipmi_free_recv_msg() when done with the message. The link is not
++ * used after the message is delivered, so the upper layer may use the
++ * link to build a linked list, if it likes.
++ */
++struct ipmi_recv_msg
++{
++ struct list_head link;
++
++ /* The type of message as defined in the "Receive Types"
++ defines above. */
++ int recv_type;
++
++ ipmi_user_t user;
++ struct ipmi_addr addr;
++ long msgid;
++ struct ipmi_msg msg;
++
++ /* Call this when done with the message. It will presumably free
++ the message and do any other necessary cleanup. */
++ void (*done)(struct ipmi_recv_msg *msg);
++
++ /* Place-holder for the data, don't make any assumptions about
++ the size or existance of this, since it may change. */
++ unsigned char msg_data[IPMI_MAX_MSG_LENGTH];
++};
++
++/* Allocate and free the receive message. */
++static inline void ipmi_free_recv_msg(struct ipmi_recv_msg *msg)
++{
++ msg->done(msg);
++}
++struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
++
++struct ipmi_user_hndl
++{
++ /* Routine type to call when a message needs to be routed to
++ the upper layer. This will be called with some locks held,
++ the only IPMI routines that can be called are ipmi_request
++ and the alloc/free operations. */
++ void (*ipmi_recv_hndl)(struct ipmi_recv_msg *msg,
++ void *handler_data);
++
++ /* Called when the interface detects a watchdog pre-timeout. If
++ this is NULL, it will be ignored for the user. */
++ void (*ipmi_watchdog_pretimeout)(void *handler_data);
++};
++
++/* Create a new user of the IPMI layer on the given interface number. */
++int ipmi_create_user(unsigned int if_num,
++ struct ipmi_user_hndl *handler,
++ void *handler_data,
++ ipmi_user_t *user);
++
++/* Destroy the given user of the IPMI layer. */
++int ipmi_destroy_user(ipmi_user_t user);
++
++/* Get the IPMI version of the BMC we are talking to. */
++void ipmi_get_version(ipmi_user_t user,
++ unsigned char *major,
++ unsigned char *minor);
++
++/* Set and get the slave address and LUN that we will use for our
++ source messages. Note that this affects the interface, not just
++ this user, so it will affect all users of this interface. This is
++ so some initialization code can come in and do the OEM-specific
++ things it takes to determine your address (if not the BMC) and set
++ it for everyone else. */
++void ipmi_set_my_address(ipmi_user_t user,
++ unsigned char address);
++unsigned char ipmi_get_my_address(ipmi_user_t user);
++void ipmi_set_my_LUN(ipmi_user_t user,
++ unsigned char LUN);
++unsigned char ipmi_get_my_LUN(ipmi_user_t user);
++
++/*
++ * Send a command request from the given user. The address is the
++ * proper address for the channel type. If this is a command, then
++ * the message response comes back, the receive handler for this user
++ * will be called with the given msgid value in the recv msg. If this
++ * is a response to a command, then the msgid will be used as the
++ * sequence number for the response (truncated if necessary), so when
++ * sending a response you should use the sequence number you received
++ * in the msgid field of the received command. If the priority is >
++ * 0, the message will go into a high-priority queue and be sent
++ * first. Otherwise, it goes into a normal-priority queue.
++ */
++int ipmi_request(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ int priority);
++
++/*
++ * Like ipmi_request, but lets you specify the slave return address.
++ */
++int ipmi_request_with_source(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ int priority,
++ unsigned char source_address,
++ unsigned char source_lun);
++
++/*
++ * Like ipmi_request, but with messages supplied. This will not
++ * allocate any memory, and the messages may be statically allocated
++ * (just make sure to do the "done" handling on them). Note that this
++ * is primarily for the watchdog timer, since it should be able to
++ * send messages even if no memory is available. This is subject to
++ * change as the system changes, so don't use it unless you REALLY
++ * have to.
++ */
++int ipmi_request_supply_msgs(ipmi_user_t user,
++ struct ipmi_addr *addr,
++ long msgid,
++ struct ipmi_msg *msg,
++ void *supplied_smi,
++ struct ipmi_recv_msg *supplied_recv,
++ int priority);
++
++/*
++ * When commands come in to the SMS, the user can register to receive
++ * them. Only one user can be listening on a specific netfn/cmd pair
++ * at a time, you will get an EBUSY error if the command is already
++ * registered. If a command is received that does not have a user
++ * registered, the driver will automatically return the proper
++ * error.
++ */
++int ipmi_register_for_cmd(ipmi_user_t user,
++ unsigned char netfn,
++ unsigned char cmd);
++int ipmi_unregister_for_cmd(ipmi_user_t user,
++ unsigned char netfn,
++ unsigned char cmd);
++
++/*
++ * When the user is created, it will not receive IPMI events by
++ * default. The user must set this to TRUE to get incoming events.
++ * The first user that sets this to TRUE will receive all events that
++ * have been queued while no one was waiting for events.
++ */
++int ipmi_set_gets_events(ipmi_user_t user, int val);
++
++/*
++ * Register the given user to handle all received IPMI commands. This
++ * will fail if anyone is registered as a command receiver or if
++ * another is already registered to receive all commands. NOTE THAT
++ * THIS IS FOR EMULATION USERS ONLY, DO NOT USER THIS FOR NORMAL
++ * STUFF.
++ */
++int ipmi_register_all_cmd_rcvr(ipmi_user_t user);
++int ipmi_unregister_all_cmd_rcvr(ipmi_user_t user);
++
++
++/*
++ * Called when a new SMI is registered. This will also be called on
++ * every existing interface when a new watcher is registered with
++ * ipmi_smi_watcher_register().
++ */
++struct ipmi_smi_watcher
++{
++ struct list_head link;
++
++ /* These two are called with read locks held for the interface
++ the watcher list. So you can add and remove users from the
++ IPMI interface, send messages, etc., but you cannot add
++ or remove SMI watchers or SMI interfaces. */
++ void (*new_smi)(int if_num);
++ void (*smi_gone)(int if_num);
++};
++
++int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher);
++int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher);
++
++/* The following are various helper functions for dealing with IPMI
++ addresses. */
++
++/* Return the maximum length of an IPMI address given it's type. */
++unsigned int ipmi_addr_length(int addr_type);
++
++/* Validate that the given IPMI address is valid. */
++int ipmi_validate_addr(struct ipmi_addr *addr, int len);
++
++/* Return 1 if the given addresses are equal, 0 if not. */
++int ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2);
++
++#endif /* __KERNEL__ */
++
++
++/*
++ * The userland interface
++ */
++
++/*
++ * The userland interface for the IPMI driver is a standard character
++ * device, with each instance of an interface registered as a minor
++ * number under the major character device.
++ *
++ * The read and write calls do not work, to get messages in and out
++ * requires ioctl calls because of the complexity of the data. select
++ * and poll do work, so you can wait for input using the file
++ * descriptor, you just can use read to get it.
++ *
++ * In general, you send a command down to the interface and receive
++ * responses back. You can use the msgid value to correlate commands
++ * and responses, the driver will take care of figuring out which
++ * incoming messages are for which command and find the proper msgid
++ * value to report. You will only receive reponses for commands you
++ * send. Asynchronous events, however, go to all open users, so you
++ * must be ready to handle these (or ignore them if you don't care).
++ *
++ * The address type depends upon the channel type. When talking
++ * directly to the BMC (IPMC_BMC_CHANNEL), the address is ignored
++ * (IPMI_UNUSED_ADDR_TYPE). When talking to an IPMB channel, you must
++ * supply a valid IPMB address with the addr_type set properly.
++ *
++ * When talking to normal channels, the driver takes care of the
++ * details of formatting and sending messages on that channel. You do
++ * not, for instance, have to format a send command, you just send
++ * whatever command you want to the channel, the driver will create
++ * the send command, automatically issue receive command and get even
++ * commands, and pass those up to the proper user.
++ */
++
++
++/* The magic IOCTL value for this interface. */
++#define IPMI_IOC_MAGIC 'i'
++
++
++/* Messages sent to the interface are this format. */
++struct ipmi_req
++{
++ unsigned char *addr; /* Address to send the message to. */
++ unsigned int addr_len;
++
++ long msgid; /* The sequence number for the message. This
++ exact value will be reported back in the
++ response to this request if it is a command.
++ If it is a response, this will be used as
++ the sequence value for the response. */
++
++ struct ipmi_msg msg;
++};
++/*
++ * Send a message to the interfaces. error values are:
++ * - EFAULT - an address supplied was invalid.
++ * - EINVAL - The address supplied was not valid, or the command
++ * was not allowed.
++ * - EMSGSIZE - The message to was too large.
++ * - ENOMEM - Buffers could not be allocated for the command.
++ */
++#define IPMICTL_SEND_COMMAND _IOR(IPMI_IOC_MAGIC, 13, \
++ struct ipmi_req)
++
++/* Messages received from the interface are this format. */
++struct ipmi_recv
++{
++ int recv_type; /* Is this a command, response or an
++ asyncronous event. */
++
++ unsigned char *addr; /* Address the message was from is put
++ here. The caller must supply the
++ memory. */
++ unsigned int addr_len; /* The size of the address buffer.
++ The caller supplies the full buffer
++ length, this value is updated to
++ the actual message length when the
++ message is received. */
++
++ long msgid; /* The sequence number specified in the request
++ if this is a response. If this is a command,
++ this will be the sequence number from the
++ command. */
++
++ struct ipmi_msg msg; /* The data field must point to a buffer.
++ The data_size field must be set to the
++ size of the message buffer. The
++ caller supplies the full buffer
++ length, this value is updated to the
++ actual message length when the message
++ is received. */
++};
++
++/*
++ * Receive a message. error values:
++ * - EAGAIN - no messages in the queue.
++ * - EFAULT - an address supplied was invalid.
++ * - EINVAL - The address supplied was not valid.
++ * - EMSGSIZE - The message to was too large to fit into the message buffer,
++ * the message will be left in the buffer. */
++#define IPMICTL_RECEIVE_MSG _IOWR(IPMI_IOC_MAGIC, 12, \
++ struct ipmi_recv)
++
++/*
++ * Like RECEIVE_MSG, but if the message won't fit in the buffer, it
++ * will truncate the contents instead of leaving the data in the
++ * buffer.
++ */
++#define IPMICTL_RECEIVE_MSG_TRUNC _IOWR(IPMI_IOC_MAGIC, 11, \
++ struct ipmi_recv)
++
++/* Register to get commands from other entities on this interface. */
++struct ipmi_cmdspec
++{
++ unsigned char netfn;
++ unsigned char cmd;
++};
++
++/*
++ * Register to receive a specific command. error values:
++ * - EFAULT - an address supplied was invalid.
++ * - EBUSY - The netfn/cmd supplied was already in use.
++ * - ENOMEM - could not allocate memory for the entry.
++ */
++#define IPMICTL_REGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 14, \
++ struct ipmi_cmdspec)
++/*
++ * Unregister a regsitered command. error values:
++ * - EFAULT - an address supplied was invalid.
++ * - ENOENT - The netfn/cmd was not found registered for this user.
++ */
++#define IPMICTL_UNREGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 15, \
++ struct ipmi_cmdspec)
++
++/*
++ * Set whether this interface receives events. Note that the first
++ * user registered for events will get all pending events for the
++ * interface. error values:
++ * - EFAULT - an address supplied was invalid.
++ */
++#define IPMICTL_SET_GETS_EVENTS_CMD _IOR(IPMI_IOC_MAGIC, 16, int)
++
++/*
++ * Set and get the slave address and LUN that we will use for our
++ * source messages. Note that this affects the interface, not just
++ * this user, so it will affect all users of this interface. This is
++ * so some initialization code can come in and do the OEM-specific
++ * things it takes to determine your address (if not the BMC) and set
++ * it for everyone else. You should probably leave the LUN alone.
++ */
++#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)
++#define IPMICTL_SET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 19, unsigned int)
++#define IPMICTL_GET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 20, unsigned int)
++
++#endif /* __LINUX_IPMI_H */
+--- /dev/null 2002-08-30 19:31:37.000000000 -0400
++++ linux-2.4.18-14/include/linux/ipmi_msgdefs.h 2003-03-27 15:26:22.000000000 -0500
+@@ -0,0 +1,58 @@
++/*
++ * ipmi_smi.h
++ *
++ * MontaVista IPMI system management interface
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __LINUX_IPMI_MSGDEFS_H
++#define __LINUX_IPMI_MSGDEFS_H
++
++/* Various definitions for IPMI messages used by almost everything in
++ the IPMI stack. */
++
++#define IPMI_NETFN_APP_REQUEST 0x06
++#define IPMI_NETFN_APP_RESPONSE 0x07
++
++#define IPMI_BMC_SLAVE_ADDR 0x20
++
++#define IPMI_GET_DEVICE_ID_CMD 0x01
++
++#define IPMI_CLEAR_MSG_FLAGS_CMD 0x30
++#define IPMI_GET_MSG_FLAGS_CMD 0x31
++#define IPMI_SEND_MSG_CMD 0x34
++#define IPMI_GET_MSG_CMD 0x33
++
++#define IPMI_SET_BMC_GLOBAL_ENABLES_CMD 0x2e
++#define IPMI_GET_BMC_GLOBAL_ENABLES_CMD 0x2f
++#define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35
++
++#define IPMI_MAX_MSG_LENGTH 80
++
++#endif /* __LINUX_IPMI_MSGDEFS_H */
+--- /dev/null 2002-08-30 19:31:37.000000000 -0400
++++ linux-2.4.18-14/include/linux/ipmi_smi.h 2003-03-27 15:26:22.000000000 -0500
+@@ -0,0 +1,144 @@
++/*
++ * ipmi_smi.h
++ *
++ * MontaVista IPMI system management interface
++ *
++ * Author: MontaVista Software, Inc.
++ * Corey Minyard <minyard@mvista.com>
++ * source@mvista.com
++ *
++ * Copyright 2002 MontaVista Software Inc.
++ *
++ * 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 SOFTWARE IS PROVIDED ``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 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.
++ *
++ * 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.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __LINUX_IPMI_SMI_H
++#define __LINUX_IPMI_SMI_H
++
++#include <linux/ipmi_msgdefs.h>
++
++/* This files describes the interface for IPMI system management interface
++ drivers to bind into the IPMI message handler. */
++
++/* Structure for the low-level drivers. */
++typedef struct ipmi_smi *ipmi_smi_t;
++
++/*
++ * Messages to/from the lower layer. The smi interface will take one
++ * of these to send. After the send has occurred and a response has
++ * been received, it will report this same data structure back up to
++ * the upper layer. If an error occurs, it should fill in the
++ * response with an error code in the completion code location. When
++ * asyncronous data is received, one of these is allocated, the
++ * data_size is set to zero and the response holds the data from the
++ * get message or get event command that the interface initiated.
++ * Note that it is the interfaces responsibility to detect
++ * asynchronous data and messages and request them from the
++ * interface.
++ */
++struct ipmi_smi_msg
++{
++ struct list_head link;
++
++ long msgid;
++ void *user_data;
++
++ /* If 0, add to the end of the queue. If 1, add to the beginning. */
++ int prio;
++
++ int data_size;
++ unsigned char data[IPMI_MAX_MSG_LENGTH];
++
++ int rsp_size;
++ unsigned char rsp[IPMI_MAX_MSG_LENGTH];
++
++ /* Will be called when the system is done with the message
++ (presumably to free it). */
++ void (*done)(struct ipmi_smi_msg *msg);
++};
++
++struct ipmi_smi_handlers
++{
++ /* Called to enqueue an SMI message to be sent. This
++ operation is not allowed to fail. If an error occurs, it
++ should report back the error in a received message. It may
++ do this in the current call context, since no write locks
++ are held when this is run. If the priority is > 0, the
++ message will go into a high-priority queue and be sent
++ first. Otherwise, it goes into a normal-priority queue. */
++ void (*sender)(void *send_info,
++ struct ipmi_smi_msg *msg,
++ int priority);
++
++ /* Called by the upper layer to request that we try to get
++ events from the BMC we are attached to. */
++ void (*request_events)(void *send_info);
++
++ /* Called when someone is using the interface, so the module can
++ adjust it's use count. Return zero if successful, or an
++ errno if not. */
++ int (*new_user)(void *send_info);
++
++ /* Called when someone is no longer using the interface, so the
++ module can adjust it's use count. */
++ void (*user_left)(void *send_info);
++
++ /* Called when the interface should go into "run to
++ completion" mode. If this call sets the value to true, the
++ interface should make sure that all messages are flushed
++ out and that none are pending, and any new requests are run
++ to completion immediately. */
++ void (*set_run_to_completion)(void *send_info, int run_to_completion);
++};
++
++/* Add a low-level interface to the IPMI driver. */
++int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
++ void *send_info,
++ unsigned char version_major,
++ unsigned char version_minor,
++ ipmi_smi_t *intf);
++
++/*
++ * Remove a low-level interface from the IPMI driver. This will
++ * return an error if the interface is still in use by a user.
++ */
++int ipmi_unregister_smi(ipmi_smi_t intf);
++
++/*
++ * The lower layer reports received messages through this interface.
++ * The data_size should be zero if this is an asyncronous message. If
++ * the lower layer gets an error sending a message, it should format
++ * an error response in the message response.
++ */
++void ipmi_smi_msg_received(ipmi_smi_t intf,
++ struct ipmi_smi_msg *msg);
++
++/* The lower layer received a watchdog pre-timeout on interface. */
++void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf);
++
++struct ipmi_smi_msg *ipmi_alloc_smi_msg(void);
++static inline void ipmi_free_smi_msg(struct ipmi_smi_msg *msg)
++{
++ msg->done(msg);
++}
++
++#endif /* __LINUX_IPMI_SMI_H */
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644
index 0000000..c5c9030
--- /dev/null
+++ b/lib/Makefile
@@ -0,0 +1,73 @@
+#!/bin/sh
+# Makefile to build/install ipmiutil lib files
+#
+# If --enable-lanplus (-DHAVE_LANPLUS), then this script
+# does a make from lib/lanplus/ for the lanplus library.
+# If --enable-landesk (-DLINK_LANDESK), then this script
+# assumes that these files are copied into this lib/ directory:
+# libipmiapi32.a libipmiapi64.a.suse libipmiapi64.a.redhat
+#
+MKDIR = sh ../mkinstalldirs
+INSTALL = sh ../install-sh -c
+INSTALL_DATA = $(INSTALL) -m 644
+INSTALL_SCRIPT = $(INSTALL) -m 755
+INSTALL_BIN = /usr/bin/install -c
+prefix = /usr
+
+datadir = ${prefix}/share
+mandir = ${prefix}/man
+sbindir = ${exec_prefix}/sbin
+libdir = ${exec_prefix}/lib
+datato = ${DESTDIR}${datadir}/ipmiutil
+lib32 = ${DESTDIR}/usr/lib
+lib64 = ${DESTDIR}/usr/lib64
+
+all:
+ if [ -f libipmiapi32.a ]; then \
+ rm -f libipmiapi.a; \
+ if [ "`uname -m`" = "x86_64" ]; then \
+ if [ -f /etc/SuSE-release ]; then \
+ cp -f libipmiapi64.a.suse libipmiapi.a; \
+ else cp -f libipmiapi64.a.redhat libipmiapi.a; fi \
+ else cp -f libipmiapi32.a libipmiapi.a; fi \
+ fi
+ cd lanplus; make clean; make
+ cp -f lanplus/libipmi_lanplus.a .
+ # cp -f lanplus/.libs/libipmi_lanplus.so.0.0.0 libipmi_lanplus.so
+
+clean:
+ rm -f libipmiapi.a lib*_lanplus.a lib*_lanplus.so
+ cd lanplus; make clean
+
+clobber:
+ rm -f libipmiapi.a lib*_lanplus.a lib*_lanplus.so
+ cd lanplus; make clean
+
+distclean:
+ rm -f libipmiapi.a lib*.a lib*_lanplus.so
+ cd lanplus; make distclean
+
+install:
+ $(MKDIR) ${datato}
+ cd lanplus; make install
+
+check:
+
+installso:
+ @if [ -d /usr/lib64 ]; then \
+ $(MKDIR) ${lib64} ; \
+ echo "installing libipmi_lanplus into ${lib64}"; \
+ cd lanplus; /bin/sh ../../libtool --mode=install $(INSTALL_BIN) 'libipmi_lanplus.la' '${lib64}/libipmi_lanplus.la' ; \
+ $(INSTALL_BIN) .libs/libipmi_lanplus.so.0.0.0 ${lib64}/libipmi_lanplus.so.0.0.0 ; \
+ (cd ${lib64} && rm -f libipmi_lanplus.so.0 && ln -s libipmi_lanplus.so.0.0.0 libipmi_lanplus.so.0) ; \
+ (cd ${lib64} && rm -f libipmi_lanplus.so && ln -s libipmi_lanplus.so.0.0.0 libipmi_lanplus.so) ; \
+ $(INSTALL_BIN) .libs/libipmi_lanplus.lai ${lib64}/libipmi_lanplus.la ; \
+ $(INSTALL_BIN) .libs/libipmi_lanplus.a ${lib64}/libipmi_lanplus.a; \
+ ranlib ${lib64}/libipmi_lanplus.a ; \
+ chmod 644 ${lib64}/libipmi_lanplus.a ; \
+ (cd ${lib32} && rm -f libipmi_lanplus.* ); \
+ ../../libtool --finish ${lib64} \
+ fi
+
+# $(INSTALL_DATA) libipmiapi.a ${datato}
+# $(INSTALL_DATA) libintf_lanplus.a ${datato}
diff --git a/lib/ipmilib.mak b/lib/ipmilib.mak
new file mode 100644
index 0000000..a894d3f
--- /dev/null
+++ b/lib/ipmilib.mak
@@ -0,0 +1,37 @@
+# ipmilib.mak
+# This makefile will build the ipmiutil lib directory
+#
+# Make sure to download and build openssl for Windows
+#
+
+# The ipmiutil lib directory
+PLUS_DIR=lanplus
+PLUS_LIB=lanplus.lib
+
+# Set your compiler options
+RM=del
+CP=copy
+
+all: banner $(PLUS_LIB)
+
+banner:
+ @echo Building ipmi libs
+
+$(PLUS_LIB):
+ cd $(PLUS_DIR)
+ nmake /nologo -f ipmiplus.mak all
+ cd ..
+ $(CP) $(PLUS_DIR)\$(PLUS_LIB) .
+
+clean:
+ $(RM) $(PLUS_LIB) 2>NUL
+ cd $(PLUS_DIR)
+ nmake /nologo -f ipmiplus.mak clean
+ cd ..
+
+distclean:
+ $(RM) $(PLUS_LIB) 2>NUL
+ cd $(PLUS_DIR)
+ nmake /nologo -f ipmiplus.mak distclean
+ cd ..
+
diff --git a/lib/lanplus/Makefile.am b/lib/lanplus/Makefile.am
new file mode 100644
index 0000000..c5394b1
--- /dev/null
+++ b/lib/lanplus/Makefile.am
@@ -0,0 +1,55 @@
+# Makefile.am for libipmi_lanplus.so and libipmi_lanplus.a
+
+ODIR = obj
+CFLAGS_STATIC = @OS_CFLAGS@ -DSTATIC -fno-strict-aliasing -fPIC $(CFLAGS)
+AM_CFLAGS = @OS_CFLAGS@ -fPIC @LANPLUS_CFLAGS@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I. -I./inc
+
+lanplus_liba = libipmi_lanplus.a
+
+noinst_LIBRARIES = $(lanplus_liba)
+
+libipmi_lanplus_a_SOURCES = lanplus.c lanplus.h rmcp.h asf.h \
+ lanplus_dump.c lanplus_dump.h \
+ lanplus_crypt.c lanplus_crypt.h \
+ lanplus_crypt_impl.c lanplus_crypt_impl.h \
+ lanplus_strings.c \
+ helper.c ipmi_strings.c
+
+lib_LTLIBRARIES =
+# lib_LTLIBRARIES = libipmi_lanplus.la
+
+# libipmi_lanplus_la_LIBADD = -lcrypto
+
+# libipmi_lanplus_la_SOURCES = lanplus.c lanplus.h rmcp.h asf.h \
+# lanplus_dump.c lanplus_dump.h \
+# lanplus_crypt.c lanplus_crypt.h \
+# lanplus_crypt_impl.c lanplus_crypt_impl.h \
+# lanplus_strings.c \
+# helper.c ipmi_strings.c
+
+
+#am_libipmi_lanplus_a_OBJECTS = $(ODIR)/lanplus.o $(ODIR)/lanplus_strings.o \
+# $(ODIR)/lanplus_crypt.o $(ODIR)/lanplus_crypt_impl.o \
+# $(ODIR)/lanplus_dump.o \
+# $(ODIR)/helper.o $(ODIR)/ipmi_strings.o
+
+clean-generic:
+ rm -rf $(ODIR)
+ rm -f $(lanplus_liba) $(lib_LTLIBRARIES) *.o *.so
+
+clean: clean-generic
+
+#$(lanplus_liba): $(am_libipmi_lanplus_a_OBJECTS)
+# $(AR) cru $(lanplus_liba) $(am_libipmi_lanplus_a_OBJECTS)
+# $(RANLIB) $(lanplus_liba)
+
+#$(ODIR):
+# mkdir -p $(ODIR)
+
+#$(ODIR)/%.o: %.c $(ODIR)
+# $(CC) -c $(CFLAGS_STATIC) $(INCLUDES) -o $@ $<
+
diff --git a/lib/lanplus/Makefile.in b/lib/lanplus/Makefile.in
new file mode 100644
index 0000000..91f0bd7
--- /dev/null
+++ b/lib/lanplus/Makefile.in
@@ -0,0 +1,532 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 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@
+
+# Makefile.am for libipmi_lanplus.so and libipmi_lanplus.a
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+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@
+subdir = lib/lanplus
+DIST_COMMON = README $(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 =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+libipmi_lanplus_a_AR = $(AR) $(ARFLAGS)
+libipmi_lanplus_a_LIBADD =
+am_libipmi_lanplus_a_OBJECTS = lanplus.$(OBJEXT) \
+ lanplus_dump.$(OBJEXT) lanplus_crypt.$(OBJEXT) \
+ lanplus_crypt_impl.$(OBJEXT) lanplus_strings.$(OBJEXT) \
+ helper.$(OBJEXT) ipmi_strings.$(OBJEXT)
+libipmi_lanplus_a_OBJECTS = $(am_libipmi_lanplus_a_OBJECTS)
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libipmi_lanplus_a_SOURCES)
+DIST_SOURCES = $(libipmi_lanplus_a_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+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@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GPL_CFLAGS = @GPL_CFLAGS@
+IA64_CFLAGS = @IA64_CFLAGS@
+INIT_DIR = @INIT_DIR@
+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@
+LDFLAGS = @LDFLAGS@
+LD_SAMX = @LD_SAMX@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_DIR = @LIB_DIR@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+OS_CFLAGS = @OS_CFLAGS@
+OS_DRIVERS = @OS_DRIVERS@
+OS_LFLAGS = @OS_LFLAGS@
+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@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHR_LINK = @SHR_LINK@
+STRIP = @STRIP@
+SUBDIR_S = @SUBDIR_S@
+SYSTEMD_DIR = @SYSTEMD_DIR@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+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@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+ODIR = obj
+CFLAGS_STATIC = @OS_CFLAGS@ -DSTATIC -fno-strict-aliasing -fPIC $(CFLAGS)
+AM_CFLAGS = @OS_CFLAGS@ -fPIC @LANPLUS_CFLAGS@
+MAINTAINERCLEANFILES = Makefile.in
+INCLUDES = -I. -I./inc
+lanplus_liba = libipmi_lanplus.a
+noinst_LIBRARIES = $(lanplus_liba)
+libipmi_lanplus_a_SOURCES = lanplus.c lanplus.h rmcp.h asf.h \
+ lanplus_dump.c lanplus_dump.h \
+ lanplus_crypt.c lanplus_crypt.h \
+ lanplus_crypt_impl.c lanplus_crypt_impl.h \
+ lanplus_strings.c \
+ helper.c ipmi_strings.c
+
+lib_LTLIBRARIES =
+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 \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/lanplus/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign lib/lanplus/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
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libipmi_lanplus.a: $(libipmi_lanplus_a_OBJECTS) $(libipmi_lanplus_a_DEPENDENCIES)
+ -rm -f libipmi_lanplus.a
+ $(libipmi_lanplus_a_AR) libipmi_lanplus.a $(libipmi_lanplus_a_OBJECTS) $(libipmi_lanplus_a_LIBADD)
+ $(RANLIB) libipmi_lanplus.a
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helper.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_strings.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lanplus.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lanplus_crypt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lanplus_crypt_impl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lanplus_dump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lanplus_strings.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@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@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@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@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@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
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+
+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; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ 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; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ 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; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && 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)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$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 $(LIBRARIES) $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)"; 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)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+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-info-am uninstall-libLTLIBRARIES
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool clean-noinstLIBRARIES ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-exec install-exec-am install-info \
+ install-info-am install-libLTLIBRARIES install-man \
+ 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-info-am uninstall-libLTLIBRARIES
+
+# lib_LTLIBRARIES = libipmi_lanplus.la
+
+# libipmi_lanplus_la_LIBADD = -lcrypto
+
+# libipmi_lanplus_la_SOURCES = lanplus.c lanplus.h rmcp.h asf.h \
+# lanplus_dump.c lanplus_dump.h \
+# lanplus_crypt.c lanplus_crypt.h \
+# lanplus_crypt_impl.c lanplus_crypt_impl.h \
+# lanplus_strings.c \
+# helper.c ipmi_strings.c
+
+#am_libipmi_lanplus_a_OBJECTS = $(ODIR)/lanplus.o $(ODIR)/lanplus_strings.o \
+# $(ODIR)/lanplus_crypt.o $(ODIR)/lanplus_crypt_impl.o \
+# $(ODIR)/lanplus_dump.o \
+# $(ODIR)/helper.o $(ODIR)/ipmi_strings.o
+
+clean-generic:
+ rm -rf $(ODIR)
+ rm -f $(lanplus_liba) $(lib_LTLIBRARIES) *.o *.so
+
+clean: clean-generic
+
+#$(lanplus_liba): $(am_libipmi_lanplus_a_OBJECTS)
+# $(AR) cru $(lanplus_liba) $(am_libipmi_lanplus_a_OBJECTS)
+# $(RANLIB) $(lanplus_liba)
+
+#$(ODIR):
+# mkdir -p $(ODIR)
+
+#$(ODIR)/%.o: %.c $(ODIR)
+# $(CC) -c $(CFLAGS_STATIC) $(INCLUDES) -o $@ $<
+# 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:
diff --git a/lib/lanplus/README b/lib/lanplus/README
new file mode 100644
index 0000000..8a155e6
--- /dev/null
+++ b/lib/lanplus/README
@@ -0,0 +1,19 @@
+ipmitool/plugins/lanplus for ipmiutil
+
+lib/lanplus directory
+
+This contains the lanplus plugin source from the ipmitool project,
+which supports IPMI LAN 2.0 RMCP+ protocol.
+This is a slightly modified version from ipmitool-1.8.8.90 with changes
+to link better with ipmiutil and changes for WIN32.
+
+See http://ipmitool.sourceforge.net for the latest version of lanplus,
+then apply the iutil.diff patch to make it compatible with ipmiutil.
+
+This builds a lanplus library that is used by ipmiutil, along with
+the crypto libraries from openssl (see openssl.org).
+
+The util/ipmilanplus.c code in ipmiutil calls the lanplus routines,
+if the HAVE_LANPLUS compile flag is defined.
+
+
diff --git a/lib/lanplus/asf.h b/lib/lanplus/asf.h
new file mode 100644
index 0000000..acf5553
--- /dev/null
+++ b/lib/lanplus/asf.h
@@ -0,0 +1,82 @@
+/*
+ * 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_ASF_H
+#define IPMI_ASF_H
+
+#include <ipmitool/helper.h>
+#include "lanplus.h"
+
+#define ASF_RMCP_IANA 0x000011be
+
+#define ASF_TYPE_PING 0x80
+#define ASF_TYPE_PONG 0x40
+
+static const struct valstr asf_type_vals[] __attribute__((unused)) = {
+ { 0x10, "Reset" },
+ { 0x11, "Power-up" },
+ { 0x12, "Unconditional Power-down" },
+ { 0x13, "Power Cycle" },
+ { 0x40, "Presence Pong" },
+ { 0x41, "Capabilities Response" },
+ { 0x42, "System State Response" },
+ { 0x80, "Presence Ping" },
+ { 0x81, "Capabilities Request" },
+ { 0x82, "System State Request" },
+ { 0x00, NULL }
+};
+
+/* ASF message header */
+#ifdef GCC_42
+struct asf_hdr {
+ uint32_t iana;
+ uint8_t type;
+ uint8_t tag;
+ uint8_t reserved;
+ uint8_t len;
+} __attribute__((packed));
+#else
+/* pragma pack works in gcc-4.3 */
+#pragma pack(1)
+struct asf_hdr {
+ uint32_t iana;
+ uint8_t type;
+ uint8_t tag;
+ uint8_t reserved;
+ uint8_t len;
+};
+#pragma pack()
+#endif
+
+int handle_asf(struct ipmi_intf * intf, uint8_t * data, int data_len);
+
+#endif /* IPMI_ASF_H */
diff --git a/lib/lanplus/helper.c b/lib/lanplus/helper.c
new file mode 100644
index 0000000..51e39c8
--- /dev/null
+++ b/lib/lanplus/helper.c
@@ -0,0 +1,480 @@
+/*
+ * 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 <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <io.h>
+#include <signal.h>
+#include <inttypes-win.h>
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h> /* For TIOCNOTTY */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#endif
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#else
+#define _PATH_VARRUN "/var/run/"
+#define _PATH_TTY "/dev/tty"
+#endif
+
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_intf.h>
+#include <ipmitool/helper.h>
+#include <ipmitool/log.h>
+
+extern int verbose;
+
+#ifdef MOVED
+/* moved to subs.c */
+uint32_t buf2long(uint8_t * buf)
+{
+ return (uint32_t)(buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]);
+}
+
+uint16_t buf2short(uint8_t * buf)
+{
+ return (uint16_t)(buf[1] << 8 | buf[0]);
+}
+
+const char * buf2str(uint8_t * buf, int len)
+{
+ static char str[1024];
+ int i;
+
+ if (len <= 0 || len > 1024)
+ return NULL;
+
+ memset(str, 0, 1024);
+
+ for (i=0; i<len; i++)
+ sprintf(str+i+i, "%2.2x", buf[i]);
+
+ str[len*2] = '\0';
+
+ return (const char *)str;
+}
+
+/* moved to util/ipmilanplus.c for better control */
+#ifdef STATIC
+extern FILE *fplog; /*see util/ipmicmd.c ++++*/
+#endif
+void printbuf(const uint8_t * buf, int len, const char * desc)
+{
+ int i;
+ FILE *fp = stderr;
+
+ if (len <= 0) return;
+ if (verbose < 1) return;
+#ifdef STATIC
+ if (fplog != NULL) fp = fplog; /*++++*/
+#endif
+ fprintf(fp, "%s (%d bytes)\r\n", desc, len);
+ for (i=0; i<len; i++) {
+ if (((i%16) == 0) && (i != 0))
+ fprintf(fp, "\r\n");
+ fprintf(fp, " %2.2x", buf[i]);
+ }
+ fprintf(fp, "\r\n");
+}
+
+const char * val2str(uint16_t 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;
+}
+
+const char * oemval2str(uint16_t oem, uint16_t val,
+ const struct oemvalstr *vs)
+{
+ static char un_str[32];
+ int i;
+
+ for (i = 0; vs[i].oem != 0x00 && vs[i].str != NULL; i++) {
+ /* FIXME: for now on we assume PICMG capability on all IANAs */
+ if
+ (
+ (
+ vs[i].oem == oem
+ ||
+ vs[i].oem == IPMI_OEM_PICMG
+ )
+ &&
+ vs[i].val == val
+ )
+ {
+ return vs[i].str;
+ }
+ }
+
+ memset(un_str, 0, 32);
+ snprintf(un_str, 32, "OEM reserved #%02x", val);
+
+ return un_str;
+}
+
+uint16_t str2val(const char *str, const struct valstr *vs)
+{
+ int i;
+
+ for (i = 0; vs[i].str != NULL; i++) {
+ if (strcasecmp(vs[i].str, str) == 0)
+ return vs[i].val;
+ }
+
+ return vs[i].val;
+}
+#else
+uint32_t buf2long(uint8_t * buf);
+uint16_t buf2short(uint8_t * buf);
+const char * buf2str(uint8_t * buf, int len);
+void printbuf(const uint8_t * buf, int len, const char * desc);
+const char * val2str(uint16_t val, const struct valstr *vs);
+const char * oemval2str(uint16_t oem, uint16_t val,
+ const struct oemvalstr *vs);
+uint16_t str2val(const char *str, const struct valstr *vs);
+#endif
+
+/* print_valstr - print value string list to log or stdout
+ *
+ * @vs: value string list to print
+ * @title: name of this value string list
+ * @loglevel: what log level to print, -1 for stdout
+ */
+void
+print_valstr(const struct valstr * vs, const char * title, int loglevel)
+{
+ int i;
+
+ if (vs == NULL)
+ return;
+
+ if (title != NULL) {
+ if (loglevel < 0)
+ printf("\n%s:\n\n", title);
+ else
+ lprintf(loglevel, "\n%s:\n", title);
+ }
+
+ if (loglevel < 0) {
+ printf(" VALUE\tHEX\tSTRING\n");
+ printf("==============================================\n");
+ } else {
+ lprintf(loglevel, " VAL\tHEX\tSTRING");
+ lprintf(loglevel, "==============================================");
+ }
+
+ for (i = 0; vs[i].str != NULL; i++) {
+ if (loglevel < 0) {
+ if (vs[i].val < 256)
+ printf(" %d\t0x%02x\t%s\n", vs[i].val, vs[i].val, vs[i].str);
+ else
+ printf(" %d\t0x%04x\t%s\n", vs[i].val, vs[i].val, vs[i].str);
+ } else {
+ if (vs[i].val < 256)
+ lprintf(loglevel, " %d\t0x%02x\t%s", vs[i].val, vs[i].val, vs[i].str);
+ else
+ lprintf(loglevel, " %d\t0x%04x\t%s", vs[i].val, vs[i].val, vs[i].str);
+ }
+ }
+
+ if (loglevel < 0)
+ printf("\n");
+ else
+ lprintf(loglevel, "");
+}
+
+/* print_valstr_2col - print value string list in two columns to log or stdout
+ *
+ * @vs: value string list to print
+ * @title: name of this value string list
+ * @loglevel: what log level to print, -1 for stdout
+ */
+void
+print_valstr_2col(const struct valstr * vs, const char * title, int loglevel)
+{
+ int i;
+
+ if (vs == NULL)
+ return;
+
+ if (title != NULL) {
+ if (loglevel < 0)
+ printf("\n%s:\n\n", title);
+ else
+ lprintf(loglevel, "\n%s:\n", title);
+ }
+
+ for (i = 0; vs[i].str != NULL; i++) {
+ if (vs[i+1].str == NULL) {
+ /* last one */
+ if (loglevel < 0) {
+ printf(" %4d %-32s\n", vs[i].val, vs[i].str);
+ } else {
+ lprintf(loglevel, " %4d %-32s\n", vs[i].val, vs[i].str);
+ }
+ }
+ else {
+ if (loglevel < 0) {
+ printf(" %4d %-32s %4d %-32s\n",
+ vs[i].val, vs[i].str, vs[i+1].val, vs[i+1].str);
+ } else {
+ lprintf(loglevel, " %4d %-32s %4d %-32s\n",
+ vs[i].val, vs[i].str, vs[i+1].val, vs[i+1].str);
+ }
+ i++;
+ }
+ }
+
+ if (loglevel < 0)
+ printf("\n");
+ else
+ lprintf(loglevel, "");
+}
+
+/* ipmi_csum - calculate an ipmi checksum
+ *
+ * @d: buffer to check
+ * @s: position in buffer to start checksum from
+ */
+uint8_t
+ipmi_csum(uint8_t * d, int s)
+{
+ uint8_t c = 0;
+ for (; s > 0; s--, d++)
+ c += *d;
+ return -c;
+}
+
+/* ipmi_open_file - safely open a file for reading or writing
+ *
+ * @file: filename
+ * @rw: read-write flag, 1=write
+ *
+ * returns pointer to file handler on success
+ * returns NULL on error
+ */
+FILE *
+ipmi_open_file(const char * file, int rw)
+{
+#ifndef WIN32
+ struct stat st1, st2;
+#endif
+ FILE * fp;
+
+ /* verify existence */
+#ifdef WIN32
+ if (1 == 0)
+#else
+ if (lstat(file, &st1) < 0)
+#endif
+ {
+ if (rw) {
+ /* does not exist, ok to create */
+ fp = fopen(file, "w");
+ if (fp == NULL) {
+ lperror(LOG_ERR, "Unable to open file %s "
+ "for write", file);
+ return NULL;
+ }
+ /* created ok, now return the descriptor */
+ return fp;
+ } else {
+ lprintf(LOG_ERR, "File %s does not exist", file);
+ return NULL;
+ }
+ }
+
+#ifndef ENABLE_FILE_SECURITY
+ if (!rw) {
+ /* on read skip the extra checks */
+ fp = fopen(file, "r");
+ if (fp == NULL) {
+ lperror(LOG_ERR, "Unable to open file %s", file);
+ return NULL;
+ }
+ return fp;
+ }
+#endif
+
+#ifndef WIN32
+ /* it exists - only regular files, not links */
+ if (S_ISREG(st1.st_mode) == 0) {
+ lprintf(LOG_ERR, "File %s has invalid mode: %d",
+ file, st1.st_mode);
+ return NULL;
+ }
+
+ /* allow only files with 1 link (itself) */
+ if (st1.st_nlink != 1) {
+ lprintf(LOG_ERR, "File %s has invalid link count: %d != 1",
+ file, (int)st1.st_nlink);
+ return NULL;
+ }
+#endif
+
+ fp = fopen(file, rw ? "w+" : "r");
+ if (fp == NULL) {
+ lperror(LOG_ERR, "Unable to open file %s", file);
+ return NULL;
+ }
+
+#ifndef WIN32
+ /* stat again */
+ if (fstat(fileno(fp), &st2) < 0) {
+ lperror(LOG_ERR, "Unable to stat file %s", file);
+ fclose(fp);
+ return NULL;
+ }
+
+ /* verify inode */
+ if (st1.st_ino != st2.st_ino) {
+ lprintf(LOG_ERR, "File %s has invalid inode: %d != %d",
+ file, st1.st_ino, st2.st_ino);
+ fclose(fp);
+ return NULL;
+ }
+
+ /* verify owner */
+ if (st1.st_uid != st2.st_uid) {
+ lprintf(LOG_ERR, "File %s has invalid user id: %d != %d",
+ file, st1.st_uid, st2.st_uid);
+ fclose(fp);
+ return NULL;
+ }
+
+ /* verify inode */
+ if (st2.st_nlink != 1) {
+ lprintf(LOG_ERR, "File %s has invalid link count: %d != 1",
+ file, st2.st_nlink);
+ fclose(fp);
+ return NULL;
+ }
+#endif
+
+ return fp;
+}
+
+void
+ipmi_start_daemon(struct ipmi_intf *intf)
+{
+#ifndef WIN32
+ pid_t pid;
+ int fd, i;
+#ifdef SIGHUP
+ sigset_t sighup;
+#endif
+
+ /* if we are started from init no need to become daemon */
+ if (getppid() == 1)
+ return;
+
+#ifdef SIGHUP
+ sigemptyset(&sighup);
+ sigaddset(&sighup, SIGHUP);
+ if (sigprocmask(SIG_UNBLOCK, &sighup, NULL) < 0)
+ fprintf(stderr, "ERROR: could not unblock SIGHUP signal\n");
+ signal(SIGHUP, SIG_IGN);
+#endif
+#ifdef SIGTTOU
+ signal(SIGTTOU, SIG_IGN);
+#endif
+#ifdef SIGTTIN
+ signal(SIGTTIN, SIG_IGN);
+#endif
+#ifdef SIGQUIT
+ signal(SIGQUIT, SIG_IGN);
+#endif
+#ifdef SIGTSTP
+ signal(SIGTSTP, SIG_IGN);
+#endif
+
+ pid = (pid_t) fork();
+ if (pid < 0 || pid > 0)
+ exit(0);
+
+#if defined(SIGTSTP) && defined(TIOCNOTTY)
+ if (setpgid(0, getpid()) == -1)
+ exit(1);
+ if ((fd = open(_PATH_TTY, O_RDWR)) >= 0) {
+ ioctl(fd, TIOCNOTTY, NULL);
+ close(fd);
+ }
+#else
+ if (setpgid(0, 0) == -1)
+ exit(1);
+ pid = (pid_t) fork();
+ if (pid < 0 || pid > 0)
+ exit(0);
+#endif
+
+ i = chdir("/");
+ umask(0);
+
+ for (fd=0; fd<64; fd++) {
+ if (fd != intf->fd)
+ close(fd);
+ }
+
+ fd = open("/dev/null", O_RDWR);
+ i = dup(0);
+ i = dup(0);
+#endif
+}
diff --git a/lib/lanplus/inc/config.h b/lib/lanplus/inc/config.h
new file mode 100644
index 0000000..4ae9ee6
--- /dev/null
+++ b/lib/lanplus/inc/config.h
@@ -0,0 +1,144 @@
+/* config.h. Generated by configure. */
+/* config.h.in. Generated from configure.in by autoheader. */
+/* Define to 1 to enable all command line options. */
+#define ENABLE_ALL_OPTIONS 1
+/* Define to 1 for extra file security. */
+/* #undef ENABLE_FILE_SECURITY */
+/* Define to 1 if you have the `alarm' function. */
+#define HAVE_ALARM 1
+#ifdef WIN32
+#undef HAVE_ARPA_INET_H
+#undef HAVE_BYTESWAP_H
+#else
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+/* Define to 1 if you have the <byteswap.h> header file. */
+#define HAVE_BYTESWAP_H 1
+#endif
+/* Define to 1 if libcrypto supports MD2. */
+#define HAVE_CRYPTO_MD2 1
+/* Define to 1 if libcrypto supports MD5. */
+#define HAVE_CRYPTO_MD5 1
+#ifdef WIN32
+#undef HAVE_DLFCN_H
+#undef HAVE_FCNTL_H
+#undef HAVE_INTTYPES_H
+#undef HAVE_NETDB_H
+#undef HAVE_NETINET_IN_H
+#undef HAVE_SYS_IOCTL_H
+#undef HAVE_OPENIPMI_H
+#else
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+/* Define to 1 if you have the <sys/ipmi.h> header file. */
+/* #undef HAVE_FREEBSD_IPMI_H */
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+/* Define to 1 if you have the <linux/ipmi.h> header file. */
+#define HAVE_OPENIPMI_H 1
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+#endif
+/* Define to 1 if you have the `gethostbyname' function. */
+#define HAVE_GETHOSTBYNAME 1
+/* Define to 1 if you have the `getpassphrase' function. */
+/* #undef HAVE_GETPASSPHRASE */
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+ to 0 otherwise. */
+#define HAVE_MALLOC 1
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+/* Define to 1 if you have the <paths.h> header file. */
+#define HAVE_PATHS_H 1
+/* Define to 1 if readline present. */
+#define HAVE_READLINE 1
+/* Define to 1 if you have the `select' function. */
+#define HAVE_SELECT 1
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+/* Define to 1 if you have the <sys/byteorder.h> header file. */
+/* #undef HAVE_SYS_BYTEORDER_H */
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+/* Define to 1 if you have <sys/termios.h>. */
+/* #undef HAVE_SYS_TERMIOS_H */
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+/* Define to 1 if you have <termios.h>. */
+#define HAVE_TERMIOS_H 1
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+/* Define to 1 to enable Solaris 10 BMC interface. */
+/* #undef IPMI_INTF_BMC */
+/* Define to 1 to enable Intel IMB interface. */
+/* #undef IPMI_INTF_IMB, or #define IPMI_INTF_IMB 1 */
+/* Define to 1 to enable LAN IPMIv1.5 interface. */
+// #define IPMI_INTF_LAN 1
+/* Define to 1 to enable LAN+ IPMIv2 interface. */
+#define IPMI_INTF_LANPLUS 1
+/* Define to 1 to enable Solaris 9 LIPMI interface. */
+/* #undef IPMI_INTF_LIPMI */
+/* Define to 1 to enable Linux OpenIPMI interface. */
+// #define IPMI_INTF_OPEN 1
+/* Name of package */
+#define PACKAGE "ipmitool"
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+/* Define to the full name of this package. */
+#define PACKAGE_NAME ""
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING ""
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME ""
+/* Define to the version of this package. */
+#define PACKAGE_VERSION ""
+/* Define to the type of arg 1 for `select'. */
+#define SELECT_TYPE_ARG1 int
+/* Define to the type of args 2, 3 and 4 for `select'. */
+#define SELECT_TYPE_ARG234 (fd_set *)
+/* Define to the type of arg 5 for `select'. */
+#define SELECT_TYPE_ARG5 (struct timeval *)
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+/* Version number of package */
+#define VERSION "1.8.7"
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+/* Define to rpl_malloc if the replacement function should be used. */
+/* #undef malloc */
diff --git a/lib/lanplus/inc/inttypes-win.h b/lib/lanplus/inc/inttypes-win.h
new file mode 100644
index 0000000..a049a3c
--- /dev/null
+++ b/lib/lanplus/inc/inttypes-win.h
@@ -0,0 +1,30 @@
+/*
+ * inttypes.h
+ *
+ */
+#ifdef WIN32
+
+#ifndef INTTYPES_WIN
+#define INTTYPES_WIN
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+/*
+#if __WORDSIZE == 64
+typedef unsigned long int uint64_t;
+#else
+typedef unsigned long long uint64_t;
+#endif
+*/
+typedef uint32_t socklen_t;
+
+#ifndef __attribute__
+#define __attribute__(Spec) /*empty*/
+#endif
+#endif
+
+#else
+/* Linux */
+#include <inttypes.h>
+#endif
+/* end of inttypes.h */
diff --git a/lib/lanplus/inc/ipmitool/bswap.h b/lib/lanplus/inc/ipmitool/bswap.h
new file mode 100644
index 0000000..9948208
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/bswap.h
@@ -0,0 +1,53 @@
+/*
+ * 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_BSWAP_H
+#define IPMI_BSWAP_H
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#undef BSWAP_16
+#undef BSWAP_32
+
+#if HAVE_BYTESWAP_H
+# include <byteswap.h>
+# define BSWAP_16(x) bswap_16(x)
+# define BSWAP_32(x) bswap_32(x)
+#else
+# define BSWAP_16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8))
+# define BSWAP_32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) |\
+ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
+#endif
+
+#endif /* IPMI_BSWAP_H */
diff --git a/lib/lanplus/inc/ipmitool/helper.h b/lib/lanplus/inc/ipmitool/helper.h
new file mode 100644
index 0000000..7f8a06e
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/helper.h
@@ -0,0 +1,102 @@
+/*
+ * 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_HELPER_H
+#define IPMI_HELPER_H
+
+#ifdef WIN32
+#include <inttypes-win.h>
+#include <stdio.h>
+#include <string.h>
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+#define strncasecmp strnicmp
+#define strcasecmp _stricmp
+// #define strcasecmp stricmp
+// extern int stricmp(const char *__s1, const char *__s2);
+#else
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#endif
+
+
+struct ipmi_intf;
+
+struct valstr {
+ uint16_t val;
+ const char * str;
+};
+struct oemvalstr {
+ uint16_t oem;
+ uint16_t val;
+ const char * str;
+};
+
+const char * val2str(uint16_t val, const struct valstr * vs);
+const char * oemval2str(uint16_t oem,uint16_t val, const struct oemvalstr * vs);
+uint16_t str2val(const char * str, const struct valstr * vs);
+void print_valstr(const struct valstr * vs, const char * title, int loglevel);
+void print_valstr_2col(const struct valstr * vs, const char * title, int loglevel);
+
+
+uint16_t buf2short(uint8_t * buf);
+uint32_t buf2long(uint8_t * buf);
+const char * buf2str(uint8_t * buf, int len);
+void printbuf(const uint8_t * buf, int len, const char * desc);
+uint8_t ipmi_csum(uint8_t * d, int s);
+FILE * ipmi_open_file(const char * file, int rw);
+void ipmi_start_daemon(struct ipmi_intf *intf);
+
+#define ipmi_open_file_read(file) ipmi_open_file(file, 0)
+#define ipmi_open_file_write(file) ipmi_open_file(file, 1)
+
+#ifndef WIN32
+#ifndef __min
+# define __min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef __max
+# define __max(a, b) ((a) > (b) ? (a) : (b))
+#endif
+#endif
+
+#ifndef __minlen
+# define __minlen(a, b) ({ int x=strlen(a); int y=strlen(b); (x < y) ? x : y;})
+#endif
+
+#ifndef __maxlen
+# define __maxlen(a, b) ({ int x=strlen(a); int y=strlen(b); (x > y) ? x : y;})
+#endif
+
+#endif /* IPMI_HELPER_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi.h b/lib/lanplus/inc/ipmitool/ipmi.h
new file mode 100644
index 0000000..39f3514
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi.h
@@ -0,0 +1,267 @@
+/*
+ * 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_H
+#define IPMI_H
+
+#ifdef WIN32
+#include <stdio.h>
+#include <inttypes-win.h>
+#include <ipmitool/helper.h>
+#include <ipmitool/ipmi_cc.h>
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <ipmitool/helper.h>
+#include <ipmitool/ipmi_cc.h>
+#endif
+
+#include <openssl/evp.h>
+
+#define IPMI_BUF_SIZE 1024
+
+/* From table 13.16 of the IPMI v2 specification */
+#define IPMI_PAYLOAD_TYPE_IPMI 0x00
+#define IPMI_PAYLOAD_TYPE_SOL 0x01
+#define IPMI_PAYLOAD_TYPE_OEM 0x02
+#define IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST 0x10
+#define IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE 0x11
+#define IPMI_PAYLOAD_TYPE_RAKP_1 0x12
+#define IPMI_PAYLOAD_TYPE_RAKP_2 0x13
+#define IPMI_PAYLOAD_TYPE_RAKP_3 0x14
+#define IPMI_PAYLOAD_TYPE_RAKP_4 0x15
+
+extern int verbose;
+extern int csv_output;
+
+#ifndef _IPMI_RQ_
+#define _IPMI_RQ_
+struct ipmi_rq {
+ struct {
+ uint8_t netfn:6;
+ uint8_t lun:2;
+ uint8_t cmd;
+ uint8_t target_cmd;
+ uint16_t data_len;
+ uint8_t *data;
+ } msg;
+};
+#endif
+
+/*
+ * This is what the sendrcv_v2() function would take as an argument. The common case
+ * is for payload_type to be IPMI_PAYLOAD_TYPE_IPMI.
+ */
+struct ipmi_v2_payload {
+ uint16_t payload_length;
+ uint8_t payload_type;
+
+ union {
+
+ struct {
+ uint8_t rq_seq;
+ struct ipmi_rq *request;
+ } ipmi_request;
+
+ struct {
+ uint8_t rs_seq;
+ struct ipmi_rs *response;
+ } ipmi_response;
+
+ /* Only used internally by the lanplus interface */
+ struct {
+ uint8_t *request;
+ } open_session_request;
+
+ /* Only used internally by the lanplus interface */
+ struct {
+ uint8_t *message;
+ } rakp_1_message;
+
+ /* Only used internally by the lanplus interface */
+ struct {
+ uint8_t *message;
+ } rakp_2_message;
+
+ /* Only used internally by the lanplus interface */
+ struct {
+ uint8_t *message;
+ } rakp_3_message;
+
+ /* Only used internally by the lanplus interface */
+ struct {
+ uint8_t *message;
+ } rakp_4_message;
+
+ struct {
+ uint8_t data[IPMI_BUF_SIZE];
+ uint16_t character_count;
+ uint8_t packet_sequence_number;
+ uint8_t acked_packet_number;
+ uint8_t accepted_character_count;
+ uint8_t is_nack; /* bool */
+ uint8_t assert_ring_wor; /* bool */
+ uint8_t generate_break; /* bool */
+ uint8_t deassert_cts; /* bool */
+ uint8_t deassert_dcd_dsr; /* bool */
+ uint8_t flush_inbound; /* bool */
+ uint8_t flush_outbound; /* bool */
+ } sol_packet;
+
+ } payload;
+};
+
+struct ipmi_rq_entry {
+ struct ipmi_rq req;
+ struct ipmi_intf *intf;
+ uint8_t rq_seq;
+ uint8_t *msg_data;
+ int msg_len;
+ struct ipmi_rq_entry *next;
+};
+
+struct ipmi_rs {
+ uint8_t ccode;
+ uint8_t data[IPMI_BUF_SIZE];
+
+ /*
+ * Looks like this is the length of the entire packet, including the RMCP
+ * stuff, then modified to be the length of the extra IPMI message data
+ */
+ int data_len;
+
+ struct {
+ uint8_t netfn;
+ uint8_t cmd;
+ uint8_t seq;
+ uint8_t lun;
+ } msg;
+
+ struct {
+ uint8_t authtype;
+ uint32_t seq;
+ uint32_t id;
+ uint8_t bEncrypted; /* IPMI v2 only */
+ uint8_t bAuthenticated; /* IPMI v2 only */
+ uint8_t payloadtype; /* IPMI v2 only */
+ /* This is the total length of the payload or
+ IPMI message. IPMI v2.0 requires this to
+ be 2 bytes. Not really used for much. */
+ uint16_t msglen;
+ } session;
+
+ /*
+ * A union of the different possible payload meta-data
+ */
+ union {
+ struct {
+ uint8_t rq_addr;
+ uint8_t netfn;
+ uint8_t rq_lun;
+ uint8_t rs_addr;
+ uint8_t rq_seq;
+ uint8_t rs_lun;
+ uint8_t cmd;
+ } ipmi_response;
+ struct {
+ uint8_t message_tag;
+ uint8_t rakp_return_code;
+ uint8_t max_priv_level;
+ uint32_t console_id;
+ uint32_t bmc_id;
+ uint8_t auth_alg;
+ uint8_t integrity_alg;
+ uint8_t crypt_alg;
+ } open_session_response;
+ struct {
+ uint8_t message_tag;
+ uint8_t rakp_return_code;
+ uint32_t console_id;
+ uint8_t bmc_rand[16]; /* Random number generated by the BMC */
+ uint8_t bmc_guid[16];
+ uint8_t key_exchange_auth_code[EVP_MAX_MD_SIZE];
+ } rakp2_message;
+ struct {
+ uint8_t message_tag;
+ uint8_t rakp_return_code;
+ uint32_t console_id;
+ uint8_t integrity_check_value[EVP_MAX_MD_SIZE];
+ } rakp4_message;
+ struct {
+ uint8_t packet_sequence_number;
+ uint8_t acked_packet_number;
+ uint8_t accepted_character_count;
+ uint8_t is_nack; /* bool */
+ uint8_t transfer_unavailable; /* bool */
+ uint8_t sol_inactive; /* bool */
+ uint8_t transmit_overrun; /* bool */
+ uint8_t break_detected; /* bool */
+ } sol_packet;
+
+ } payload;
+};
+
+#define IPMI_NETFN_CHASSIS 0x0
+#define IPMI_NETFN_BRIDGE 0x2
+#define IPMI_NETFN_SE 0x4
+#define IPMI_NETFN_APP 0x6
+#define IPMI_NETFN_FIRMWARE 0x8
+#define IPMI_NETFN_STORAGE 0xa
+#define IPMI_NETFN_TRANSPORT 0xc
+#define IPMI_NETFN_PICMG 0x2C
+#define IPMI_NETFN_ISOL 0x34
+#define IPMI_NETFN_TSOL 0x30
+
+#define IPMI_BMC_SLAVE_ADDR 0x20
+#define IPMI_REMOTE_SWID 0x81
+
+
+/* These values are IANA numbers */
+typedef enum IPMI_OEM {
+ IPMI_OEM_UNKNOWN = 0,
+ IPMI_OEM_SUN = 42,
+ IPMI_OEM_NOKIA = 94,
+ IPMI_OEM_INTEL = 343,
+ IPMI_OEM_TYAN = 6653,
+ IPMI_OEM_NEWISYS = 9237,
+ IPMI_OEM_SUPERMICRO = 10876,
+ IPMI_OEM_GOOGLE = 11129,
+ IPMI_OEM_PICMG = 12634,
+ IPMI_OEM_KONTRON = 15000,
+} IPMI_OEM;
+
+extern const struct valstr completion_code_vals[];
+
+#endif /* IPMI_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_cc.h b/lib/lanplus/inc/ipmitool/ipmi_cc.h
new file mode 100644
index 0000000..237b1ee
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_cc.h
@@ -0,0 +1,76 @@
+/*
+ * 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_CC_H
+#define IPMI_CC_H
+
+/*
+ Thu Jan 11 09:32:41 2007
+ francois.isabelle@ca.kontron.com
+
+ I just noticed that most modules refer to IPMI completion codes using
+ hard coded values ...
+*/
+
+/*
+ * CC
+ * See IPMI specification table 5-2 Generic Completion Codes
+ */
+
+#define IPMI_CC_OK 0x00
+#define IPMI_CC_NODE_BUSY 0xc0
+#define IPMI_CC_INV_CMD 0xc1
+#define IPMI_CC_INV_CMD_FOR_LUN 0xc2
+#define IPMI_CC_TIMEOUT 0xc3
+#define IPMI_CC_OUT_OF_SPACE 0xc4
+#define IPMI_CC_RES_CANCELED 0xc5
+#define IPMI_CC_REQ_DATA_TRUNC 0xc6
+#define IPMI_CC_REQ_DATA_INV_LENGTH 0xc7
+#define IPMI_CC_REQ_DATA_FIELD_EXCEED 0xc8
+#define IPMI_CC_PARAM_OUT_OF_RANGE 0xc9
+#define IPMI_CC_CANT_RET_NUM_REQ_BYTES 0xca
+#define IPMI_CC_REQ_DATA_NOT_PRESENT 0xcb
+#define IPMI_CC_INV_DATA_FIELD_IN_REQ 0xcc
+#define IPMI_CC_ILL_SENSOR_OR_RECORD 0xcd
+#define IPMI_CC_RESP_COULD_NOT_BE_PRV 0xce
+#define IPMI_CC_CANT_RESP_DUPLI_REQ 0xcf
+#define IPMI_CC_CANT_RESP_SDRR_UPDATE 0xd0
+#define IPMI_CC_CANT_RESP_FIRM_UPDATE 0xd1
+#define IPMI_CC_CANT_RESP_BMC_INIT 0xd2
+#define IPMI_CC_DESTINATION_UNAVAILABLE 0xd3
+#define IPMI_CC_INSUFFICIENT_PRIVILEGES 0xd4
+#define IPMI_CC_NOT_SUPPORTED_PRESENT_STATE 0xd5
+#define IPMI_CC_ILLEGAL_COMMAND_DISABLED 0xd6
+#define IPMI_CC_UNSPECIFIED_ERROR 0xff
+
+
+#endif /*IPMI_CC_H*/
diff --git a/lib/lanplus/inc/ipmitool/ipmi_channel.h b/lib/lanplus/inc/ipmitool/ipmi_channel.h
new file mode 100644
index 0000000..00fda96
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_channel.h
@@ -0,0 +1,229 @@
+/*
+ * 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_CHANNEL_H
+#define IPMI_CHANNEL_H
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <ipmitool/ipmi.h>
+
+
+#define IPMI_GET_CHANNEL_AUTH_CAP 0x38
+#define IPMI_GET_CHANNEL_ACCESS 0x41
+#define IPMI_GET_CHANNEL_INFO 0x42
+#define IPMI_SET_USER_ACCESS 0x43
+#define IPMI_GET_USER_ACCESS 0x44
+#define IPMI_SET_USER_NAME 0x45
+#define IPMI_GET_USER_NAME 0x46
+#define IPMI_SET_USER_PASSWORD 0x47
+#define IPMI_GET_CHANNEL_CIPHER_SUITES 0x54
+
+
+/*
+ * The Get Authentication Capabilities response structure
+ * From table 22-15 of the IPMI v2.0 spec
+ */
+struct get_channel_auth_cap_rsp {
+ uint8_t channel_number;
+#if WORDS_BIGENDIAN
+ uint8_t v20_data_available : 1; /* IPMI v2.0 data is available */
+ uint8_t __reserved1 : 1;
+ uint8_t enabled_auth_types : 6; /* IPMI v1.5 enabled auth types */
+#else
+ uint8_t enabled_auth_types : 6; /* IPMI v1.5 enabled auth types */
+ uint8_t __reserved1 : 1;
+ uint8_t v20_data_available : 1; /* IPMI v2.0 data is available */
+#endif
+#if WORDS_BIGENDIAN
+ uint8_t __reserved2 : 2;
+ uint8_t kg_status : 1; /* two-key login status */
+ uint8_t per_message_auth : 1; /* per-message authentication status */
+ uint8_t user_level_auth : 1; /* user-level authentication status */
+ uint8_t non_null_usernames : 1; /* one or more non-null users exist */
+ uint8_t null_usernames : 1; /* one or more null usernames non-null pwds */
+ uint8_t anon_login_enabled : 1; /* a null-named, null-pwd user exists */
+#else
+ uint8_t anon_login_enabled : 1; /* a null-named, null-pwd user exists */
+ uint8_t null_usernames : 1; /* one or more null usernames non-null pwds */
+ uint8_t non_null_usernames : 1; /* one or more non-null users exist */
+ uint8_t user_level_auth : 1; /* user-level authentication status */
+ uint8_t per_message_auth : 1; /* per-message authentication status */
+ uint8_t kg_status : 1; /* two-key login status */
+ uint8_t __reserved2 : 2;
+#endif
+#if WORDS_BIGENDIAN
+ uint8_t __reserved3 : 6;
+ uint8_t ipmiv15_support : 1; /* channel supports IPMI v1.5 connections */
+ uint8_t ipmiv20_support : 1; /* channel supports IPMI v2.0 connections */
+#else
+ uint8_t ipmiv20_support : 1; /* channel supports IPMI v2.0 connections */
+ uint8_t ipmiv15_support : 1; /* channel supports IPMI v1.5 connections */
+ uint8_t __reserved3 : 6;
+#endif
+ uint8_t oem_id[3]; /* IANA enterprise number for auth type */
+ uint8_t oem_aux_data; /* Additional OEM specific data for oem auths */
+} __attribute__ ((packed));
+
+
+
+/*
+ * The Get Channel Info response structure
+ * From table 22-29 of the IPMI v2.0 spec
+ */
+struct get_channel_info_rsp {
+#if WORDS_BIGENDIAN
+ uint8_t __reserved1 : 4;
+ uint8_t channel_number : 4; /* channel number */
+#else
+ uint8_t channel_number : 4; /* channel number */
+ uint8_t __reserved1 : 4;
+#endif
+#if WORDS_BIGENDIAN
+ uint8_t __reserved2 : 1;
+ uint8_t channel_medium : 7; /* Channel medium type per table 6-3 */
+#else
+ uint8_t channel_medium : 7; /* Channel medium type per table 6-3 */
+ uint8_t __reserved2 : 1;
+#endif
+#if WORDS_BIGENDIAN
+ uint8_t __reserved3 : 3;
+ uint8_t channel_protocol : 5; /* Channel protocol per table 6-2 */
+#else
+ uint8_t channel_protocol : 5; /* Channel protocol per table 6-2 */
+ uint8_t __reserved3 : 3;
+#endif
+#if WORDS_BIGENDIAN
+ uint8_t session_support : 2; /* Description of session support */
+ uint8_t active_sessions : 6; /* Count of active sessions */
+#else
+ uint8_t active_sessions : 6; /* Count of active sessions */
+ uint8_t session_support : 2; /* Description of session support */
+#endif
+ uint8_t vendor_id[3]; /* For OEM that specified the protocol */
+ uint8_t aux_info[2]; /* Not used*/
+} __attribute__ ((packed));
+
+
+
+/*
+ * The Get Channel Access response structure
+ * From table 22-28 of the IPMI v2.0 spec
+ */
+struct get_channel_access_rsp {
+#if WORDS_BIGENDIAN
+ uint8_t __reserved1 : 2;
+ uint8_t alerting : 1;
+ uint8_t per_message_auth : 1;
+ uint8_t user_level_auth : 1;
+ uint8_t access_mode : 3;
+#else
+ uint8_t access_mode : 3;
+ uint8_t user_level_auth : 1;
+ uint8_t per_message_auth : 1;
+ uint8_t alerting : 1;
+ uint8_t __reserved1 : 2;
+#endif
+#if WORDS_BIGENDIAN
+ uint8_t __reserved2 : 4;
+ uint8_t channel_priv_limit : 4; /* Channel privilege level limit */
+#else
+ uint8_t channel_priv_limit : 4; /* Channel privilege level limit */
+ uint8_t __reserved2 : 4;
+#endif
+} __attribute__ ((packed));
+
+
+struct get_user_access_rsp {
+#if WORDS_BIGENDIAN
+ uint8_t __reserved1 : 2;
+ uint8_t max_user_ids : 6;
+ uint8_t __reserved2 : 2;
+ uint8_t enabled_user_ids : 6;
+ uint8_t __reserved3 : 2;
+ uint8_t fixed_user_ids : 6;
+ uint8_t __reserved4 : 1;
+ uint8_t callin_callback : 1;
+ uint8_t link_auth : 1;
+ uint8_t ipmi_messaging : 1;
+ uint8_t privilege_limit : 4;
+#else
+ uint8_t max_user_ids : 6;
+ uint8_t __reserved1 : 2;
+ uint8_t enabled_user_ids : 6;
+ uint8_t __reserved2 : 2;
+ uint8_t fixed_user_ids : 6;
+ uint8_t __reserved3 : 2;
+ uint8_t privilege_limit : 4;
+ uint8_t ipmi_messaging : 1;
+ uint8_t link_auth : 1;
+ uint8_t callin_callback : 1;
+ uint8_t __reserved4 : 1;
+#endif
+} __attribute__ ((packed));
+
+struct set_user_access_data {
+#if WORDS_BIGENDIAN
+ uint8_t change_bits : 1;
+ uint8_t callin_callback : 1;
+ uint8_t link_auth : 1;
+ uint8_t ipmi_messaging : 1;
+ uint8_t channel : 4;
+ uint8_t __reserved1 : 2;
+ uint8_t user_id : 6;
+ uint8_t __reserved2 : 4;
+ uint8_t privilege_limit : 4;
+ uint8_t __reserved3 : 4;
+ uint8_t session_limit : 4;
+#else
+ uint8_t channel : 4;
+ uint8_t ipmi_messaging : 1;
+ uint8_t link_auth : 1;
+ uint8_t callin_callback : 1;
+ uint8_t change_bits : 1;
+ uint8_t user_id : 6;
+ uint8_t __reserved1 : 2;
+ uint8_t privilege_limit : 4;
+ uint8_t __reserved2 : 4;
+ uint8_t session_limit : 4;
+ uint8_t __reserved3 : 4;
+#endif
+} __attribute__ ((packed));
+
+uint8_t ipmi_get_channel_medium(struct ipmi_intf * intf, uint8_t channel);
+uint8_t ipmi_current_channel_medium(struct ipmi_intf * intf);
+int ipmi_channel_main(struct ipmi_intf * intf, int argc, char ** argv);
+int ipmi_get_channel_auth_cap(struct ipmi_intf * intf, uint8_t channel, uint8_t priv);
+int ipmi_get_channel_info(struct ipmi_intf * intf, uint8_t channel);
+
+#endif /*IPMI_CHANNEL_H*/
diff --git a/lib/lanplus/inc/ipmitool/ipmi_chassis.h b/lib/lanplus/inc/ipmitool/ipmi_chassis.h
new file mode 100644
index 0000000..3f56924
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_chassis.h
@@ -0,0 +1,55 @@
+/*
+ * 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_CHASSIS_H
+#define IPMI_CHASSIS_H
+
+#include <ipmitool/ipmi.h>
+
+#define IPMI_CHASSIS_CTL_POWER_DOWN 0x0
+#define IPMI_CHASSIS_CTL_POWER_UP 0x1
+#define IPMI_CHASSIS_CTL_POWER_CYCLE 0x2
+#define IPMI_CHASSIS_CTL_HARD_RESET 0x3
+#define IPMI_CHASSIS_CTL_PULSE_DIAG 0x4
+#define IPMI_CHASSIS_CTL_ACPI_SOFT 0x5
+
+#define IPMI_CHASSIS_POLICY_NO_CHANGE 0x3
+#define IPMI_CHASSIS_POLICY_ALWAYS_ON 0x2
+#define IPMI_CHASSIS_POLICY_PREVIOUS 0x1
+#define IPMI_CHASSIS_POLICY_ALWAYS_OFF 0x0
+
+int ipmi_chassis_power_status(struct ipmi_intf * intf);
+int ipmi_chassis_power_control(struct ipmi_intf * intf, uint8_t ctl);
+int ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv);
+int ipmi_power_main(struct ipmi_intf * intf, int argc, char ** argv);
+
+#endif /*IPMI_CHASSIS_H*/
diff --git a/lib/lanplus/inc/ipmitool/ipmi_constants.h b/lib/lanplus/inc/ipmitool/ipmi_constants.h
new file mode 100644
index 0000000..654e0ae
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_constants.h
@@ -0,0 +1,136 @@
+/*
+ * 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_CONSTANTS_H
+#define IPMI_CONSTANTS_H
+
+
+/*
+ * COMMANDS
+ */
+#define IPMI_GET_SDR_REPOSITORY_INFO 0x20
+#define IMPI_SOL_ACTIVATING 0x20
+#define IMPI_SET_SOL_CONFIG_PARAMETERS 0x21
+#define IMPI_GET_SOL_CONFIG_PARAMETERS 0x22
+#define IPMI_SET_USER_ACCESS 0x43
+#define IPMI_GET_USER_ACCESS 0x44
+#define IPMI_SET_USER_NAME 0x45
+#define IPMI_GET_USER_NAME 0x46
+#define IPMI_SET_USER_PASSWORD 0x47
+#define IPMI_ACTIVATE_PAYLOAD 0x48
+#define IPMI_DEACTIVATE_PAYLOAD 0x49
+#define IPMI_SUSPEND_RESUME_PAYLOAD_ENCRYPTYION 0x55
+#define IPMI_GET_SEL_TIME 0x48
+#define IPMI_SET_SEL_TIME 0x49
+#define IPMI_SET_USER_PAYLOAD_ACCESS 0x4c
+#define IPMI_GET_USER_PAYLOAD_ACCESS 0x4d
+
+#define IPMI_1_5_AUTH_TYPE_BIT_NONE 0x01
+#define IPMI_1_5_AUTH_TYPE_BIT_MD2 0x02
+#define IPMI_1_5_AUTH_TYPE_BIT_MD5 0x04
+#define IPMI_1_5_AUTH_TYPE_BIT_PASSWORD 0x10
+#define IPMI_1_5_AUTH_TYPE_BIT_OEM 0x20
+
+#define IPMI_SESSION_AUTHTYPE_NONE 0x0
+#define IPMI_SESSION_AUTHTYPE_MD2 0x1
+#define IPMI_SESSION_AUTHTYPE_MD5 0x2
+#define IPMI_SESSION_AUTHTYPE_KEY 0x4
+#define IPMI_SESSION_AUTHTYPE_PASSWORD IPMI_SESSION_AUTHTYPE_KEY
+#define IPMI_SESSION_AUTHTYPE_OEM 0x5
+#define IPMI_SESSION_AUTHTYPE_RMCP_PLUS 0x6
+
+#define IPMI_SESSION_PRIV_UNSPECIFIED 0x0
+#define IPMI_SESSION_PRIV_CALLBACK 0x1
+#define IPMI_SESSION_PRIV_USER 0x2
+#define IPMI_SESSION_PRIV_OPERATOR 0x3
+#define IPMI_SESSION_PRIV_ADMIN 0x4
+#define IPMI_SESSION_PRIV_OEM 0x5
+
+#define IPMI_SET_IN_PROGRESS_SET_COMPLETE 0x00
+#define IPMI_SET_IN_PROGRESS_IN_PROGRESS 0x01
+#define IPMI_SET_IN_PROGRESS_COMMIT_WRITE 0x02
+
+#define IPMI_CHANNEL_MEDIUM_RESERVED 0x0
+#define IPMI_CHANNEL_MEDIUM_IPMB_I2C 0x1
+#define IPMI_CHANNEL_MEDIUM_ICMB_1 0x2
+#define IPMI_CHANNEL_MEDIUM_ICMB_09 0x3
+#define IPMI_CHANNEL_MEDIUM_LAN 0x4
+#define IPMI_CHANNEL_MEDIUM_SERIAL 0x5
+#define IPMI_CHANNEL_MEDIUM_LAN_OTHER 0x6
+#define IPMI_CHANNEL_MEDIUM_SMBUS_PCI 0x7
+#define IPMI_CHANNEL_MEDIUM_SMBUS_1 0x8
+#define IPMI_CHANNEL_MEDIUM_SMBUS_2 0x9
+#define IPMI_CHANNEL_MEDIUM_USB_1 0xa
+#define IPMI_CHANNEL_MEDIUM_USB_2 0xb
+#define IPMI_CHANNEL_MEDIUM_SYSTEM 0xc
+
+#define IPMI_CHASSIS_CTL_POWER_DOWN 0x0
+#define IPMI_CHASSIS_CTL_POWER_UP 0x1
+#define IPMI_CHASSIS_CTL_POWER_CYCLE 0x2
+#define IPMI_CHASSIS_CTL_HARD_RESET 0x3
+#define IPMI_CHASSIS_CTL_PULSE_DIAG 0x4
+#define IPMI_CHASSIS_CTL_ACPI_SOFT 0x5
+
+#define IPMI_CHASSIS_POLICY_NO_CHANGE 0x3
+#define IPMI_CHASSIS_POLICY_ALWAYS_ON 0x2
+#define IPMI_CHASSIS_POLICY_PREVIOUS 0x1
+#define IPMI_CHASSIS_POLICY_ALWAYS_OFF 0x0
+
+#define IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS 0
+#define IPMI_CHASSIS_BOOTPARAM_SVCPART_SELECT 1
+#define IPMI_CHASSIS_BOOTPARAM_SVCPART_SCAN 2
+#define IPMI_CHASSIS_BOOTPARAM_FLAG_VALID 3
+#define IPMI_CHASSIS_BOOTPARAM_INFO_ACK 4
+#define IPMI_CHASSIS_BOOTPARAM_BOOT_FLAGS 5
+#define IPMI_CHASSIS_BOOTPARAM_INIT_INFO 6
+#define IPMI_CHASSIS_BOOTPARAM_INIT_MBOX 7
+
+/* From table 13-17 of the IPMI v2 specification */
+#define IPMI_AUTH_RAKP_NONE 0x00
+#define IPMI_AUTH_RAKP_HMAC_SHA1 0x01
+#define IPMI_AUTH_RAKP_HMAC_MD5 0x02
+#define IPMI_AUTH_RAKP_HMAC_SHA256 0x03
+
+/* From table 13-18 of the IPMI v2 specification */
+#define IPMI_INTEGRITY_NONE 0x00
+#define IPMI_INTEGRITY_HMAC_SHA1_96 0x01
+#define IPMI_INTEGRITY_HMAC_MD5_128 0x02
+#define IPMI_INTEGRITY_MD5_128 0x03
+#define IPMI_INTEGRITY_HMAC_SHA256_128 0x04
+
+/* From table 13-19 of the IPMI v2 specfication */
+#define IPMI_CRYPT_NONE 0x00
+#define IPMI_CRYPT_AES_CBC_128 0x01
+#define IPMI_CRYPT_XRC4_128 0x02
+#define IPMI_CRYPT_XRC4_40 0x03
+
+#endif /*IPMI_CONSTANTS_H*/
diff --git a/lib/lanplus/inc/ipmitool/ipmi_entity.h b/lib/lanplus/inc/ipmitool/ipmi_entity.h
new file mode 100644
index 0000000..29f44d2
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_entity.h
@@ -0,0 +1,47 @@
+/*
+ * 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_ENTITY_H
+#define IPMI_ENTITY_H
+
+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));
+
+#endif /* IPMI_ENTITY_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_event.h b/lib/lanplus/inc/ipmitool/ipmi_event.h
new file mode 100644
index 0000000..e78d453
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_event.h
@@ -0,0 +1,60 @@
+/*
+ * 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_EVENT_H
+#define IPMI_EVENT_H
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <ipmitool/ipmi.h>
+
+#define EVENT_DIR_ASSERT 0
+#define EVENT_DIR_DEASSERT 1
+
+struct platform_event_msg {
+ 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
+ uint8_t event_data[3];
+} __attribute__((packed));
+
+int ipmi_event_main(struct ipmi_intf *, int, char **);
+
+#endif /*IPMI_EVENT_H*/
diff --git a/lib/lanplus/inc/ipmitool/ipmi_firewall.h b/lib/lanplus/inc/ipmitool/ipmi_firewall.h
new file mode 100644
index 0000000..f18770e
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_firewall.h
@@ -0,0 +1,106 @@
+/*
+ * 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_FIREWALL_H
+#define IPMI_FIREWALL_H
+
+#include <ipmitool/ipmi.h>
+
+int ipmi_firewall_main(struct ipmi_intf *, int, char **);
+
+#define BMC_GET_NETFN_SUPPORT 0x09
+#define BMC_GET_COMMAND_SUPPORT 0x0A
+#define BMC_GET_COMMAND_SUBFUNCTION_SUPPORT 0x0B
+#define BMC_GET_CONFIGURABLE_COMMANDS 0x0C
+#define BMC_GET_CONFIGURABLE_COMMAND_SUBFUNCTIONS 0x0D
+#define BMC_SET_COMMAND_ENABLES 0x60
+#define BMC_GET_COMMAND_ENABLES 0x61
+#define BMC_SET_COMMAND_SUBFUNCTION_ENABLES 0x62
+#define BMC_GET_COMMAND_SUBFUNCTION_ENABLES 0x63
+#define BMC_OEM_NETFN_IANA_SUPPORT 0x64
+
+#define SET_COMMAND_ENABLE_BYTE (BMC_SET_COMMAND_ENABLES / 8)
+#define SET_COMMAND_ENABLE_BIT (BMC_SET_COMMAND_ENABLES % 8)
+
+#define MAX_LUN 4
+#define MAX_NETFN 64
+#define MAX_NETFN_PAIR (MAX_NETFN/2)
+#define MAX_COMMAND 256
+#define MAX_SUBFN 32
+#define MAX_COMMAND_BYTES (MAX_COMMAND>>3)
+#define MAX_SUBFN_BYTES (MAX_SUBFN>>3)
+
+// support is a bitfield with the following bits set...
+#define BIT_AVAILABLE 0x01
+#define BIT_CONFIGURABLE 0x02
+#define BIT_ENABLED 0x04
+
+extern int verbose;
+
+struct command_support {
+ unsigned char support;
+ unsigned char version[3];
+ unsigned char subfn_support[MAX_SUBFN_BYTES];
+ unsigned char subfn_config[MAX_SUBFN_BYTES];
+ unsigned char subfn_enable[MAX_SUBFN_BYTES];
+};
+struct lun_netfn_support {
+ unsigned char support;
+ struct command_support command[MAX_COMMAND];
+ unsigned char command_mask[MAX_COMMAND_BYTES];
+ unsigned char config_mask[MAX_COMMAND_BYTES];
+ unsigned char enable_mask[MAX_COMMAND_BYTES];
+};
+struct lun_support {
+ unsigned char support;
+ struct lun_netfn_support netfn[MAX_NETFN_PAIR];
+};
+struct bmc_fn_support {
+ struct lun_support lun[MAX_LUN];
+};
+struct ipmi_function_params {
+ int channel;
+ int lun;
+ int netfn;
+ int command;
+ int subfn;
+ unsigned char force;
+};
+
+static inline int bit_test(const unsigned char * bf, int n) {
+ return !!(bf[n>>3]&(1<<(n%8)));
+}
+static inline void bit_set(unsigned char * bf, int n, int v) {
+ bf[n>>3] = (bf[n>>3] & ~(1<<(n%8))) | ((v?1:0)<<(n%8));
+}
+
+#endif /*IPMI_FIREWALL_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_fru.h b/lib/lanplus/inc/ipmitool/ipmi_fru.h
new file mode 100644
index 0000000..0fe594a
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_fru.h
@@ -0,0 +1,381 @@
+/*
+ * 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_FRU_H
+#define IPMI_FRU_H
+
+#ifdef WIN32
+#include <inttypes-win.h>
+#else
+#include <inttypes.h>
+#endif
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_sdr.h>
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#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_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_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;
+};
+
+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));
+
+static const char *combined_voltage_desc[] __attribute__ ((unused)) = {
+"12 V", "-12 V", "5 V", "3.3 V"};
+
+struct fru_multirec_dcoutput {
+#if WORDS_BIGENDIAN
+ uint8_t standby:1;
+ uint8_t __reserved1:3;
+ uint8_t output_number:4;
+#else
+ uint8_t output_number:4;
+ uint8_t __reserved1: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 __reserved1:4;
+ uint8_t output_number:4;
+#else
+ uint8_t output_number:4;
+ uint8_t __reserved1: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
+ unsigned char record_id;
+ unsigned char record_version;
+} __attribute__ ((packed));
+
+struct fru_picmgext_guid {
+ unsigned char guid[16];
+} __attribute__ ((packed));
+
+struct fru_picmgext_link_desc {
+#ifndef WORDS_BIGENDIAN
+ unsigned int designator:12;
+#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 designator:12;
+#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));
+
+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));
+
+
+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));
+
+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"};
+
+int ipmi_fru_main(struct ipmi_intf *intf, int argc, char **argv);
+int ipmi_fru_print(struct ipmi_intf *intf, struct sdr_record_fru_locator *fru);
+int ipmi_spd_print(uint8_t *data, int len);
+int ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id);
+
+#endif /* IPMI_FRU_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_fwum.h b/lib/lanplus/inc/ipmitool/ipmi_fwum.h
new file mode 100644
index 0000000..1170abe
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_fwum.h
@@ -0,0 +1,46 @@
+/*
+ * 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
+
+#ifdef WIN32
+#include <inttypes-win.h>
+#else
+#include <inttypes.h>
+#endif
+#include <ipmitool/ipmi.h>
+
+
+int ipmi_fwum_main(struct ipmi_intf *, int, char **);
+
+#endif /* IPMI_KFWUM_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_hpmfwupg.h b/lib/lanplus/inc/ipmitool/ipmi_hpmfwupg.h
new file mode 100644
index 0000000..4739d58
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_hpmfwupg.h
@@ -0,0 +1,45 @@
+/*
+ * 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_HPMFWUPG_H
+#define IPMI_HPMFWUPG_H
+
+#ifdef WIN32
+#include <inttypes-win.h>
+#else
+#include <inttypes.h>
+#endif
+#include <ipmitool/ipmi.h>
+
+int ipmi_hpmfwupg_main(struct ipmi_intf *, int, char **);
+
+#endif /* IPMI_KFWUM_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_intf.h b/lib/lanplus/inc/ipmitool/ipmi_intf.h
new file mode 100644
index 0000000..db1ffd5
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_intf.h
@@ -0,0 +1,224 @@
+/*
+ * 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_INTF_H
+#define IPMI_INTF_H
+
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_oem.h>
+#include <ipmitool/ipmi_constants.h>
+
+#ifdef WIN32
+#include <windows.h>
+#include <winsock.h>
+#include <inttypes-win.h>
+#else
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif
+
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+
+#ifdef MOVED
+// moved this to "lanplus_defs.h"
+/*
+ * An enumeration that describes every possible session state for
+ * an IPMIv2 / RMCP+ session.
+ */
+enum LANPLUS_SESSION_STATE {
+ LANPLUS_STATE_PRESESSION = 0,
+ LANPLUS_STATE_OPEN_SESSION_SENT,
+ LANPLUS_STATE_OPEN_SESSION_RECEIEVED,
+ LANPLUS_STATE_RAKP_1_SENT,
+ LANPLUS_STATE_RAKP_2_RECEIVED,
+ LANPLUS_STATE_RAKP_3_SENT,
+ LANPLUS_STATE_ACTIVE,
+ LANPLUS_STATE_CLOSE_SENT,
+};
+
+#define IPMI_AUTHCODE_BUFFER_SIZE 20 // KG or KUID
+#define IPMI_SIK_BUFFER_SIZE EVP_MAX_MD_SIZE
+#define IPMI_KG_BUFFER_SIZE 21 /* key plus null byte */
+
+struct ipmi_session {
+ uint8_t hostname[64];
+ uint8_t username[17];
+ uint8_t authcode[IPMI_AUTHCODE_BUFFER_SIZE + 1];
+ uint8_t challenge[16];
+ uint8_t authtype;
+ uint8_t authtype_set;
+#define IPMI_AUTHSTATUS_PER_MSG_DISABLED 0x10
+#define IPMI_AUTHSTATUS_PER_USER_DISABLED 0x08
+#define IPMI_AUTHSTATUS_NONNULL_USERS_ENABLED 0x04
+#define IPMI_AUTHSTATUS_NULL_USERS_ENABLED 0x02
+#define IPMI_AUTHSTATUS_ANONYMOUS_USERS_ENABLED 0x01
+ uint8_t authstatus;
+ uint8_t authextra;
+ uint8_t privlvl;
+ uint8_t cipher_suite_id;
+ char sol_escape_char;
+ int password;
+ int port;
+ int active;
+ int retry;
+
+ uint32_t session_id;
+ uint32_t in_seq;
+ uint32_t out_seq;
+ uint32_t timeout;
+
+ struct sockaddr_in addr; /*old*/
+ socklen_t addrlen;
+
+ /*
+ * This struct holds state data specific to IPMI v2 / RMCP+ sessions
+ */
+ struct {
+ enum LANPLUS_SESSION_STATE session_state;
+
+ /* These are the algorithms agreed upon for the session */
+ uint8_t requested_auth_alg;
+ uint8_t requested_integrity_alg;
+ uint8_t requested_crypt_alg;
+ uint8_t auth_alg;
+ uint8_t integrity_alg;
+ uint8_t crypt_alg;
+ uint8_t max_priv_level;
+ uint8_t lookupbit;
+
+ uint32_t console_id;
+ uint32_t bmc_id;
+
+ /*
+ * Values required for RAKP mesages
+ */
+
+ /* Random number generated byt the console */
+ uint8_t console_rand[16];
+ /* Random number generated by the BMC */
+ uint8_t bmc_rand[16];
+
+ uint8_t bmc_guid[16];
+ uint8_t requested_role; /* As sent in the RAKP 1 message */
+ uint8_t rakp2_return_code;
+
+ uint8_t sik[EVP_MAX_MD_SIZE]; /* Session integrity key */
+ uint8_t kg[IPMI_KG_BUFFER_SIZE]; /* BMC key */
+ uint8_t k1[EVP_MAX_MD_SIZE]; /* Used for Integrity checking? */
+ uint8_t k2[EVP_MAX_MD_SIZE]; /* First 16 bytes used for AES */
+ uint8_t sik_len; /* length of sik */
+ uint8_t k1_len; /* length of k1 */
+ uint8_t k2_len; /* length of k2 */
+ } v2_data;
+
+
+ /*
+ * This data is specific to the Serial Over Lan session
+ */
+ struct {
+ uint16_t max_inbound_payload_size;
+ uint16_t max_outbound_payload_size;
+ uint16_t port;
+ uint8_t sequence_number;
+
+ /* This data describes the last SOL packet */
+ uint8_t last_received_sequence_number;
+ uint8_t last_received_byte_count;
+ void (*sol_input_handler)(struct ipmi_rs * rsp);
+ } sol_data;
+};
+
+struct ipmi_cmd {
+ int (*func)(struct ipmi_intf * intf, int argc, char ** argv);
+ const char * name;
+ const char * desc;
+};
+
+struct ipmi_intf_support {
+ const char * name;
+ int supported;
+};
+
+struct ipmi_intf {
+ char name[16];
+ char desc[128];
+ int fd;
+ int opened;
+ int abort;
+ int noanswer;
+
+ struct ipmi_session * session;
+ struct ipmi_oem_handle * oem;
+ struct ipmi_cmd * cmdlist;
+ uint32_t my_addr;
+ uint32_t target_addr;
+ uint8_t target_lun;
+ uint8_t target_channel;
+ uint32_t transit_addr;
+ uint8_t transit_channel;
+ uint8_t devnum;
+
+ int (*setup)(struct ipmi_intf * intf);
+ int (*open)(struct ipmi_intf * intf);
+ void (*close)(struct ipmi_intf * intf);
+ struct ipmi_rs *(*sendrecv)(struct ipmi_intf * intf, struct ipmi_rq * req);
+ int (*sendrsp)(struct ipmi_intf * intf, struct ipmi_rs * rsp);
+ struct ipmi_rs *(*recv_sol)(struct ipmi_intf * intf);
+ struct ipmi_rs *(*send_sol)(struct ipmi_intf * intf, struct ipmi_v2_payload * payload);
+ int (*keepalive)(struct ipmi_intf * intf);
+};
+#else
+
+#include "lanplus_defs.h"
+#endif
+
+struct ipmi_intf * ipmi_intf_load(char * name);
+void ipmi_intf_print(struct ipmi_intf_support * intflist);
+
+void ipmi_intf_session_set_hostname(struct ipmi_intf * intf, char * hostname);
+void ipmi_intf_session_set_username(struct ipmi_intf * intf, char * username);
+void ipmi_intf_session_set_password(struct ipmi_intf * intf, char * password);
+void ipmi_intf_session_set_privlvl(struct ipmi_intf * intf, uint8_t privlvl);
+void ipmi_intf_session_set_lookupbit(struct ipmi_intf * intf, uint8_t lookupbit);
+void ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_suite_id);
+void ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_char);
+void ipmi_intf_session_set_kgkey(struct ipmi_intf * intf, char * kgkey);
+void ipmi_intf_session_set_port(struct ipmi_intf * intf, int port);
+void ipmi_intf_session_set_authtype(struct ipmi_intf * intf, uint8_t authtype);
+void ipmi_intf_session_set_timeout(struct ipmi_intf * intf, uint32_t timeout);
+void ipmi_intf_session_set_retry(struct ipmi_intf * intf, int retry);
+void ipmi_cleanup(struct ipmi_intf * intf);
+
+#endif /* IPMI_INTF_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_isol.h b/lib/lanplus/inc/ipmitool/ipmi_isol.h
new file mode 100644
index 0000000..6a41b07
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_isol.h
@@ -0,0 +1,56 @@
+/*
+ * 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_ISOL_H
+#define IPMI_ISOL_H
+
+#include <ipmitool/ipmi.h>
+
+#define ACTIVATE_ISOL 0x01
+#define SET_ISOL_CONFIG 0x03
+#define GET_ISOL_CONFIG 0x04
+
+#define ISOL_ENABLE_PARAM 0x01
+#define ISOL_AUTHENTICATION_PARAM 0x02
+#define ISOL_ENABLE_FLAG 0x01
+#define ISOL_PRIVILEGE_LEVEL_USER 0x02
+#define ISOL_BAUD_RATE_PARAM 0x05
+#define ISOL_BAUD_RATE_9600 0x06
+#define ISOL_BAUD_RATE_19200 0x07
+#define ISOL_BAUD_RATE_38400 0x08
+#define ISOL_BAUD_RATE_57600 0x09
+#define ISOL_BAUD_RATE_115200 0x0A
+#define ISOL_PREFERRED_BAUD_RATE 0x07
+
+int ipmi_isol_main(struct ipmi_intf *, int, char **);
+
+#endif /* IPMI_SOL_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_kontronoem.h b/lib/lanplus/inc/ipmitool/ipmi_kontronoem.h
new file mode 100644
index 0000000..083e546
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_kontronoem.h
@@ -0,0 +1,49 @@
+/*
+ * 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
+
+#ifdef WIN32
+#include <inttypes-win.h>
+#else
+#include <inttypes.h>
+#endif
+#include <ipmitool/ipmi.h>
+
+
+int ipmi_kontronoem_main(struct ipmi_intf *, int, char **);
+
+#endif /* IPMI_KONTRONOEM_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_lanp.h b/lib/lanplus/inc/ipmitool/ipmi_lanp.h
new file mode 100644
index 0000000..1aaae5e
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_lanp.h
@@ -0,0 +1,132 @@
+/*
+ * 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_LANP_H
+#define IPMI_LANP_H
+
+#include <ipmitool/ipmi.h>
+
+#define IPMI_LAN_SET_CONFIG 0x01
+#define IPMI_LAN_GET_CONFIG 0x02
+#define IPMI_LAN_SUSPEND_ARP 0x03
+# define IPMI_LAN_SUSPEND_ARP_RESP (2)
+# define IPMI_LAN_SUSPEND_ARP_GRAT (1)
+#define IPMI_LAN_GET_STAT 0x04
+
+#define IPMI_CHANNEL_NUMBER_MAX 0xe
+
+#define IPMI_LANP_TIMEOUT 3
+#define IPMI_LANP_RETRIES 10
+#define IPMI_LANP_WRITE_UNLOCK 0
+#define IPMI_LANP_WRITE_LOCK 1
+#define IPMI_LANP_WRITE_COMMIT 2
+
+enum {
+ IPMI_LANP_SET_IN_PROGRESS,
+ IPMI_LANP_AUTH_TYPE,
+ IPMI_LANP_AUTH_TYPE_ENABLE,
+ IPMI_LANP_IP_ADDR,
+ IPMI_LANP_IP_ADDR_SRC,
+ IPMI_LANP_MAC_ADDR, /* 5 */
+ IPMI_LANP_SUBNET_MASK,
+ IPMI_LANP_IP_HEADER,
+ IPMI_LANP_PRI_RMCP_PORT,
+ IPMI_LANP_SEC_RMCP_PORT,
+ IPMI_LANP_BMC_ARP, /* 10 */
+ IPMI_LANP_GRAT_ARP,
+ IPMI_LANP_DEF_GATEWAY_IP,
+ IPMI_LANP_DEF_GATEWAY_MAC,
+ IPMI_LANP_BAK_GATEWAY_IP,
+ IPMI_LANP_BAK_GATEWAY_MAC, /* 15 */
+ IPMI_LANP_SNMP_STRING,
+ IPMI_LANP_NUM_DEST,
+ IPMI_LANP_DEST_TYPE,
+ IPMI_LANP_DEST_ADDR,
+ IPMI_LANP_VLAN_ID, /* 20 */
+ IPMI_LANP_VLAN_PRIORITY,
+ IPMI_LANP_RMCP_CIPHER_SUPPORT,
+ IPMI_LANP_RMCP_CIPHERS,
+ IPMI_LANP_RMCP_PRIV_LEVELS,
+ IPMI_LANP_OEM_ALERT_STRING=96,
+ IPMI_LANP_ALERT_RETRY=97,
+ IPMI_LANP_UTC_OFFSET=98,
+ IPMI_LANP_DHCP_SERVER_IP=192,
+ IPMI_LANP_DHCP_SERVER_MAC=193,
+ IPMI_LANP_DHCP_ENABLE=194,
+ IPMI_LANP_CHAN_ACCESS_MODE=201,
+};
+
+static struct lan_param {
+ int cmd;
+ int size;
+ char desc[24];
+ uint8_t * data;
+ int data_len;
+} ipmi_lan_params[] __attribute__((unused)) = {
+ { IPMI_LANP_SET_IN_PROGRESS, 1, "Set in Progress" },
+ { IPMI_LANP_AUTH_TYPE, 1, "Auth Type Support" },
+ { IPMI_LANP_AUTH_TYPE_ENABLE, 5, "Auth Type Enable" },
+ { IPMI_LANP_IP_ADDR, 4, "IP Address" },
+ { IPMI_LANP_IP_ADDR_SRC, 1, "IP Address Source" },
+ { IPMI_LANP_MAC_ADDR, 6, "MAC Address" }, /* 5 */
+ { IPMI_LANP_SUBNET_MASK, 4, "Subnet Mask" },
+ { IPMI_LANP_IP_HEADER, 3, "IP Header" },
+ { IPMI_LANP_PRI_RMCP_PORT, 2, "Primary RMCP Port" },
+ { IPMI_LANP_SEC_RMCP_PORT, 2, "Secondary RMCP Port" },
+ { IPMI_LANP_BMC_ARP, 1, "BMC ARP Control" }, /* 10 */
+ { IPMI_LANP_GRAT_ARP, 1, "Gratituous ARP Intrvl" },
+ { IPMI_LANP_DEF_GATEWAY_IP, 4, "Default Gateway IP" },
+ { IPMI_LANP_DEF_GATEWAY_MAC, 6, "Default Gateway MAC" },
+ { IPMI_LANP_BAK_GATEWAY_IP, 4, "Backup Gateway IP" },
+ { IPMI_LANP_BAK_GATEWAY_MAC, 6, "Backup Gateway MAC" }, /* 15 */
+ { IPMI_LANP_SNMP_STRING, 18, "SNMP Community String" },
+ { IPMI_LANP_NUM_DEST, 1, "Number of Destinations"},
+ { IPMI_LANP_DEST_TYPE, 4, "Destination Type" },
+ { IPMI_LANP_DEST_ADDR, 13, "Destination Addresses" },
+ { IPMI_LANP_VLAN_ID, 2, "802.1q VLAN ID" }, /* 20 */
+ { IPMI_LANP_VLAN_PRIORITY, 1, "802.1q VLAN Priority" },
+ { IPMI_LANP_RMCP_CIPHER_SUPPORT,1, "RMCP+ Cipher Suite Count" },
+ { IPMI_LANP_RMCP_CIPHERS, 16, "RMCP+ Cipher Suites" },
+ { IPMI_LANP_RMCP_PRIV_LEVELS, 9, "Cipher Suite Priv Max" },
+ { IPMI_LANP_OEM_ALERT_STRING, 28, "OEM Alert String" }, /* 25 */
+ { IPMI_LANP_ALERT_RETRY, 1, "Alert Retry Algorithm" },
+ { IPMI_LANP_UTC_OFFSET, 3, "UTC Offset" },
+ { IPMI_LANP_DHCP_SERVER_IP, 4, "DHCP Server IP" },
+ { IPMI_LANP_DHCP_SERVER_MAC, 6, "DHDP Server MAC" },
+ { IPMI_LANP_DHCP_ENABLE, 1, "DHCP Enable" }, /* 30 */
+ { IPMI_LANP_CHAN_ACCESS_MODE, 2, "Channel Access Mode" },
+ { -1 }
+};
+
+int ipmi_lanp_main(struct ipmi_intf *, int, char **);
+
+#endif /*IPMI_LANP_H*/
diff --git a/lib/lanplus/inc/ipmitool/ipmi_main.h b/lib/lanplus/inc/ipmitool/ipmi_main.h
new file mode 100644
index 0000000..e32360a
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_main.h
@@ -0,0 +1,42 @@
+/*
+ * 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_MAIN_H
+#define IPMI_MAIN_H
+
+#include <ipmitool/ipmi_intf.h>
+
+int ipmi_main(int argc, char ** argv, struct ipmi_cmd * cmdlist, struct ipmi_intf_support * intflist);
+void ipmi_cmd_print(struct ipmi_cmd * cmdlist);
+int ipmi_cmd_run(struct ipmi_intf * intf, char * name, int argc, char ** argv);
+
+#endif /* IPMI_MAIN_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_mc.h b/lib/lanplus/inc/ipmitool/ipmi_mc.h
new file mode 100644
index 0000000..601f40e
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_mc.h
@@ -0,0 +1,103 @@
+/*
+ * 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_MC_H
+#define IPMI_MC_H
+
+#include <ipmitool/ipmi.h>
+
+#define BMC_GET_DEVICE_ID 0x01
+#define BMC_COLD_RESET 0x02
+#define BMC_WARM_RESET 0x03
+#define BMC_GET_SELF_TEST 0x04
+#define BMC_SET_GLOBAL_ENABLES 0x2e
+#define BMC_GET_GLOBAL_ENABLES 0x2f
+#define BMC_GET_GUID 0x37
+
+int ipmi_mc_main(struct ipmi_intf *, int, char **);
+
+/*
+ * Response data from IPM Get Device ID Command (IPMI rev 1.5, section 17.1)
+ * The following really apply to any IPM device, not just BMCs...
+ */
+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));
+
+#define IPM_DEV_DEVICE_ID_SDR_MASK (0x80) /* 1 = provides SDRs */
+#define IPM_DEV_DEVICE_ID_REV_MASK (0x07) /* BCD-enoded */
+
+#define IPM_DEV_FWREV1_AVAIL_MASK (0x80) /* 0 = normal operation */
+#define IPM_DEV_FWREV1_MAJOR_MASK (0x3f) /* Major rev, BCD-encoded */
+
+#define IPM_DEV_IPMI_VER_MAJOR_MASK (0x0F) /* Major rev, BCD-encoded */
+#define IPM_DEV_IPMI_VER_MINOR_MASK (0xF0) /* Minor rev, BCD-encoded */
+#define IPM_DEV_IPMI_VER_MINOR_SHIFT (4) /* Minor rev shift */
+#define IPM_DEV_IPMI_VERSION_MAJOR(x) \
+ (x & IPM_DEV_IPMI_VER_MAJOR_MASK)
+#define IPM_DEV_IPMI_VERSION_MINOR(x) \
+ ((x & IPM_DEV_IPMI_VER_MINOR_MASK) >> IPM_DEV_IPMI_VER_MINOR_SHIFT)
+
+#define IPM_DEV_MANUFACTURER_ID(x) \
+ ((uint32_t) ((x[2] & 0x0F) << 16 | x[1] << 8 | x[0]))
+
+#define IPM_DEV_ADTL_SUPPORT_BITS (8)
+
+struct ipm_selftest_rsp {
+ unsigned char code;
+ unsigned char test;
+} __attribute__ ((packed));
+
+#define IPM_SFT_CODE_OK 0x55
+#define IPM_SFT_CODE_NOT_IMPLEMENTED 0x56
+#define IPM_SFT_CODE_DEV_CORRUPTED 0x57
+#define IPM_SFT_CODE_FATAL_ERROR 0x58
+#define IPM_SFT_CODE_RESERVED 0xff
+
+#define IPM_SELFTEST_SEL_ERROR 0x80
+#define IPM_SELFTEST_SDR_ERROR 0x40
+#define IPM_SELFTEST_FRU_ERROR 0x20
+#define IPM_SELFTEST_IPMB_ERROR 0x10
+#define IPM_SELFTEST_SDRR_EMPTY 0x08
+#define IPM_SELFTEST_INTERNAL_USE 0x04
+#define IPM_SELFTEST_FW_BOOTBLOCK 0x02
+#define IPM_SELFTEST_FW_CORRUPTED 0x01
+
+#endif /*IPMI_MC_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_oem.h b/lib/lanplus/inc/ipmitool/ipmi_oem.h
new file mode 100644
index 0000000..ad22fde
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_oem.h
@@ -0,0 +1,47 @@
+/*
+ * 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_OEM_H
+#define IPMI_OEM_H
+
+#include <ipmitool/ipmi.h>
+
+/* oem handler, see lib/ipmi_oem.c */
+struct ipmi_oem_handle {
+ const char * name;
+ const char * desc;
+ int (*setup)(struct ipmi_intf * intf);
+};
+
+void ipmi_oem_print(void);
+int ipmi_oem_setup(struct ipmi_intf * intf, char * oemtype);
+int ipmi_oem_active(struct ipmi_intf * intf, const char * oemtype);
+
+#endif /*IPMI_OEM_H*/
diff --git a/lib/lanplus/inc/ipmitool/ipmi_pef.h b/lib/lanplus/inc/ipmitool/ipmi_pef.h
new file mode 100644
index 0000000..904a2ac
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_pef.h
@@ -0,0 +1,784 @@
+/*
+ * Copyright (c) 2004 Dell Computers. 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 Dell Computers, 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.
+ * DELL COMPUTERS ("DELL") 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
+ * DELL 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 DELL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IPMI_PEF_H
+#define IPMI_PEF_H
+
+#include <ipmitool/ipmi.h>
+
+/* PEF */
+
+struct pef_capabilities { /* "get pef capabilities" response */
+ uint8_t version;
+ uint8_t actions; /* mapped by PEF_ACTION_xxx */
+ uint8_t tblsize;
+};
+
+typedef enum {
+ P_TRUE,
+ P_SUPP,
+ P_ACTV,
+ P_ABLE,
+} flg_e;
+
+struct pef_table_entry {
+#define PEF_CONFIG_ENABLED 0x80
+#define PEF_CONFIG_PRECONFIGURED 0x40
+ uint8_t config;
+#define PEF_ACTION_DIAGNOSTIC_INTERRUPT 0x20
+#define PEF_ACTION_OEM 0x10
+#define PEF_ACTION_POWER_CYCLE 0x08
+#define PEF_ACTION_RESET 0x04
+#define PEF_ACTION_POWER_DOWN 0x02
+#define PEF_ACTION_ALERT 0x01
+ uint8_t action;
+#define PEF_POLICY_NUMBER_MASK 0x0f
+ uint8_t policy_number;
+#define PEF_SEVERITY_NON_RECOVERABLE 0x20
+#define PEF_SEVERITY_CRITICAL 0x10
+#define PEF_SEVERITY_WARNING 0x08
+#define PEF_SEVERITY_OK 0x04
+#define PEF_SEVERITY_INFORMATION 0x02
+#define PEF_SEVERITY_MONITOR 0x01
+ uint8_t severity;
+ uint8_t generator_ID_addr;
+ uint8_t generator_ID_lun;
+ uint8_t sensor_type;
+#define PEF_SENSOR_NUMBER_MATCH_ANY 0xff
+ uint8_t sensor_number;
+#define PEF_EVENT_TRIGGER_UNSPECIFIED 0x0
+#define PEF_EVENT_TRIGGER_THRESHOLD 0x1
+#define PEF_EVENT_TRIGGER_SENSOR_SPECIFIC 0x6f
+#define PEF_EVENT_TRIGGER_MATCH_ANY 0xff
+ uint8_t event_trigger;
+ uint8_t event_data_1_offset_mask[2];
+ uint8_t event_data_1_AND_mask;
+ uint8_t event_data_1_compare_1;
+ uint8_t event_data_1_compare_2;
+ uint8_t event_data_2_AND_mask;
+ uint8_t event_data_2_compare_1;
+ uint8_t event_data_2_compare_2;
+ uint8_t event_data_3_AND_mask;
+ uint8_t event_data_3_compare_1;
+ uint8_t event_data_3_compare_2;
+} __attribute__ ((packed));
+
+struct desc_map { /* maps a description to a value/mask */
+ const char *desc;
+ uint32_t mask;
+};
+
+struct bit_desc_map { /* description text container */
+#define BIT_DESC_MAP_LIST 0x1 /* index-based text array */
+#define BIT_DESC_MAP_ANY 0x2 /* bitwise, but only print 1st one */
+#define BIT_DESC_MAP_ALL 0x3 /* bitwise, print them all */
+ uint32_t desc_map_type;
+ struct desc_map desc_maps[128];
+};
+
+static struct bit_desc_map
+pef_b2s_actions __attribute__((unused)) = {
+BIT_DESC_MAP_ALL,
+{ {"Alert", PEF_ACTION_ALERT},
+ {"Power-off", PEF_ACTION_POWER_DOWN},
+ {"Reset", PEF_ACTION_RESET},
+ {"Power-cycle", PEF_ACTION_POWER_CYCLE},
+ {"OEM-defined", PEF_ACTION_OEM},
+ {"Diagnostic-interrupt", PEF_ACTION_DIAGNOSTIC_INTERRUPT},
+ {NULL}
+} };
+
+static struct bit_desc_map
+pef_b2s_severities __attribute__((unused)) = {
+BIT_DESC_MAP_ANY,
+{ {"Non-recoverable", PEF_SEVERITY_NON_RECOVERABLE},
+ {"Critical", PEF_SEVERITY_CRITICAL},
+ {"Warning", PEF_SEVERITY_WARNING},
+ {"OK", PEF_SEVERITY_OK},
+ {"Information", PEF_SEVERITY_INFORMATION},
+ {"Monitor", PEF_SEVERITY_MONITOR},
+ {NULL}
+} };
+
+static struct bit_desc_map
+pef_b2s_sensortypes __attribute__((unused)) = {
+BIT_DESC_MAP_LIST,
+{ {"Any", 255},
+ {"Temperature", 1},
+ {"Voltage", 2},
+ {"Current", 3},
+ {"Fan", 4},
+ {"Chassis Intrusion", 5},
+ {"Platform security breach", 6},
+ {"Processor", 7},
+ {"Power supply", 8},
+ {"Power Unit", 9},
+ {"Cooling device", 10},
+ {"Other (units-based)", 11},
+ {"Memory", 12},
+ {"Drive Slot", 13},
+ {"POST memory resize", 14},
+ {"POST error", 15},
+ {"Logging disabled", 16},
+ {"Watchdog 1", 17},
+ {"System event", 18},
+ {"Critical Interrupt", 19},
+ {"Button", 20},
+ {"Module/board", 21},
+ {"uController/coprocessor", 22},
+ {"Add-in card", 23},
+ {"Chassis", 24},
+ {"Chipset", 25},
+ {"Other (FRU)", 26},
+ {"Cable/interconnect", 27},
+ {"Terminator", 28},
+ {"System boot", 29},
+ {"Boot error", 30},
+ {"OS boot", 31},
+ {"OS critical stop", 32},
+ {"Slot/connector", 33},
+ {"ACPI power state", 34},
+ {"Watchdog 2", 35},
+ {"Platform alert", 36},
+ {"Entity presence", 37},
+ {"Monitor ASIC/IC", 38},
+ {"LAN", 39},
+ {"Management subsytem health",40},
+ {"Battery", 41},
+ {NULL}
+} };
+
+static struct bit_desc_map
+pef_b2s_gentype_1 = {
+BIT_DESC_MAP_LIST,
+{ {"<LNC", 0}, /* '<' : getting worse */
+ {">LNC", 1}, /* '>' : getting better */
+ {"<LC", 2},
+ {">LC", 3},
+ {"<LNR", 4},
+ {">LNR", 5},
+ {">UNC", 6},
+ {"<UNC", 7},
+ {">UC", 8},
+ {"<UC", 9},
+ {">UNR", 10},
+ {"<UNR", 11},
+ {NULL}
+} };
+
+static struct bit_desc_map
+pef_b2s_gentype_2 = {
+BIT_DESC_MAP_LIST,
+{ {"transition to idle", 0},
+ {"transition to active", 1},
+ {"transition to busy", 2},
+ {NULL}
+} };
+
+static struct bit_desc_map
+pef_b2s_gentype_3 = {
+BIT_DESC_MAP_LIST,
+{ {"state deasserted", 0},
+ {"state asserted", 1},
+ {NULL}
+} };
+
+static struct bit_desc_map
+pef_b2s_gentype_4 = {
+BIT_DESC_MAP_LIST,
+{ {"predictive failure deasserted", 0},
+ {"predictive failure asserted", 1},
+ {NULL}
+} };
+
+static struct bit_desc_map
+pef_b2s_gentype_5 = {
+BIT_DESC_MAP_LIST,
+{ {"limit not exceeded", 0},
+ {"limit exceeded", 1},
+ {NULL}
+} };
+
+static struct bit_desc_map
+pef_b2s_gentype_6 = {
+BIT_DESC_MAP_LIST,
+{ {"performance met", 0},
+ {"performance lags", 1},
+ {NULL}
+} };
+
+static struct bit_desc_map
+pef_b2s_gentype_7 = {
+BIT_DESC_MAP_LIST,
+{ {"ok", 0},
+ {"<warn", 1}, /* '<' : getting worse */
+ {"<fail", 2},
+ {"<dead", 3},
+ {">warn", 4}, /* '>' : getting better */
+ {">fail", 5},
+ {"dead", 6},
+ {"monitor", 7},
+ {"informational", 8},
+ {NULL}
+} };
+
+static struct bit_desc_map
+pef_b2s_gentype_8 = {
+BIT_DESC_MAP_LIST,
+{ {"device removed/absent", 0},
+ {"device inserted/present", 1},
+ {NULL}
+} };
+
+static struct bit_desc_map
+pef_b2s_gentype_9 = {
+BIT_DESC_MAP_LIST,
+{ {"device disabled", 0},
+ {"device enabled", 1},
+ {NULL}
+} };
+
+static struct bit_desc_map
+pef_b2s_gentype_10 = {
+BIT_DESC_MAP_LIST,
+{ {"transition to running", 0},
+ {"transition to in test", 1},
+ {"transition to power off", 2},
+ {"transition to online", 3},
+ {"transition to offline", 4},
+ {"transition to off duty", 5},
+ {"transition to degraded", 6},
+ {"transition to power save", 7},
+ {"install error", 8},
+ {NULL}
+} };
+
+static struct bit_desc_map
+pef_b2s_gentype_11 = {
+BIT_DESC_MAP_LIST,
+{ {"fully redundant", 0},
+ {"redundancy lost", 1},
+ {"redundancy degraded", 2},
+ {"<non-redundant/sufficient", 3}, /* '<' : getting worse */
+ {">non-redundant/sufficient", 4}, /* '>' : getting better */
+ {"non-redundant/insufficient", 5},
+ {"<redundancy degraded", 6},
+ {">redundancy degraded", 7},
+ {NULL}
+} };
+
+static struct bit_desc_map
+pef_b2s_gentype_12 = {
+BIT_DESC_MAP_LIST,
+{ {"D0 power state", 0},
+ {"D1 power state", 1},
+ {"D2 power state", 2},
+ {"D3 power state", 3},
+ {NULL}
+} };
+
+static struct bit_desc_map *
+pef_b2s_generic_ER[] __attribute__((unused)) = {
+ &pef_b2s_gentype_1,
+ &pef_b2s_gentype_2,
+ &pef_b2s_gentype_3,
+ &pef_b2s_gentype_4,
+ &pef_b2s_gentype_5,
+ &pef_b2s_gentype_6,
+ &pef_b2s_gentype_7,
+ &pef_b2s_gentype_8,
+ &pef_b2s_gentype_9,
+ &pef_b2s_gentype_10,
+ &pef_b2s_gentype_11,
+ &pef_b2s_gentype_12,
+};
+#define PEF_B2S_GENERIC_ER_ENTRIES \
+ (sizeof(pef_b2s_generic_ER) / sizeof(pef_b2s_generic_ER[0]))
+
+struct pef_policy_entry {
+#define PEF_POLICY_ID_MASK 0xf0
+#define PEF_POLICY_ID_SHIFT 4
+#define PEF_POLICY_ENABLED 0x08
+#define PEF_POLICY_FLAGS_MASK 0x07
+#define PEF_POLICY_FLAGS_MATCH_ALWAYS 0
+#define PEF_POLICY_FLAGS_PREV_OK_SKIP 1
+#define PEF_POLICY_FLAGS_PREV_OK_NEXT_POLICY_SET 2
+#define PEF_POLICY_FLAGS_PREV_OK_NEXT_CHANNEL_IN_SET 3
+#define PEF_POLICY_FLAGS_PREV_OK_NEXT_DESTINATION_IN_SET 4
+ uint8_t policy;
+#define PEF_POLICY_CHANNEL_MASK 0xf0
+#define PEF_POLICY_CHANNEL_SHIFT 4
+#define PEF_POLICY_DESTINATION_MASK 0x0f
+ uint8_t chan_dest;
+#define PEF_POLICY_EVENT_SPECIFIC 0x80
+ uint8_t alert_string_key;
+} __attribute__ ((packed));
+
+static struct bit_desc_map
+pef_b2s_policies __attribute__((unused)) = {
+BIT_DESC_MAP_LIST,
+{ {"Match-always", PEF_POLICY_FLAGS_MATCH_ALWAYS},
+ {"Try-next-entry", PEF_POLICY_FLAGS_PREV_OK_SKIP},
+ {"Try-next-set", PEF_POLICY_FLAGS_PREV_OK_NEXT_POLICY_SET},
+ {"Try-next-channel", PEF_POLICY_FLAGS_PREV_OK_NEXT_CHANNEL_IN_SET},
+ {"Try-next-destination", PEF_POLICY_FLAGS_PREV_OK_NEXT_DESTINATION_IN_SET},
+ {NULL}
+} };
+
+static struct bit_desc_map
+pef_b2s_ch_medium __attribute__((unused)) = {
+#define PEF_CH_MEDIUM_TYPE_IPMB 1
+#define PEF_CH_MEDIUM_TYPE_ICMB_10 2
+#define PEF_CH_MEDIUM_TYPE_ICMB_09 3
+#define PEF_CH_MEDIUM_TYPE_LAN 4
+#define PEF_CH_MEDIUM_TYPE_SERIAL 5
+#define PEF_CH_MEDIUM_TYPE_XLAN 6
+#define PEF_CH_MEDIUM_TYPE_PCI_SMBUS 7
+#define PEF_CH_MEDIUM_TYPE_SMBUS_V1X 8
+#define PEF_CH_MEDIUM_TYPE_SMBUS_V2X 9
+#define PEF_CH_MEDIUM_TYPE_USB_V1X 10
+#define PEF_CH_MEDIUM_TYPE_USB_V2X 11
+#define PEF_CH_MEDIUM_TYPE_SYSTEM 12
+BIT_DESC_MAP_LIST,
+{ {"IPMB (I2C)", PEF_CH_MEDIUM_TYPE_IPMB},
+ {"ICMB v1.0", PEF_CH_MEDIUM_TYPE_ICMB_10},
+ {"ICMB v0.9", PEF_CH_MEDIUM_TYPE_ICMB_09},
+ {"802.3 LAN", PEF_CH_MEDIUM_TYPE_LAN},
+ {"Serial/Modem (RS-232)", PEF_CH_MEDIUM_TYPE_SERIAL},
+ {"Other LAN", PEF_CH_MEDIUM_TYPE_XLAN},
+ {"PCI SMBus", PEF_CH_MEDIUM_TYPE_PCI_SMBUS},
+ {"SMBus v1.0/1.1", PEF_CH_MEDIUM_TYPE_SMBUS_V1X},
+ {"SMBus v2.0", PEF_CH_MEDIUM_TYPE_SMBUS_V2X},
+ {"USB 1.x", PEF_CH_MEDIUM_TYPE_USB_V1X},
+ {"USB 2.x", PEF_CH_MEDIUM_TYPE_USB_V2X},
+ {"System I/F (KCS,SMIC,BT)", PEF_CH_MEDIUM_TYPE_SYSTEM},
+ {NULL}
+} };
+
+struct pef_cfgparm_selector {
+#define PEF_CFGPARM_ID_REVISION_ONLY_MASK 0x80
+#define PEF_CFGPARM_ID_SET_IN_PROGRESS 0
+#define PEF_CFGPARM_ID_PEF_CONTROL 1
+#define PEF_CFGPARM_ID_PEF_ACTION 2
+#define PEF_CFGPARM_ID_PEF_STARTUP_DELAY 3
+#define PEF_CFGPARM_ID_PEF_ALERT_STARTUP_DELAY 4
+#define PEF_CFGPARM_ID_PEF_FILTER_TABLE_SIZE 5
+#define PEF_CFGPARM_ID_PEF_FILTER_TABLE_ENTRY 6
+#define PEF_CFGPARM_ID_PEF_FILTER_TABLE_DATA_1 7
+#define PEF_CFGPARM_ID_PEF_ALERT_POLICY_TABLE_SIZE 8
+#define PEF_CFGPARM_ID_PEF_ALERT_POLICY_TABLE_ENTRY 9
+#define PEF_CFGPARM_ID_SYSTEM_GUID 10
+#define PEF_CFGPARM_ID_PEF_ALERT_STRING_TABLE_SIZE 11
+#define PEF_CFGPARM_ID_PEF_ALERT_STRING_KEY 12
+#define PEF_CFGPARM_ID_PEF_ALERT_STRING_TABLE_ENTRY 13
+ uint8_t id;
+ uint8_t set;
+ uint8_t block;
+} __attribute__ ((packed));
+
+struct pef_cfgparm_set_in_progress {
+#define PEF_SET_IN_PROGRESS_COMMIT_WRITE 0x02
+#define PEF_SET_IN_PROGRESS 0x01
+ uint8_t data1;
+} __attribute__ ((packed));
+
+struct pef_cfgparm_control {
+#define PEF_CONTROL_ENABLE_ALERT_STARTUP_DELAY 0x08
+#define PEF_CONTROL_ENABLE_STARTUP_DELAY 0x04
+#define PEF_CONTROL_ENABLE_EVENT_MESSAGES 0x02
+#define PEF_CONTROL_ENABLE 0x01
+ uint8_t data1;
+} __attribute__ ((packed));
+
+static struct bit_desc_map
+pef_b2s_control __attribute__((unused)) = {
+BIT_DESC_MAP_ALL,
+{ {"PEF", PEF_CONTROL_ENABLE},
+ {"PEF event messages", PEF_CONTROL_ENABLE_EVENT_MESSAGES},
+ {"PEF startup delay", PEF_CONTROL_ENABLE_STARTUP_DELAY},
+ {"Alert startup delay", PEF_CONTROL_ENABLE_ALERT_STARTUP_DELAY},
+ {NULL}
+} };
+
+struct pef_cfgparm_action {
+#define PEF_ACTION_ENABLE_DIAGNOSTIC_INTERRUPT 0x20
+#define PEF_ACTION_ENABLE_OEM 0x10
+#define PEF_ACTION_ENABLE_POWER_CYCLE 0x08
+#define PEF_ACTION_ENABLE_RESET 0x04
+#define PEF_ACTION_ENABLE_POWER_DOWN 0x02
+#define PEF_ACTION_ENABLE_ALERT 0x01
+ uint8_t data1;
+} __attribute__ ((packed));
+
+struct pef_cfgparm_startup_delay {
+ uint8_t data1;
+} __attribute__ ((packed));
+
+struct pef_cfgparm_alert_startup_delay {
+ uint8_t data1;
+} __attribute__ ((packed));
+
+struct pef_cfgparm_filter_table_size {
+#define PEF_FILTER_TABLE_SIZE_MASK 0x7f
+ uint8_t data1;
+} __attribute__ ((packed));
+
+struct pef_cfgparm_filter_table_entry {
+#define PEF_FILTER_TABLE_ID_MASK 0x7f
+ uint8_t data1;
+ struct pef_table_entry entry;
+} __attribute__ ((packed));
+
+struct pef_cfgparm_filter_table_data_1 {
+ uint8_t data1;
+ uint8_t data2;
+} __attribute__ ((packed));
+
+struct pef_cfgparm_policy_table_size {
+#define PEF_POLICY_TABLE_SIZE_MASK 0x7f
+ uint8_t data1;
+} __attribute__ ((packed));
+
+struct pef_cfgparm_policy_table_entry {
+#define PEF_POLICY_TABLE_ID_MASK 0x7f
+ uint8_t data1;
+ struct pef_policy_entry entry;
+} __attribute__ ((packed));
+
+struct pef_cfgparm_system_guid {
+#define PEF_SYSTEM_GUID_USED_IN_PET 0x01
+ uint8_t data1;
+ uint8_t guid[16];
+} __attribute__ ((packed));
+
+struct pef_cfgparm_alert_string_table_size {
+#define PEF_ALERT_STRING_TABLE_SIZE_MASK 0x7f
+ uint8_t data1;
+} __attribute__ ((packed));
+
+struct pef_cfgparm_alert_string_keys {
+#define PEF_ALERT_STRING_ID_MASK 0x7f
+ uint8_t data1;
+#define PEF_EVENT_FILTER_ID_MASK 0x7f
+ uint8_t data2;
+#define PEF_ALERT_STRING_SET_ID_MASK 0x7f
+ uint8_t data3;
+} __attribute__ ((packed));
+
+struct pef_cfgparm_alert_string_table_entry {
+ uint8_t id;
+ uint8_t blockno;
+ uint8_t block[16];
+} __attribute__ ((packed));
+
+/* PEF - LAN */
+
+struct pef_lan_cfgparm_selector {
+#define PEF_LAN_CFGPARM_CH_REVISION_ONLY_MASK 0x80
+#define PEF_LAN_CFGPARM_CH_MASK 0x0f
+#define PEF_LAN_CFGPARM_ID_PET_COMMUNITY 16
+#define PEF_LAN_CFGPARM_ID_DEST_COUNT 17
+#define PEF_LAN_CFGPARM_ID_DESTTYPE 18
+#define PEF_LAN_CFGPARM_ID_DESTADDR 19
+ uint8_t ch;
+ uint8_t id;
+ uint8_t set;
+ uint8_t block;
+} __attribute__ ((packed));
+
+struct pef_lan_cfgparm_dest_size {
+#define PEF_LAN_DEST_TABLE_SIZE_MASK 0x0f
+ uint8_t data1;
+} __attribute__ ((packed));
+
+struct pef_lan_cfgparm_dest_type {
+#define PEF_LAN_DEST_TYPE_ID_MASK 0x0f
+ uint8_t dest;
+#define PEF_LAN_DEST_TYPE_ACK 0x80
+#define PEF_LAN_DEST_TYPE_MASK 0x07
+#define PEF_LAN_DEST_TYPE_PET 0
+#define PEF_LAN_DEST_TYPE_OEM_1 6
+#define PEF_LAN_DEST_TYPE_OEM_2 7
+ uint8_t dest_type;
+ uint8_t alert_timeout;
+#define PEF_LAN_RETRIES_MASK 0x07
+ uint8_t retries;
+} __attribute__ ((packed));
+
+static struct bit_desc_map
+pef_b2s_lan_desttype __attribute__((unused)) = {
+BIT_DESC_MAP_LIST,
+{ {"Acknowledged", PEF_LAN_DEST_TYPE_ACK},
+ {"PET", PEF_LAN_DEST_TYPE_PET},
+ {"OEM 1", PEF_LAN_DEST_TYPE_OEM_1},
+ {"OEM 2", PEF_LAN_DEST_TYPE_OEM_2},
+ {NULL}
+} };
+
+struct pef_lan_cfgparm_dest_info {
+#define PEF_LAN_DEST_MASK 0x0f
+ uint8_t dest;
+#define PEF_LAN_DEST_ADDRTYPE_MASK 0xf0
+#define PEF_LAN_DEST_ADDRTYPE_SHIFT 4
+#define PEF_LAN_DEST_ADDRTYPE_IPV4_MAC 0x00
+ uint8_t addr_type;
+#define PEF_LAN_DEST_GATEWAY_USE_BACKUP 0x01
+ uint8_t gateway;
+ uint8_t ip[4];
+ uint8_t mac[6];
+} __attribute__ ((packed));
+
+/* PEF - Serial/PPP */
+
+struct pef_serial_cfgparm_selector {
+#define PEF_SERIAL_CFGPARM_CH_REVISION_ONLY_MASK 0x80
+#define PEF_SERIAL_CFGPARM_CH_MASK 0x0f
+#define PEF_SERIAL_CFGPARM_ID_DEST_COUNT 16
+#define PEF_SERIAL_CFGPARM_ID_DESTINFO 17
+#define PEF_SERIAL_CFGPARM_ID_DEST_DIAL_STRING_COUNT 20
+#define PEF_SERIAL_CFGPARM_ID_DEST_DIAL_STRING 21
+#define PEF_SERIAL_CFGPARM_ID_TAP_ACCT_COUNT 24
+#define PEF_SERIAL_CFGPARM_ID_TAP_ACCT_INFO 25
+#define PEF_SERIAL_CFGPARM_ID_TAP_ACCT_PAGER_STRING 27
+ uint8_t ch;
+ uint8_t id;
+ uint8_t set;
+ uint8_t block;
+} __attribute__ ((packed));
+
+struct pef_serial_cfgparm_dest_size {
+#define PEF_SERIAL_DEST_TABLE_SIZE_MASK 0x0f
+ uint8_t data1;
+} __attribute__ ((packed));
+
+struct pef_serial_cfgparm_dest_info {
+#define PEF_SERIAL_DEST_MASK 0x0f
+ uint8_t dest;
+#define PEF_SERIAL_DEST_TYPE_ACK 0x80
+#define PEF_SERIAL_DEST_TYPE_MASK 0x0f
+#define PEF_SERIAL_DEST_TYPE_DIAL 0
+#define PEF_SERIAL_DEST_TYPE_TAP 1
+#define PEF_SERIAL_DEST_TYPE_PPP 2
+#define PEF_SERIAL_DEST_TYPE_BASIC_CALLBACK 3
+#define PEF_SERIAL_DEST_TYPE_PPP_CALLBACK 4
+#define PEF_SERIAL_DEST_TYPE_OEM_1 14
+#define PEF_SERIAL_DEST_TYPE_OEM_2 15
+ uint8_t dest_type;
+ uint8_t alert_timeout;
+#define PEF_SERIAL_RETRIES_MASK 0x77
+#define PEF_SERIAL_RETRIES_POST_CONNECT_MASK 0x70
+#define PEF_SERIAL_RETRIES_PRE_CONNECT_MASK 0x07
+ uint8_t retries;
+#define PEF_SERIAL_DIALPAGE_STRING_ID_MASK 0xf0
+#define PEF_SERIAL_DIALPAGE_STRING_ID_SHIFT 4
+#define PEF_SERIAL_TAP_PAGE_SERVICE_ID_MASK 0x0f
+#define PEF_SERIAL_PPP_ACCT_IPADDR_ID_MASK 0xf0
+#define PEF_SERIAL_PPP_ACCT_IPADDR_ID_SHIFT 4
+#define PEF_SERIAL_PPP_ACCT_ID_MASK 0x0f
+#define PEF_SERIAL_CALLBACK_IPADDR_ID_MASK 0x0f
+#define PEF_SERIAL_CALLBACK_IPADDR_ID_SHIFT 4
+#define PEF_SERIAL_CALLBACK_ACCT_ID_MASK 0xf0
+ uint8_t data5;
+} __attribute__ ((packed));
+
+static struct bit_desc_map
+pef_b2s_serial_desttype __attribute__((unused)) = {
+BIT_DESC_MAP_LIST,
+{ {"Acknowledged", PEF_SERIAL_DEST_TYPE_ACK},
+ {"TAP page", PEF_SERIAL_DEST_TYPE_TAP},
+ {"PPP PET", PEF_SERIAL_DEST_TYPE_PPP},
+ {"Basic callback", PEF_SERIAL_DEST_TYPE_BASIC_CALLBACK},
+ {"PPP callback", PEF_SERIAL_DEST_TYPE_PPP_CALLBACK},
+ {"OEM 1", PEF_SERIAL_DEST_TYPE_OEM_1},
+ {"OEM 2", PEF_SERIAL_DEST_TYPE_OEM_2},
+ {NULL}
+} };
+
+struct pef_serial_cfgparm_dial_string_count {
+#define PEF_SERIAL_DIAL_STRING_COUNT_MASK 0x0f
+ uint8_t data1;
+} __attribute__ ((packed));
+
+struct pef_serial_cfgparm_dial_string {
+#define PEF_SERIAL_DIAL_STRING_MASK 0x0f
+ uint8_t data1;
+ uint8_t data2;
+ uint8_t data3;
+} __attribute__ ((packed));
+
+struct pef_serial_cfgparm_tap_acct_count {
+#define PEF_SERIAL_TAP_ACCT_COUNT_MASK 0x0f
+ uint8_t data1;
+} __attribute__ ((packed));
+
+struct pef_serial_cfgparm_tap_acct_info {
+ uint8_t data1;
+#define PEF_SERIAL_TAP_ACCT_INFO_DIAL_STRING_ID_MASK 0xf0
+#define PEF_SERIAL_TAP_ACCT_INFO_DIAL_STRING_ID_SHIFT 4
+#define PEF_SERIAL_TAP_ACCT_INFO_SVC_SETTINGS_ID_MASK 0x0f
+ uint8_t data2;
+} __attribute__ ((packed));
+
+struct pef_serial_cfgparm_tap_svc_settings {
+ uint8_t data1;
+#define PEF_SERIAL_TAP_CONFIRMATION_ACK_AFTER_ETX 0x0
+#define PEF_SERIAL_TAP_CONFIRMATION_211_ACK_AFTER_ETX 0x01
+#define PEF_SERIAL_TAP_CONFIRMATION_21X_ACK_AFTER_ETX 0x02
+ uint8_t confirmation_flags;
+ uint8_t service_type[3];
+ uint8_t escape_mask[4];
+ uint8_t timeout_parms[3];
+ uint8_t retry_parms[2];
+} __attribute__ ((packed));
+
+static struct bit_desc_map
+pef_b2s_tap_svc_confirm __attribute__((unused)) = {
+BIT_DESC_MAP_LIST,
+{ {"ACK", PEF_SERIAL_TAP_CONFIRMATION_ACK_AFTER_ETX},
+ {"211+ACK", PEF_SERIAL_TAP_CONFIRMATION_211_ACK_AFTER_ETX},
+ {"{211|213}+ACK", PEF_SERIAL_TAP_CONFIRMATION_21X_ACK_AFTER_ETX},
+ {NULL}
+} };
+
+#if 0 /* FYI : config parm groupings */
+ struct pef_config_parms { /* PEF */
+ struct pef_cfgparm_set_in_progress;
+ struct pef_cfgparm_control;
+ struct pef_cfgparm_action;
+ struct pef_cfgparm_startup_delay; /* in seconds, 1-based */
+ struct pef_cfgparm_alert_startup_delay; /* in seconds, 1-based */
+ struct pef_cfgparm_filter_table_size; /* 1-based, READ-ONLY */
+ struct pef_cfgparm_filter_table_entry;
+ struct pef_cfgparm_filter_table_data_1;
+ struct pef_cfgparm_policy_table_size;
+ struct pef_cfgparm_policy_table_entry;
+ struct pef_cfgparm_system_guid;
+ struct pef_cfgparm_alert_string_table_size;
+ struct pef_cfgparm_alert_string_keys;
+ struct pef_cfgparm_alert_string_table_entry;
+ } __attribute__ ((packed));
+
+ struct pef_lan_config_parms { /* LAN */
+ struct pef_lan_cfgparm_set_in_progress;
+ struct pef_lan_cfgparm_auth_capabilities;
+ struct pef_lan_cfgparm_auth_type;
+ struct pef_lan_cfgparm_ip_address;
+ struct pef_lan_cfgparm_ip_address_source;
+ struct pef_lan_cfgparm_mac_address;
+ struct pef_lan_cfgparm_subnet_mask;
+ struct pef_lan_cfgparm_ipv4_header_parms;
+ struct pef_lan_cfgparm_primary_rmcp_port;
+ struct pef_lan_cfgparm_secondary_rmcp_port;
+ struct pef_lan_cfgparm_bmc_generated_arp_control;
+ struct pef_lan_cfgparm_gratuitous_arp;
+ struct pef_lan_cfgparm_default_gateway_ipaddr;
+ struct pef_lan_cfgparm_default_gateway_macaddr;
+ struct pef_lan_cfgparm_backup_gateway_ipaddr;
+ struct pef_lan_cfgparm_backup_gateway_macaddr;
+ struct pef_lan_cfgparm_pet_community;
+ struct pef_lan_cfgparm_destination_count;
+ struct pef_lan_cfgparm_destination_type;
+ struct pef_lan_cfgparm_destination_ipaddr;
+ } __attribute__ ((packed));
+
+ struct pef_serial_config_parms { /* Serial/PPP */
+ struct pef_serial_cfgparm_set_in_progress;
+ struct pef_serial_cfgparm_auth_capabilities;
+ struct pef_serial_cfgparm_auth_type;
+ struct pef_serial_cfgparm_connection_mode;
+ struct pef_serial_cfgparm_idle_timeout;
+ struct pef_serial_cfgparm_callback_control;
+ struct pef_serial_cfgparm_session_termination;
+ struct pef_serial_cfgparm_ipmi_settings;
+ struct pef_serial_cfgparm_mux_control;
+ struct pef_serial_cfgparm_modem_ring_time;
+ struct pef_serial_cfgparm_modem_init_string;
+ struct pef_serial_cfgparm_modem_escape_sequence;
+ struct pef_serial_cfgparm_modem_hangup_sequence;
+ struct pef_serial_cfgparm_modem_dial_command;
+ struct pef_serial_cfgparm_page_blackout_interval;
+ struct pef_serial_cfgparm_pet_community;
+ struct pef_serial_cfgparm_destination_count;
+ struct pef_serial_cfgparm_destination_info;
+ struct pef_serial_cfgparm_call_retry_interval;
+ struct pef_serial_cfgparm_destination_settings;
+ struct pef_serial_cfgparm_dialstring_count;
+ struct pef_serial_cfgparm_dialstring_info;
+ struct pef_serial_cfgparm_ipaddr_count;
+ struct pef_serial_cfgparm_ipaddr_info;
+ struct pef_serial_cfgparm_tap_acct_count;
+ struct pef_serial_cfgparm_tap_acct_info;
+ struct pef_serial_cfgparm_tap_acct_passwords; /* WRITE only */
+ struct pef_serial_cfgparm_tap_pager_id_strings;
+ struct pef_serial_cfgparm_tap_service_settings;
+ struct pef_serial_cfgparm_terminal_mode_config;
+ struct pef_serial_cfgparm_ppp_otions;
+ struct pef_serial_cfgparm_ppp_primary_rmcp_port;
+ struct pef_serial_cfgparm_ppp_secondary_rmcp_port;
+ struct pef_serial_cfgparm_ppp_link_auth;
+ struct pef_serial_cfgparm_ppp_chap_name;
+ struct pef_serial_cfgparm_ppp_accm;
+ struct pef_serial_cfgparm_ppp_snoop_accm;
+ struct pef_serial_cfgparm_ppp_acct_count;
+ struct pef_serial_cfgparm_ppp_acct_dialstring_selector;
+ struct pef_serial_cfgparm_ppp_acct_ipaddrs;
+ struct pef_serial_cfgparm_ppp_acct_user_names;
+ struct pef_serial_cfgparm_ppp_acct_user_domains;
+ struct pef_serial_cfgparm_ppp_acct_user_passwords; /* WRITE only */
+ struct pef_serial_cfgparm_ppp_acct_auth_settings;
+ struct pef_serial_cfgparm_ppp_acct_connect_hold_times;
+ struct pef_serial_cfgparm_ppp_udp_proxy_ipheader;
+ struct pef_serial_cfgparm_ppp_udp_proxy_xmit_bufsize;
+ struct pef_serial_cfgparm_ppp_udp_proxy_recv_bufsize;
+ struct pef_serial_cfgparm_ppp_remote_console_ipaddr;
+ } __attribute__ ((packed));
+#endif
+
+#define IPMI_CMD_GET_PEF_CAPABILITIES 0x10
+#define IPMI_CMD_GET_PEF_CONFIG_PARMS 0x13
+#define IPMI_CMD_GET_LAST_PROCESSED_EVT_ID 0x15
+#define IPMI_CMD_GET_SYSTEM_GUID 0x37
+#define IPMI_CMD_GET_CHANNEL_INFO 0x42
+#define IPMI_CMD_LAN_GET_CONFIG 0x02
+#define IPMI_CMD_SERIAL_GET_CONFIG 0x11
+
+const char * ipmi_pef_bit_desc(struct bit_desc_map * map, uint32_t val);
+void ipmi_pef_print_flags(struct bit_desc_map * map, flg_e type, uint32_t val);
+void ipmi_pef_print_dec(const char * text, uint32_t val);
+void ipmi_pef_print_hex(const char * text, uint32_t val);
+void ipmi_pef_print_1xd(const char * text, uint32_t val);
+void ipmi_pef_print_2xd(const char * text, uint8_t u1, uint8_t u2);
+void ipmi_pef_print_str(const char * text, const char * val);
+
+int ipmi_pef_main(struct ipmi_intf * intf, int argc, char ** argv);
+
+#endif /* IPMI_PEF_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_picmg.h b/lib/lanplus/inc/ipmitool/ipmi_picmg.h
new file mode 100644
index 0000000..ab234e4
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_picmg.h
@@ -0,0 +1,90 @@
+
+/*
+ (C) Kontron
+*/
+
+#ifndef _IPMI_PICMG_H_
+#define _IPMI_PICMG_H_
+
+#include <ipmitool/ipmi.h>
+
+/* 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
+
+/* 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
+
+
+
+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));
+
+
+
+/* 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)) = {
+ " FRU_PICMGEXT_AMC_LINK_TYPE_RESERVED",
+ " FRU_PICMGEXT_AMC_LINK_TYPE_RESERVED1",
+ " FRU_PICMGEXT_AMC_LINK_TYPE_PCI_EXPRESS",
+ " FRU_PICMGEXT_AMC_LINK_TYPE_ADVANCED_SWITCHING1",
+ " FRU_PICMGEXT_AMC_LINK_TYPE_ADVANCED_SWITCHING2",
+ " FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET",
+ " FRU_PICMGEXT_AMC_LINK_TYPE_RAPIDIO",
+ " FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE",
+};
+
+int ipmi_picmg_main (struct ipmi_intf * intf, int argc, char ** argv);
+
+#endif
diff --git a/lib/lanplus/inc/ipmitool/ipmi_raw.h b/lib/lanplus/inc/ipmitool/ipmi_raw.h
new file mode 100644
index 0000000..f4364f3
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_raw.h
@@ -0,0 +1,44 @@
+/*
+ * 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_RAW_H
+#define IPMI_RAW_H
+
+#include <ipmitool/ipmi.h>
+
+int ipmi_raw_main(struct ipmi_intf * intf, int argc, char ** argv);
+struct ipmi_rs * ipmi_master_write_read(struct ipmi_intf * intf, uint8_t bus, uint8_t addr,
+ uint8_t * wdata, uint8_t wsize, uint8_t rsize);
+int ipmi_rawi2c_main(struct ipmi_intf * intf, int argc, char ** argv);
+int ipmi_rawspd_main(struct ipmi_intf * intf, int argc, char ** argv);
+
+#endif /* IPMI_RAW_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_sdr.h b/lib/lanplus/inc/ipmitool/ipmi_sdr.h
new file mode 100644
index 0000000..65b5a8c
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_sdr.h
@@ -0,0 +1,876 @@
+/*
+ * 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_SDR_H
+#define IPMI_SDR_H
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef WIN32
+#include <inttypes-win.h>
+#else
+#include <inttypes.h>
+#endif
+#include <math.h>
+#include <ipmitool/bswap.h>
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_entity.h>
+
+int ipmi_sdr_main(struct ipmi_intf *, int, char **);
+
+#define tos32(val, bits) ((val & ((1<<((bits)-1)))) ? (-((val) & (1<<((bits)-1))) | (val)) : (val))
+
+#if WORDS_BIGENDIAN
+# define __TO_TOL(mtol) (uint16_t)(mtol & 0x3f)
+# define __TO_M(mtol) (int16_t)(tos32((((mtol & 0xff00) >> 8) | ((mtol & 0xc0) << 2)), 10))
+# define __TO_B(bacc) (int32_t)(tos32((((bacc & 0xff000000) >> 24) | ((bacc & 0xc00000) >> 14)), 10))
+# define __TO_ACC(bacc) (uint32_t)(((bacc & 0x3f0000) >> 16) | ((bacc & 0xf000) >> 6))
+# define __TO_ACC_EXP(bacc) (uint32_t)((bacc & 0xc00) >> 10)
+# define __TO_R_EXP(bacc) (int32_t)(tos32(((bacc & 0xf0) >> 4), 4))
+# define __TO_B_EXP(bacc) (int32_t)(tos32((bacc & 0xf), 4))
+#else
+# define __TO_TOL(mtol) (uint16_t)(BSWAP_16(mtol) & 0x3f)
+# define __TO_M(mtol) (int16_t)(tos32((((BSWAP_16(mtol) & 0xff00) >> 8) | ((BSWAP_16(mtol) & 0xc0) << 2)), 10))
+# define __TO_B(bacc) (int32_t)(tos32((((BSWAP_32(bacc) & 0xff000000) >> 24) | \
+ ((BSWAP_32(bacc) & 0xc00000) >> 14)), 10))
+# define __TO_ACC(bacc) (uint32_t)(((BSWAP_32(bacc) & 0x3f0000) >> 16) | ((BSWAP_32(bacc) & 0xf000) >> 6))
+# define __TO_ACC_EXP(bacc) (uint32_t)((BSWAP_32(bacc) & 0xc00) >> 10)
+# define __TO_R_EXP(bacc) (int32_t)(tos32(((BSWAP_32(bacc) & 0xf0) >> 4), 4))
+# define __TO_B_EXP(bacc) (int32_t)(tos32((BSWAP_32(bacc) & 0xf), 4))
+#endif
+
+enum {
+ ANALOG_SENSOR,
+ DISCRETE_SENSOR,
+};
+
+#define READING_UNAVAILABLE 0x20
+#define SCANNING_DISABLED 0x40
+#define EVENT_MSG_DISABLED 0x80
+
+#define IS_READING_UNAVAILABLE(val) ((val) & READING_UNAVAILABLE)
+#define IS_SCANNING_DISABLED(val) (!((val) & SCANNING_DISABLED))
+#define IS_EVENT_MSG_DISABLED(val) (!((val) & EVENT_MSG_DISABLED))
+
+#define GET_SDR_REPO_INFO 0x20
+#define GET_SDR_ALLOC_INFO 0x21
+
+#define SDR_SENSOR_STAT_LO_NC (1<<0)
+#define SDR_SENSOR_STAT_LO_CR (1<<1)
+#define SDR_SENSOR_STAT_LO_NR (1<<2)
+#define SDR_SENSOR_STAT_HI_NC (1<<3)
+#define SDR_SENSOR_STAT_HI_CR (1<<4)
+#define SDR_SENSOR_STAT_HI_NR (1<<5)
+
+#define GET_DEVICE_SDR_INFO 0x20
+#define GET_DEVICE_SDR 0x21
+#define GET_SENSOR_FACTORS 0x23
+#define GET_SENSOR_FACTORS 0x23
+#define SET_SENSOR_HYSTERESIS 0x24
+#define GET_SENSOR_HYSTERESIS 0x25
+#define SET_SENSOR_THRESHOLDS 0x26
+#define GET_SENSOR_THRESHOLDS 0x27
+#define SET_SENSOR_EVENT_ENABLE 0x28
+#define GET_SENSOR_EVENT_ENABLE 0x29
+#define GET_SENSOR_EVENT_STATUS 0x2b
+#define GET_SENSOR_READING 0x2d
+#define GET_SENSOR_TYPE 0x2f
+#define GET_SENSOR_READING 0x2d
+#define GET_SENSOR_TYPE 0x2f
+
+struct sdr_repo_info_rs {
+ uint8_t version; /* SDR version (51h) */
+ uint16_t count; /* number of records */
+ uint16_t free; /* free space in SDR */
+ uint32_t add_stamp; /* last add timestamp */
+ uint32_t erase_stamp; /* last del timestamp */
+ uint8_t op_support; /* supported operations */
+} __attribute__ ((packed));
+
+/* builtin (device) sdrs support */
+struct sdr_device_info_rs {
+ unsigned char count; /* number of records */
+ unsigned char flags; /* flags */
+ unsigned char popChangeInd[3]; /* free space in SDR */
+} __attribute__ ((packed));
+
+#define GET_SDR_RESERVE_REPO 0x22
+struct sdr_reserve_repo_rs {
+ uint16_t reserve_id; /* reservation ID */
+} __attribute__ ((packed));
+
+#define GET_SDR 0x23
+struct sdr_get_rq {
+ uint16_t reserve_id; /* reservation ID */
+ uint16_t id; /* record ID */
+ uint8_t offset; /* offset into SDR */
+#define GET_SDR_ENTIRE_RECORD 0xff
+ uint8_t length; /* length to read */
+} __attribute__ ((packed));
+
+struct sdr_get_rs {
+ uint16_t next; /* next record id */
+ uint16_t id; /* record ID */
+ uint8_t version; /* SDR version (51h) */
+#define SDR_RECORD_TYPE_FULL_SENSOR 0x01
+#define SDR_RECORD_TYPE_COMPACT_SENSOR 0x02
+#define SDR_RECORD_TYPE_EVENTONLY_SENSOR 0x03
+#define SDR_RECORD_TYPE_ENTITY_ASSOC 0x08
+#define SDR_RECORD_TYPE_DEVICE_ENTITY_ASSOC 0x09
+#define SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR 0x10
+#define SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR 0x11
+#define SDR_RECORD_TYPE_MC_DEVICE_LOCATOR 0x12
+#define SDR_RECORD_TYPE_MC_CONFIRMATION 0x13
+#define SDR_RECORD_TYPE_BMC_MSG_CHANNEL_INFO 0x14
+#define SDR_RECORD_TYPE_OEM 0xc0
+ uint8_t type; /* record type */
+ uint8_t length; /* remaining record bytes */
+} __attribute__ ((packed));
+
+struct sdr_record_mask {
+ union {
+ struct {
+ uint16_t assert_event; /* assertion event mask */
+ uint16_t deassert_event; /* de-assertion event mask */
+ uint16_t read; /* discrete reading mask */
+ } discrete;
+ struct {
+#if WORDS_BIGENDIAN
+ uint16_t reserved:1;
+ uint16_t status_lnr:1;
+ uint16_t status_lcr:1;
+ uint16_t status_lnc:1;
+ uint16_t assert_unr_high:1;
+ uint16_t assert_unr_low:1;
+ uint16_t assert_ucr_high:1;
+ uint16_t assert_ucr_low:1;
+ uint16_t assert_unc_high:1;
+ uint16_t assert_unc_low:1;
+ uint16_t assert_lnr_high:1;
+ uint16_t assert_lnr_low:1;
+ uint16_t assert_lcr_high:1;
+ uint16_t assert_lcr_low:1;
+ uint16_t assert_lnc_high:1;
+ uint16_t assert_lnc_low:1;
+#else
+ uint16_t assert_lnc_low:1;
+ uint16_t assert_lnc_high:1;
+ uint16_t assert_lcr_low:1;
+ uint16_t assert_lcr_high:1;
+ uint16_t assert_lnr_low:1;
+ uint16_t assert_lnr_high:1;
+ uint16_t assert_unc_low:1;
+ uint16_t assert_unc_high:1;
+ uint16_t assert_ucr_low:1;
+ uint16_t assert_ucr_high:1;
+ uint16_t assert_unr_low:1;
+ uint16_t assert_unr_high:1;
+ uint16_t status_lnc:1;
+ uint16_t status_lcr:1;
+ uint16_t status_lnr:1;
+ uint16_t reserved:1;
+#endif
+#if WORDS_BIGENDIAN
+ uint16_t reserved_2:1;
+ uint16_t status_unr:1;
+ uint16_t status_ucr:1;
+ uint16_t status_unc:1;
+ uint16_t deassert_unr_high:1;
+ uint16_t deassert_unr_low:1;
+ uint16_t deassert_ucr_high:1;
+ uint16_t deassert_ucr_low:1;
+ uint16_t deassert_unc_high:1;
+ uint16_t deassert_unc_low:1;
+ uint16_t deassert_lnr_high:1;
+ uint16_t deassert_lnr_low:1;
+ uint16_t deassert_lcr_high:1;
+ uint16_t deassert_lcr_low:1;
+ uint16_t deassert_lnc_high:1;
+ uint16_t deassert_lnc_low:1;
+#else
+ uint16_t deassert_lnc_low:1;
+ uint16_t deassert_lnc_high:1;
+ uint16_t deassert_lcr_low:1;
+ uint16_t deassert_lcr_high:1;
+ uint16_t deassert_lnr_low:1;
+ uint16_t deassert_lnr_high:1;
+ uint16_t deassert_unc_low:1;
+ uint16_t deassert_unc_high:1;
+ uint16_t deassert_ucr_low:1;
+ uint16_t deassert_ucr_high:1;
+ uint16_t deassert_unr_low:1;
+ uint16_t deassert_unr_high:1;
+ uint16_t status_unc:1;
+ uint16_t status_ucr:1;
+ uint16_t status_unr:1;
+ uint16_t reserved_2:1;
+#endif
+ union {
+ struct {
+#if WORDS_BIGENDIAN /* settable threshold mask */
+ uint16_t reserved:2;
+ uint16_t unr:1;
+ uint16_t ucr:1;
+ uint16_t unc:1;
+ uint16_t lnr:1;
+ uint16_t lcr:1;
+ uint16_t lnc:1;
+ /* padding lower 8 bits */
+ uint16_t readable:8;
+#else
+ uint16_t readable:8;
+ uint16_t lnc:1;
+ uint16_t lcr:1;
+ uint16_t lnr:1;
+ uint16_t unc:1;
+ uint16_t ucr:1;
+ uint16_t unr:1;
+ uint16_t reserved:2;
+#endif
+ } set;
+ struct {
+#if WORDS_BIGENDIAN /* readable threshold mask */
+ /* padding upper 8 bits */
+ uint16_t settable:8;
+ uint16_t reserved:2;
+ uint16_t unr:1;
+ uint16_t ucr:1;
+ uint16_t unc:1;
+ uint16_t lnr:1;
+ uint16_t lcr:1;
+ uint16_t lnc:1;
+#else
+ uint16_t lnc:1;
+ uint16_t lcr:1;
+ uint16_t lnr:1;
+ uint16_t unc:1;
+ uint16_t ucr:1;
+ uint16_t unr:1;
+ uint16_t reserved:2;
+ uint16_t settable:8;
+#endif
+ } read;
+ };
+ } threshold;
+ } type;
+} __attribute__ ((packed));
+
+struct sdr_record_compact_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 __reserved1:2;
+ uint8_t channel:4; /* channel number */
+#endif
+ uint8_t sensor_num; /* unique sensor number */
+ } keys;
+
+ struct entity_id entity;
+
+ struct {
+ struct {
+#if WORDS_BIGENDIAN
+ uint8_t __reserved2: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 __reserved2:1;
+#endif
+ } 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
+ } capabilities;
+ uint8_t type; /* sensor type */
+ } 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;
+ } type;
+ } unit;
+
+ struct {
+#if WORDS_BIGENDIAN
+ uint8_t __reserved3:2;
+ uint8_t mod_type:2;
+ uint8_t count:4;
+#else
+ uint8_t count:4;
+ uint8_t mod_type:2;
+ uint8_t __reserved3:2;
+#endif
+#if WORDS_BIGENDIAN
+ uint8_t entity_inst:1;
+ uint8_t mod_offset:7;
+#else
+ uint8_t mod_offset:7;
+ uint8_t entity_inst:1;
+#endif
+ } share;
+
+ struct {
+ struct {
+ uint8_t positive;
+ uint8_t negative;
+ } hysteresis;
+ } threshold;
+
+ uint8_t __reserved4[3];
+ 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__ ((packed));
+
+struct sdr_record_eventonly_sensor {
+ struct {
+ uint8_t owner_id;
+#if WORDS_BIGENDIAN
+ uint8_t channel:4; /* channel number */
+ uint8_t fru_owner:2; /* fru device owner lun */
+ uint8_t lun:2; /* sensor owner lun */
+#else
+ uint8_t lun:2; /* sensor owner lun */
+ uint8_t fru_owner:2; /* fru device owner lun */
+ uint8_t channel:4; /* channel number */
+#endif
+ uint8_t sensor_num; /* unique sensor number */
+ } keys;
+
+ struct entity_id entity;
+
+ uint8_t sensor_type; /* sensor type */
+ uint8_t event_type; /* event/reading type code */
+
+ struct {
+#if WORDS_BIGENDIAN
+ uint8_t __reserved1:2;
+ uint8_t mod_type:2;
+ uint8_t count:4;
+#else
+ uint8_t count:4;
+ uint8_t mod_type:2;
+ uint8_t __reserved1:2;
+#endif
+#if WORDS_BIGENDIAN
+ uint8_t entity_inst:1;
+ uint8_t mod_offset:7;
+#else
+ uint8_t mod_offset:7;
+ uint8_t entity_inst:1;
+#endif
+ } share;
+
+ uint8_t __reserved4;
+ 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__ ((packed));
+
+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 __reserved1:2;
+ uint8_t channel:4; /* channel number */
+#endif
+ uint8_t sensor_num; /* unique sensor number */
+ } keys;
+
+ struct entity_id entity;
+
+ struct {
+ struct {
+#if WORDS_BIGENDIAN
+ uint8_t __reserved2: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 __reserved2:1;
+#endif
+ } 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
+ } capabilities;
+ uint8_t type;
+ } 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;
+ } type;
+ } 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 __reserved3: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 __reserved3:5;
+#endif
+ } 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;
+ } upper;
+ struct {
+ uint8_t non_recover;
+ uint8_t critical;
+ uint8_t non_critical;
+ } lower;
+ struct {
+ uint8_t positive;
+ uint8_t negative;
+ } hysteresis;
+ } threshold;
+ uint8_t __reserved4[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__ ((packed));
+
+struct sdr_record_mc_locator {
+ uint8_t dev_slave_addr;
+#if WORDS_BIGENDIAN
+ uint8_t __reserved2:4;
+ uint8_t channel_num:4;
+#else
+ uint8_t channel_num:4;
+ uint8_t __reserved2:4;
+#endif
+#if WORDS_BIGENDIAN
+ uint8_t pwr_state_notif:3;
+ uint8_t __reserved3:1;
+ uint8_t global_init:4;
+#else
+ uint8_t global_init:4;
+ uint8_t __reserved3:1;
+ uint8_t pwr_state_notif:3;
+#endif
+ uint8_t dev_support;
+ uint8_t __reserved4[3];
+ struct entity_id entity;
+ uint8_t oem;
+ uint8_t id_code;
+ uint8_t id_string[16];
+} __attribute__ ((packed));
+
+struct sdr_record_fru_locator {
+ uint8_t dev_slave_addr;
+ uint8_t device_id;
+#if WORDS_BIGENDIAN
+ uint8_t logical:1;
+ uint8_t __reserved2:2;
+ uint8_t lun:2;
+ uint8_t bus:3;
+#else
+ uint8_t bus:3;
+ uint8_t lun:2;
+ uint8_t __reserved2:2;
+ uint8_t logical:1;
+#endif
+#if WORDS_BIGENDIAN
+ uint8_t channel_num:4;
+ uint8_t __reserved3:4;
+#else
+ uint8_t __reserved3:4;
+ uint8_t channel_num:4;
+#endif
+ uint8_t __reserved4;
+ 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_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 __reserved1:5;
+#else
+ uint8_t __reserved1: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));
+
+struct sdr_record_oem {
+ uint8_t *data;
+ int data_len;
+};
+
+/*
+ * The Get SDR Repository Info response structure
+ * From table 33-3 of the IPMI v2.0 spec
+ */
+struct get_sdr_repository_info_rsp {
+ uint8_t sdr_version;
+ uint8_t record_count_lsb;
+ uint8_t record_count_msb;
+ uint8_t free_space[2];
+ uint8_t most_recent_addition_timestamp[4];
+ uint8_t most_recent_erase_timestamp[4];
+#if WORDS_BIGENDIAN
+ uint8_t overflow_flag:1;
+ uint8_t modal_update_support:2;
+ uint8_t __reserved1:1;
+ uint8_t delete_sdr_supported:1;
+ uint8_t partial_add_sdr_supported:1;
+ uint8_t reserve_sdr_repository_supported:1;
+ uint8_t get_sdr_repository_allo_info_supported:1;
+#else
+ uint8_t get_sdr_repository_allo_info_supported:1;
+ uint8_t reserve_sdr_repository_supported:1;
+ uint8_t partial_add_sdr_supported:1;
+ uint8_t delete_sdr_supported:1;
+ uint8_t __reserved1:1;
+ uint8_t modal_update_support:2;
+ uint8_t overflow_flag:1;
+#endif
+} __attribute__ ((packed));
+
+struct ipmi_sdr_iterator {
+ uint16_t reservation;
+ int total;
+ int next;
+};
+
+struct sdr_record_list {
+ uint16_t id;
+ uint8_t version;
+ uint8_t type;
+ uint8_t length;
+ uint8_t *raw;
+ struct sdr_record_list *next;
+ union {
+ struct sdr_record_full_sensor *full;
+ struct sdr_record_compact_sensor *compact;
+ struct sdr_record_eventonly_sensor *eventonly;
+ struct sdr_record_generic_locator *genloc;
+ struct sdr_record_fru_locator *fruloc;
+ struct sdr_record_mc_locator *mcloc;
+ struct sdr_record_entity_assoc *entassoc;
+ struct sdr_record_oem *oem;
+ } record;
+};
+
+/* unit description codes (IPMI v1.5 section 37.16) */
+#define UNIT_MAX 0x90
+static const char *unit_desc[] __attribute__ ((unused)) = {
+"unspecified",
+ "degrees C", "degrees F", "degrees K",
+ "Volts", "Amps", "Watts", "Joules",
+ "Coulombs", "VA", "Nits",
+ "lumen", "lux", "Candela",
+ "kPa", "PSI", "Newton",
+ "CFM", "RPM", "Hz",
+ "microsecond", "millisecond", "second", "minute", "hour",
+ "day", "week", "mil", "inches", "feet", "cu in", "cu feet",
+ "mm", "cm", "m", "cu cm", "cu m", "liters", "fluid ounce",
+ "radians", "steradians", "revolutions", "cycles",
+ "gravities", "ounce", "pound", "ft-lb", "oz-in", "gauss",
+ "gilberts", "henry", "millihenry", "farad", "microfarad",
+ "ohms", "siemens", "mole", "becquerel", "PPM", "reserved",
+ "Decibels", "DbA", "DbC", "gray", "sievert",
+ "color temp deg K", "bit", "kilobit", "megabit", "gigabit",
+ "byte", "kilobyte", "megabyte", "gigabyte", "word", "dword",
+ "qword", "line", "hit", "miss", "retry", "reset",
+ "overflow", "underrun", "collision", "packets", "messages",
+ "characters", "error", "correctable error", "uncorrectable error",};
+
+/* sensor type codes (IPMI v1.5 table 36.3)
+ / Updated to v2.0 Table 42-3, Sensor Type Codes */
+#define SENSOR_TYPE_MAX 0x2C
+static const char *sensor_type_desc[] __attribute__ ((unused)) = {
+"reserved",
+ "Temperature", "Voltage", "Current", "Fan",
+ "Physical Security", "Platform Security", "Processor",
+ "Power Supply", "Power Unit", "Cooling Device", "Other",
+ "Memory", "Drive Slot / Bay", "POST Memory Resize",
+ "System Firmwares", "Event Logging Disabled", "Watchdog",
+ "System Event", "Critical Interrupt", "Button",
+ "Module / Board", "Microcontroller", "Add-in Card",
+ "Chassis", "Chip Set", "Other FRU", "Cable / Interconnect",
+ "Terminator", "System Boot Initiated", "Boot Error",
+ "OS Boot", "OS Critical Stop", "Slot / Connector",
+ "System ACPI Power State", "Watchdog", "Platform Alert",
+ "Entity Presence", "Monitor ASIC", "LAN",
+ "Management Subsystem Health", "Battery","Session Audit",
+ "Version Change","FRU State" };
+
+struct ipmi_sdr_iterator *ipmi_sdr_start(struct ipmi_intf *intf);
+struct sdr_get_rs *ipmi_sdr_get_next_header(struct ipmi_intf *intf,
+ struct ipmi_sdr_iterator *i);
+uint8_t *ipmi_sdr_get_record(struct ipmi_intf *intf, struct sdr_get_rs *header,
+ struct ipmi_sdr_iterator *i);
+void ipmi_sdr_end(struct ipmi_intf *intf, struct ipmi_sdr_iterator *i);
+int ipmi_sdr_print_sdr(struct ipmi_intf *intf, uint8_t type);
+int ipmi_sdr_print_rawentry(struct ipmi_intf *intf, uint8_t type, uint8_t * raw,
+ int len);
+int ipmi_sdr_print_listentry(struct ipmi_intf *intf,
+ struct sdr_record_list *entry);
+char *ipmi_sdr_get_unit_string(uint8_t type, uint8_t base, uint8_t modifier);
+const char *ipmi_sdr_get_status(struct sdr_record_full_sensor *sensor,
+ uint8_t stat);
+double sdr_convert_sensor_tolerance(struct sdr_record_full_sensor *sensor,
+ uint8_t val);
+double sdr_convert_sensor_reading(struct sdr_record_full_sensor *sensor,
+ uint8_t val);
+double sdr_convert_sensor_hysterisis(struct sdr_record_full_sensor *sensor,
+ uint8_t val);
+uint8_t sdr_convert_sensor_value_to_raw(struct sdr_record_full_sensor *sensor,
+ double val);
+struct ipmi_rs *ipmi_sdr_get_sensor_reading(struct ipmi_intf *intf,
+ uint8_t sensor);
+struct ipmi_rs *ipmi_sdr_get_sensor_reading_ipmb(struct ipmi_intf *intf,
+ uint8_t sensor,
+ uint8_t target,
+ uint8_t lun);
+struct ipmi_rs *ipmi_sdr_get_sensor_thresholds(struct ipmi_intf *intf,
+ uint8_t sensor);
+struct ipmi_rs *ipmi_sdr_get_sensor_hysteresis(struct ipmi_intf *intf,
+ uint8_t sensor);
+const char *ipmi_sdr_get_sensor_type_desc(const uint8_t type);
+int ipmi_sdr_get_reservation(struct ipmi_intf *intf, uint16_t * reserve_id);
+
+int ipmi_sdr_print_sensor_full(struct ipmi_intf *intf,
+ struct sdr_record_full_sensor *sensor);
+int ipmi_sdr_print_sensor_compact(struct ipmi_intf *intf,
+ struct sdr_record_compact_sensor *sensor);
+int ipmi_sdr_print_sensor_eventonly(struct ipmi_intf *intf,
+ struct sdr_record_eventonly_sensor *sensor);
+int ipmi_sdr_print_sensor_generic_locator(struct ipmi_intf *intf,
+ struct sdr_record_generic_locator
+ *fru);
+int ipmi_sdr_print_sensor_fru_locator(struct ipmi_intf *intf,
+ struct sdr_record_fru_locator *fru);
+int ipmi_sdr_print_sensor_mc_locator(struct ipmi_intf *intf,
+ struct sdr_record_mc_locator *mc);
+int ipmi_sdr_print_sensor_entity_assoc(struct ipmi_intf *intf,
+ struct sdr_record_entity_assoc *assoc);
+
+struct sdr_record_list *ipmi_sdr_find_sdr_byentity(struct ipmi_intf *intf,
+ struct entity_id *entity);
+struct sdr_record_list *ipmi_sdr_find_sdr_bynumtype(struct ipmi_intf *intf,
+ uint8_t num, uint8_t type);
+struct sdr_record_list *ipmi_sdr_find_sdr_bysensortype(struct ipmi_intf *intf,
+ uint8_t type);
+struct sdr_record_list *ipmi_sdr_find_sdr_byid(struct ipmi_intf *intf,
+ char *id);
+struct sdr_record_list *ipmi_sdr_find_sdr_bytype(struct ipmi_intf *intf,
+ uint8_t type);
+int ipmi_sdr_list_cache(struct ipmi_intf *intf);
+int ipmi_sdr_list_cache_fromfile(struct ipmi_intf *intf, const char *ifile);
+void ipmi_sdr_list_empty(struct ipmi_intf *intf);
+int ipmi_sdr_print_info(struct ipmi_intf *intf);
+void ipmi_sdr_print_discrete_state(const char *desc, uint8_t sensor_type,
+ uint8_t event_type, uint8_t state1,
+ uint8_t state2);
+void ipmi_sdr_print_discrete_state_mini(const char *separator,
+ uint8_t sensor_type, uint8_t event_type,
+ uint8_t state1, uint8_t state2);
+int ipmi_sdr_print_sensor_event_status(struct ipmi_intf *intf,
+ uint8_t sensor_num, uint8_t sensor_type,
+ uint8_t event_type, int numeric_fmt);
+int ipmi_sdr_print_sensor_event_enable(struct ipmi_intf *intf,
+ uint8_t sensor_num, uint8_t sensor_type,
+ uint8_t event_type, int numeric_fmt);
+
+#endif /* IPMI_SDR_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_sel.h b/lib/lanplus/inc/ipmitool/ipmi_sel.h
new file mode 100644
index 0000000..e4ce1d3
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_sel.h
@@ -0,0 +1,542 @@
+/*
+ * 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_SEL_H
+#define IPMI_SEL_H
+
+#ifdef WIN32
+#include <inttypes-win.h>
+#else
+#include <inttypes.h>
+#endif
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_sdr.h>
+
+#define IPMI_CMD_GET_SEL_INFO 0x40
+#define IPMI_CMD_GET_SEL_ALLOC_INFO 0x41
+#define IPMI_CMD_RESERVE_SEL 0x42
+#define IPMI_CMD_GET_SEL_ENTRY 0x43
+#define IPMI_CMD_ADD_SEL_ENTRY 0x44
+#define IPMI_CMD_PARTIAL_ADD_SEL_ENTRY 0x45
+#define IPMI_CMD_DELETE_SEL_ENTRY 0x46
+#define IPMI_CMD_CLEAR_SEL 0x47
+#define IPMI_CMD_GET_SEL_TIME 0x48
+#define IPMI_CMD_SET_SEL_TIME 0x49
+#define IPMI_CMD_GET_AUX_LOG_STATUS 0x5A
+#define IPMI_CMD_SET_AUX_LOG_STATUS 0x5B
+
+enum {
+ IPMI_EVENT_CLASS_DISCRETE,
+ IPMI_EVENT_CLASS_DIGITAL,
+ IPMI_EVENT_CLASS_THRESHOLD,
+ IPMI_EVENT_CLASS_OEM,
+};
+
+struct sel_get_rq {
+ uint16_t reserve_id;
+ uint16_t record_id;
+ uint8_t offset;
+ uint8_t length;
+} __attribute__ ((packed));
+
+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];
+};
+
+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__ ((packed));
+
+struct ipmi_event_sensor_types {
+ uint8_t code;
+ uint8_t offset;
+#define ALL_OFFSETS_SPECIFIED 0xff
+ uint8_t data;
+ uint8_t class;
+ const char * type;
+ const char * desc;
+};
+
+static struct ipmi_event_sensor_types generic_event_types[] __attribute__((unused)) = {
+ /* Threshold Based States */
+ { 0x01, 0x00, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Lower Non-critical going low " },
+ { 0x01, 0x01, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Lower Non-critical going high" },
+ { 0x01, 0x02, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Lower Critical going low " },
+ { 0x01, 0x03, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Lower Critical going high" },
+ { 0x01, 0x04, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Lower Non-recoverable going low " },
+ { 0x01, 0x05, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Lower Non-recoverable going high" },
+ { 0x01, 0x06, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Upper Non-critical going low " },
+ { 0x01, 0x07, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Upper Non-critical going high" },
+ { 0x01, 0x08, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Upper Critical going low " },
+ { 0x01, 0x09, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Upper Critical going high" },
+ { 0x01, 0x0a, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Upper Non-recoverable going low " },
+ { 0x01, 0x0b, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Upper Non-recoverable going high" },
+ /* DMI-based "usage state" States */
+ { 0x02, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Usage State", "Transition to Idle" },
+ { 0x02, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Usage State", "Transition to Active" },
+ { 0x02, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Usage State", "Transition to Busy" },
+ /* Digital-Discrete Event States */
+ { 0x03, 0x00, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "State Deasserted" },
+ { 0x03, 0x01, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "State Asserted" },
+ { 0x04, 0x00, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "Predictive Failure Deasserted" },
+ { 0x04, 0x01, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "Predictive Failure Asserted" },
+ { 0x05, 0x00, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "Limit Not Exceeded" },
+ { 0x05, 0x01, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "Limit Exceeded" },
+ { 0x06, 0x00, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "Performance Met" },
+ { 0x06, 0x01, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "Performance Lags" },
+ /* Severity Event States */
+ { 0x07, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Transition to OK" },
+ { 0x07, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Transition to Non-critical from OK" },
+ { 0x07, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Transition to Critical from less severe" },
+ { 0x07, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Transition to Non-recoverable from less severe" },
+ { 0x07, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Transition to Non-critical from more severe" },
+ { 0x07, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Transition to Critical from Non-recoverable" },
+ { 0x07, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Transition to Non-recoverable" },
+ { 0x07, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Monitor" },
+ { 0x07, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Informational" },
+ /* Availability Status States */
+ { 0x08, 0x00, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Availability State", "Device Absent" },
+ { 0x08, 0x01, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Availability State", "Device Present" },
+ { 0x09, 0x00, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Availability State", "Device Disabled" },
+ { 0x09, 0x01, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Availability State", "Device Enabled" },
+ { 0x0a, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to Running" },
+ { 0x0a, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to In Test" },
+ { 0x0a, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to Power Off" },
+ { 0x0a, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to On Line" },
+ { 0x0a, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to Off Line" },
+ { 0x0a, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to Off Duty" },
+ { 0x0a, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to Degraded" },
+ { 0x0a, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to Power Save" },
+ { 0x0a, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Install Error" },
+ /* Redundancy States */
+ { 0x0b, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Fully Redundant" },
+ { 0x0b, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Redundancy Lost" },
+ { 0x0b, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Redundancy Degraded" },
+ { 0x0b, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Non-Redundant: Sufficient from Redundant" },
+ { 0x0b, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Non-Redundant: Sufficient from Insufficient" },
+ { 0x0b, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Non-Redundant: Insufficient Resources" },
+ { 0x0b, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Redundancy Degraded from Fully Redundant" },
+ { 0x0b, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Redundancy Degraded from Non-Redundant" },
+ /* ACPI Device Power States */
+ { 0x0c, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "ACPI Device Power State", "D0 Power State" },
+ { 0x0c, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "ACPI Device Power State", "D1 Power State" },
+ { 0x0c, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "ACPI Device Power State", "D2 Power State" },
+ { 0x0c, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "ACPI Device Power State", "D3 Power State" },
+ /* END */
+ { 0x00, 0x00, 0xff, 0x00, NULL, NULL },
+};
+
+static struct ipmi_event_sensor_types sensor_specific_types[] __attribute__((unused)) = {
+ { 0x00, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Reserved", NULL },
+ { 0x01, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Temperature", NULL },
+ { 0x02, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Voltage", NULL },
+ { 0x03, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Current", NULL },
+ { 0x04, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Fan", NULL },
+
+ { 0x05, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Physical Security", "General Chassis intrusion" },
+ { 0x05, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Physical Security", "Drive Bay intrusion" },
+ { 0x05, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Physical Security", "I/O Card area intrusion" },
+ { 0x05, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Physical Security", "Processor area intrusion" },
+ { 0x05, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Physical Security", "System unplugged from LAN" },
+ { 0x05, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Physical Security", "Unauthorized dock" },
+ { 0x05, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Physical Security", "FAN area intrusion" },
+
+ { 0x06, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Security", "Front Panel Lockout violation attempted" },
+ { 0x06, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Security", "Pre-boot password violation - user password" },
+ { 0x06, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Security", "Pre-boot password violation - setup password" },
+ { 0x06, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Security", "Pre-boot password violation - network boot password" },
+ { 0x06, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Security", "Other pre-boot password violation" },
+ { 0x06, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Security", "Out-of-band access password violation" },
+
+ { 0x07, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "IERR" },
+ { 0x07, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "Thermal Trip" },
+ { 0x07, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "FRB1/BIST failure" },
+ { 0x07, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "FRB2/Hang in POST failure" },
+ { 0x07, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "FRB3/Processor startup/init failure" },
+ { 0x07, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "Configuration Error" },
+ { 0x07, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "SM BIOS Uncorrectable CPU-complex Error" },
+ { 0x07, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "Presence detected" },
+ { 0x07, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "Disabled" },
+ { 0x07, 0x09, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "Terminator presence detected" },
+ { 0x07, 0x0a, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "Throttled" },
+
+ { 0x08, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Presence detected" },
+ { 0x08, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Failure detected" },
+ { 0x08, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Predictive failure" },
+ { 0x08, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Power Supply AC lost" },
+ { 0x08, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "AC lost or out-of-range" },
+ { 0x08, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "AC out-of-range, but present" },
+ { 0x08, 0x06, 0x00, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Config Error: Vendor Mismatch" },
+ { 0x08, 0x06, 0x01, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Config Error: Revision Mismatch" },
+ { 0x08, 0x06, 0x02, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Config Error: Processor Missing" },
+ { 0x08, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Config Error" },
+
+ { 0x09, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "Power off/down" },
+ { 0x09, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "Power cycle" },
+ { 0x09, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "240VA power down" },
+ { 0x09, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "Interlock power down" },
+ { 0x09, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "AC lost" },
+ { 0x09, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "Soft-power control failure" },
+ { 0x09, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "Failure detected" },
+ { 0x09, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "Predictive failure" },
+
+ { 0x0a, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Cooling Device", NULL },
+ { 0x0b, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Other Units-based Sensor", NULL },
+
+ { 0x0c, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Correctable ECC" },
+ { 0x0c, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Uncorrectable ECC" },
+ { 0x0c, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Parity" },
+ { 0x0c, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Memory Scrub Failed" },
+ { 0x0c, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Memory Device Disabled" },
+ { 0x0c, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Correctable ECC logging limit reached" },
+ { 0x0c, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Presence Detected" },
+ { 0x0c, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Configuration Error" },
+ { 0x0c, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Spare" },
+ { 0x0c, 0x09, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Throttled" },
+
+ { 0x0d, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "Drive Present" },
+ { 0x0d, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "Drive Fault" },
+ { 0x0d, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "Predictive Failure" },
+ { 0x0d, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "Hot Spare" },
+ { 0x0d, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "Parity Check In Progress" },
+ { 0x0d, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "In Critical Array" },
+ { 0x0d, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "In Failed Array" },
+ { 0x0d, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "Rebuild In Progress" },
+ { 0x0d, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "Rebuild Aborted" },
+
+ { 0x0e, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "POST Memory Resize", NULL },
+
+ { 0x0f, 0x00, 0x00, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unspecified" },
+ { 0x0f, 0x00, 0x01, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "No system memory installed" },
+ { 0x0f, 0x00, 0x02, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "No usable system memory" },
+ { 0x0f, 0x00, 0x03, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unrecoverable IDE device failure" },
+ { 0x0f, 0x00, 0x04, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unrecoverable system-board failure" },
+ { 0x0f, 0x00, 0x05, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unrecoverable diskette failure" },
+ { 0x0f, 0x00, 0x06, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unrecoverable hard-disk controller failure" },
+ { 0x0f, 0x00, 0x07, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unrecoverable PS/2 or USB keyboard failure" },
+ { 0x0f, 0x00, 0x08, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Removable boot media not found" },
+ { 0x0f, 0x00, 0x09, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unrecoverable video controller failure" },
+ { 0x0f, 0x00, 0x0a, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "No video device selected" },
+ { 0x0f, 0x00, 0x0b, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "BIOS corruption detected" },
+ { 0x0f, 0x00, 0x0c, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "CPU voltage mismatch" },
+ { 0x0f, 0x00, 0x0d, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "CPU speed mismatch failure" },
+ { 0x0f, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unknown Error" },
+
+ { 0x0f, 0x01, 0x00, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Unspecified" },
+ { 0x0f, 0x01, 0x01, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Memory initialization" },
+ { 0x0f, 0x01, 0x02, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Hard-disk initialization" },
+ { 0x0f, 0x01, 0x03, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Secondary CPU Initialization" },
+ { 0x0f, 0x01, 0x04, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "User authentication" },
+ { 0x0f, 0x01, 0x05, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "User-initiated system setup" },
+ { 0x0f, 0x01, 0x06, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "USB resource configuration" },
+ { 0x0f, 0x01, 0x07, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "PCI resource configuration" },
+ { 0x0f, 0x01, 0x08, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Option ROM initialization" },
+ { 0x0f, 0x01, 0x09, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Video initialization" },
+ { 0x0f, 0x01, 0x0a, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Cache initialization" },
+ { 0x0f, 0x01, 0x0b, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "SMBus initialization" },
+ { 0x0f, 0x01, 0x0c, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Keyboard controller initialization" },
+ { 0x0f, 0x01, 0x0d, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Management controller initialization" },
+ { 0x0f, 0x01, 0x0e, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Docking station attachment" },
+ { 0x0f, 0x01, 0x0f, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Enabling docking station" },
+ { 0x0f, 0x01, 0x10, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Docking station ejection" },
+ { 0x0f, 0x01, 0x11, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Disabling docking station" },
+ { 0x0f, 0x01, 0x12, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Calling operating system wake-up vector" },
+ { 0x0f, 0x01, 0x13, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "System boot initiated" },
+ { 0x0f, 0x01, 0x14, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Motherboard initialization" },
+ { 0x0f, 0x01, 0x15, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "reserved" },
+ { 0x0f, 0x01, 0x16, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Floppy initialization" },
+ { 0x0f, 0x01, 0x17, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Keyboard test" },
+ { 0x0f, 0x01, 0x18, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Pointing device test" },
+ { 0x0f, 0x01, 0x19, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Primary CPU initialization" },
+ { 0x0f, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Unknown Hang" },
+
+ { 0x0f, 0x02, 0x00, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Unspecified" },
+ { 0x0f, 0x02, 0x01, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Memory initialization" },
+ { 0x0f, 0x02, 0x02, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Hard-disk initialization" },
+ { 0x0f, 0x02, 0x03, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Secondary CPU Initialization" },
+ { 0x0f, 0x02, 0x04, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "User authentication" },
+ { 0x0f, 0x02, 0x05, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "User-initiated system setup" },
+ { 0x0f, 0x02, 0x06, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "USB resource configuration" },
+ { 0x0f, 0x02, 0x07, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "PCI resource configuration" },
+ { 0x0f, 0x02, 0x08, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Option ROM initialization" },
+ { 0x0f, 0x02, 0x09, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Video initialization" },
+ { 0x0f, 0x02, 0x0a, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Cache initialization" },
+ { 0x0f, 0x02, 0x0b, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "SMBus initialization" },
+ { 0x0f, 0x02, 0x0c, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Keyboard controller initialization" },
+ { 0x0f, 0x02, 0x0d, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Management controller initialization" },
+ { 0x0f, 0x02, 0x0e, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Docking station attachment" },
+ { 0x0f, 0x02, 0x0f, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Enabling docking station" },
+ { 0x0f, 0x02, 0x10, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Docking station ejection" },
+ { 0x0f, 0x02, 0x11, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Disabling docking station" },
+ { 0x0f, 0x02, 0x12, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Calling operating system wake-up vector" },
+ { 0x0f, 0x02, 0x13, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "System boot initiated" },
+ { 0x0f, 0x02, 0x14, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Motherboard initialization" },
+ { 0x0f, 0x02, 0x15, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "reserved" },
+ { 0x0f, 0x02, 0x16, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Floppy initialization" },
+ { 0x0f, 0x02, 0x17, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Keyboard test" },
+ { 0x0f, 0x02, 0x18, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Pointing device test" },
+ { 0x0f, 0x02, 0x19, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Primary CPU initialization" },
+ { 0x0f, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Unknown Progress" },
+
+ { 0x10, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Event Logging Disabled", "Correctable memory error logging disabled" },
+ { 0x10, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Event Logging Disabled", "Event logging disabled" },
+ { 0x10, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Event Logging Disabled", "Log area reset/cleared" },
+ { 0x10, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Event Logging Disabled", "All event logging disabled" },
+ { 0x10, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Event Logging Disabled", "Log full" },
+ { 0x10, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Event Logging Disabled", "Log almost full" },
+
+ { 0x11, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "BIOS Reset" },
+ { 0x11, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "OS Reset" },
+ { 0x11, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "OS Shut Down" },
+ { 0x11, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "OS Power Down" },
+ { 0x11, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "OS Power Cycle" },
+ { 0x11, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "OS NMI/Diag Interrupt" },
+ { 0x11, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "OS Expired" },
+ { 0x11, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "OS pre-timeout Interrupt" },
+
+ { 0x12, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Event", "System Reconfigured" },
+ { 0x12, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Event", "OEM System boot event" },
+ { 0x12, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Event", "Undetermined system hardware failure" },
+ { 0x12, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Event", "Entry added to auxiliary log" },
+ { 0x12, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Event", "PEF Action" },
+ { 0x12, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Event", "Timestamp Clock Sync" },
+
+ { 0x13, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "NMI/Diag Interrupt" },
+ { 0x13, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "Bus Timeout" },
+ { 0x13, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "I/O Channel check NMI" },
+ { 0x13, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "Software NMI" },
+ { 0x13, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "PCI PERR" },
+ { 0x13, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "PCI SERR" },
+ { 0x13, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "EISA failsafe timeout" },
+ { 0x13, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "Bus Correctable error" },
+ { 0x13, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "Bus Uncorrectable error" },
+ { 0x13, 0x09, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "Fatal NMI" },
+ { 0x13, 0x0a, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "Bus Fatal Error" },
+
+ { 0x14, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Button", "Power Button pressed" },
+ { 0x14, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Button", "Sleep Button pressed" },
+ { 0x14, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Button", "Reset Button pressed" },
+ { 0x14, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Button", "FRU Latch" },
+ { 0x14, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Button", "FRU Service" },
+
+ { 0x15, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Module/Board", NULL },
+ { 0x16, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Microcontroller/Coprocessor", NULL },
+ { 0x17, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Add-in Card", NULL },
+ { 0x18, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Chassis", NULL },
+ { 0x19, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Chip Set", NULL },
+ { 0x1a, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Other FRU", NULL },
+
+ { 0x1b, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Cable/Interconnect", "Connected" },
+ { 0x1b, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Cable/Interconnect", "Config Error" },
+
+ { 0x1c, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Terminator", NULL },
+
+ { 0x1d, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "Initiated by power up" },
+ { 0x1d, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "Initiated by hard reset" },
+ { 0x1d, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "Initiated by warm reset" },
+ { 0x1d, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "User requested PXE boot" },
+ { 0x1d, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "Automatic boot to diagnostic" },
+ { 0x1d, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "OS initiated hard reset" },
+ { 0x1d, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "OS initiated warm reset" },
+ { 0x1d, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "System Restart" },
+
+ { 0x1e, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Boot Error", "No bootable media" },
+ { 0x1e, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Boot Error", "Non-bootable disk in drive" },
+ { 0x1e, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Boot Error", "PXE server not found" },
+ { 0x1e, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Boot Error", "Invalid boot sector" },
+ { 0x1e, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Boot Error", "Timeout waiting for selection" },
+
+ { 0x1f, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "A: boot completed" },
+ { 0x1f, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "C: boot completed" },
+ { 0x1f, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "PXE boot completed" },
+ { 0x1f, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "Diagnostic boot completed" },
+ { 0x1f, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "CD-ROM boot completed" },
+ { 0x1f, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "ROM boot completed" },
+ { 0x1f, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "boot completed - device not specified" },
+
+ { 0x20, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Stop/Shutdown", "Error during system startup" },
+ { 0x20, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Stop/Shutdown", "Run-time critical stop" },
+ { 0x20, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Stop/Shutdown", "OS graceful stop" },
+ { 0x20, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Stop/Shutdown", "OS graceful shutdown" },
+ { 0x20, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Stop/Shutdown", "PEF initiated soft shutdown" },
+ { 0x20, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Stop/Shutdown", "Agent not responding" },
+
+ { 0x21, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Fault Status" },
+ { 0x21, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Identify Status" },
+ { 0x21, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Device Installed" },
+ { 0x21, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Ready for Device Installation" },
+ { 0x21, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Ready for Device Removal" },
+ { 0x21, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Slot Power is Off" },
+ { 0x21, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Device Removal Request" },
+ { 0x21, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Interlock" },
+ { 0x21, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Slot is Disabled" },
+ { 0x21, 0x09, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Spare Device" },
+
+ { 0x22, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S0/G0: working" },
+ { 0x22, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S1: sleeping with system hw & processor context maintained" },
+ { 0x22, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S2: sleeping, processor context lost" },
+ { 0x22, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S3: sleeping, processor & hw context lost, memory retained" },
+ { 0x22, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S4: non-volatile sleep/suspend-to-disk" },
+ { 0x22, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S5/G2: soft-off" },
+ { 0x22, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S4/S5: soft-off" },
+ { 0x22, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "G3: mechanical off" },
+ { 0x22, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "Sleeping in S1/S2/S3 state" },
+ { 0x22, 0x09, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "G1: sleeping" },
+ { 0x22, 0x0a, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S5: entered by override" },
+ { 0x22, 0x0b, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "Legacy ON state" },
+ { 0x22, 0x0c, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "Legacy OFF state" },
+ { 0x22, 0x0e, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "Unknown" },
+
+ { 0x23, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "Timer expired" },
+ { 0x23, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "Hard reset" },
+ { 0x23, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "Power down" },
+ { 0x23, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "Power cycle" },
+ { 0x23, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "reserved" },
+ { 0x23, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "reserved" },
+ { 0x23, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "reserved" },
+ { 0x23, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "reserved" },
+ { 0x23, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "Timer interrupt" },
+
+ { 0x24, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Alert", "Platform generated page" },
+ { 0x24, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Alert", "Platform generated LAN alert" },
+ { 0x24, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Alert", "Platform Event Trap generated" },
+ { 0x24, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Alert", "Platform generated SNMP trap, OEM format" },
+
+ { 0x25, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Entity Presence", "Present" },
+ { 0x25, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Entity Presence", "Absent" },
+ { 0x25, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Entity Presence", "Disabled" },
+
+ { 0x26, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Monitor ASIC/IC", NULL },
+
+ { 0x27, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "LAN", "Heartbeat Lost" },
+ { 0x27, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "LAN", "Heartbeat" },
+
+ { 0x28, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Management Subsystem Health", "Sensor access degraded or unavailable" },
+ { 0x28, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Management Subsystem Health", "Controller access degraded or unavailable" },
+ { 0x28, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Management Subsystem Health", "Management controller off-line" },
+ { 0x28, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Management Subsystem Health", "Management controller unavailable" },
+ { 0x28, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Management Subsystem Health", "Sensor failure" },
+ { 0x28, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Management Subsystem Health", "FRU failure" },
+
+ { 0x29, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Battery", "Low" },
+ { 0x29, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Battery", "Failed" },
+ { 0x29, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Battery", "Presence Detected" },
+
+ { 0x2b, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Hardware change detected" },
+ { 0x2b, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected" },
+ { 0x2b, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Hardware incompatibility detected" },
+ { 0x2b, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software incompatibility detected" },
+ { 0x2b, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Invalid or unsupported hardware version" },
+ { 0x2b, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Invalid or unsupported firmware or software version" },
+ { 0x2b, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Hardware change success" },
+ { 0x2b, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success" },
+
+ { 0x2c, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Not Installed" },
+ { 0x2c, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Inactive" },
+ { 0x2c, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Activation Requested" },
+ { 0x2c, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Activation in Progress" },
+ { 0x2c, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Active" },
+ { 0x2c, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Deactivation Requested" },
+ { 0x2c, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Deactivation in Progress" },
+ { 0x2c, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Communication lost" },
+
+ { 0xF0, 0x00, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M0" },
+ { 0xF0, 0x01, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M1" },
+ { 0xF0, 0x02, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M2" },
+ { 0xF0, 0x03, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M3" },
+ { 0xF0, 0x04, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M4" },
+ { 0xF0, 0x05, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M5" },
+ { 0xF0, 0x06, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M6" },
+ { 0xF0, 0x06, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M7" },
+
+ { 0xF1, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "IPMB-0 Status", "IPMB-A disabled, IPMB-B disabled" },
+ { 0xF1, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "IPMB-0 Status", "IPMB-A enabled, IPMB-B disabled" },
+ { 0xF1, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "IPMB-0 Status", "IPMB-A disabled, IPMB-B enabled" },
+ { 0xF1, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "IPMB-0 Status", "IPMB-A enabled, IPMP-B enabled" },
+
+ { 0xF2, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Module Hot Swap", "Module Handle Closed" },
+ { 0xF2, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Module Hot Swap", "Module Handle Opened" },
+ { 0xF2, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Module Hot Swap", "Quiesced" },
+
+ { 0xC0, 0x00, 0xff, 0x00, "OEM", "OEM Specific" },
+
+ { 0x00, 0x00, 0x00, 0x00, NULL, NULL },
+};
+
+int ipmi_sel_main(struct ipmi_intf *, int, char **);
+void ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt);
+void ipmi_sel_print_std_entry_verbose(struct ipmi_intf * intf, struct sel_event_record * evt);
+void ipmi_sel_print_extended_entry(struct ipmi_intf * intf, struct sel_event_record * evt);
+void ipmi_sel_print_extended_entry_verbose(struct ipmi_intf * intf, struct sel_event_record * evt);
+void ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char ** desc);
+const char * ipmi_sel_get_sensor_type(uint8_t code);
+const char * ipmi_sel_get_sensor_type_offset(uint8_t code, uint8_t offset);
+uint16_t ipmi_sel_get_std_entry(struct ipmi_intf * intf, uint16_t id, struct sel_event_record * evt);
+char * get_newisys_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec);
+IPMI_OEM ipmi_get_oem(struct ipmi_intf * intf);
+char * ipmi_get_oem_desc(struct ipmi_intf * intf, struct sel_event_record * rec);
+int ipmi_sel_oem_init(const char * filename);
+
+#endif /* IPMI_SEL_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_sensor.h b/lib/lanplus/inc/ipmitool/ipmi_sensor.h
new file mode 100644
index 0000000..8c145cf
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_sensor.h
@@ -0,0 +1,84 @@
+/*
+ * 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_SENSOR_H
+#define IPMI_SENSOR_H
+
+#include <math.h>
+#include <ipmitool/bswap.h>
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_sdr.h>
+
+/* threshold specification bits for analog sensors for get sensor threshold command
+ * and set sensor threshold command
+ */
+#define UPPER_NON_RECOV_SPECIFIED 0x20
+#define UPPER_CRIT_SPECIFIED 0x10
+#define UPPER_NON_CRIT_SPECIFIED 0x08
+#define LOWER_NON_RECOV_SPECIFIED 0x04
+#define LOWER_CRIT_SPECIFIED 0x02
+#define LOWER_NON_CRIT_SPECIFIED 0x01
+
+/* state assertion bits for discrete sensors for get sensor reading command */
+#define STATE_0_ASSERTED 0x01
+#define STATE_1_ASSERTED 0x02
+#define STATE_2_ASSERTED 0x04
+#define STATE_3_ASSERTED 0x08
+#define STATE_4_ASSERTED 0x10
+#define STATE_5_ASSERTED 0x20
+#define STATE_6_ASSERTED 0x40
+#define STATE_7_ASSERTED 0x80
+#define STATE_8_ASSERTED 0x01
+#define STATE_9_ASSERTED 0x02
+#define STATE_10_ASSERTED 0x04
+#define STATE_11_ASSERTED 0x08
+#define STATE_12_ASSERTED 0x10
+#define STATE_13_ASSERTED 0x20
+#define STATE_14_ASSERTED 0x40
+
+struct sensor_set_thresh_rq {
+ uint8_t sensor_num; /* sensor # */
+ uint8_t set_mask; /* threshold setting mask */
+ uint8_t lower_non_crit; /* new lower non critical threshold*/
+ uint8_t lower_crit; /* new lower critical threshold*/
+ uint8_t lower_non_recov; /* new lower non recoverable threshold*/
+ uint8_t upper_non_crit; /* new upper non critical threshold*/
+ uint8_t upper_crit; /* new upper critical threshold*/
+ uint8_t upper_non_recov; /* new upper non recoverable threshold*/
+} __attribute__ ((packed));
+
+
+int ipmi_sensor_main(struct ipmi_intf *, int, char **);
+int ipmi_sensor_print_full(struct ipmi_intf *, struct sdr_record_full_sensor *);
+int ipmi_sensor_print_compact(struct ipmi_intf *, struct sdr_record_compact_sensor *);
+
+#endif /* IPMI_SENSOR_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_session.h b/lib/lanplus/inc/ipmitool/ipmi_session.h
new file mode 100644
index 0000000..ad7a09c
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_session.h
@@ -0,0 +1,125 @@
+/*
+ * 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_SESSION_H
+#define IPMI_SESSION_H
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <ipmitool/ipmi.h>
+
+#define IPMI_GET_SESSION_INFO 0x3D
+
+/*
+ * From table 22.25 of the IPMIv2 specification
+ */
+struct get_session_info_rsp
+{
+ uint8_t session_handle;
+
+ #if WORDS_BIGENDIAN
+ uint8_t __reserved1 : 2;
+ uint8_t session_slot_count : 6; /* 1-based */
+ #else
+ uint8_t session_slot_count : 6; /* 1-based */
+ uint8_t __reserved1 : 2;
+ #endif
+
+ #if WORDS_BIGENDIAN
+ uint8_t __reserved2 : 2;
+ uint8_t active_session_count : 6; /* 1-based */
+ #else
+ uint8_t active_session_count : 6; /* 1-based */
+ uint8_t __reserved2 : 2;
+ #endif
+
+ #if WORDS_BIGENDIAN
+ uint8_t __reserved3 : 2;
+ uint8_t user_id : 6;
+ #else
+ uint8_t user_id : 6;
+ uint8_t __reserved3 : 2;
+ #endif
+
+ #if WORDS_BIGENDIAN
+ uint8_t __reserved4 : 4;
+ uint8_t privilege_level : 4;
+ #else
+ uint8_t privilege_level : 4;
+ uint8_t __reserved4 : 4;
+ #endif
+
+ #if WORDS_BIGENDIAN
+ uint8_t auxiliary_data : 4;
+ uint8_t channel_number : 4;
+ #else
+ uint8_t channel_number : 4;
+ uint8_t auxiliary_data : 4;
+ #endif
+
+ union
+ {
+ /* Only exists if channel type is 802.3 LAN */
+ struct
+ {
+ uint8_t console_ip[4]; /* MSBF */
+ uint8_t console_mac[6]; /* MSBF */
+ uint16_t console_port; /* LSBF */
+ } lan_data;
+
+ /* Only exists if channel type is async. serial modem */
+ struct
+ {
+ uint8_t session_channel_activity_type;
+
+ #if WORDS_BIGENDIAN
+ uint8_t __reserved5 : 4;
+ uint8_t destination_selector : 4;
+ #else
+ uint8_t destination_selector : 4;
+ uint8_t __reserved5 : 4;
+ #endif
+
+ uint8_t console_ip[4]; /* MSBF */
+
+ /* Only exists if session is PPP */
+ uint16_t console_port; /* LSBF */
+ } modem_data;
+ } channel_data;
+} __attribute__ ((packed));
+
+
+
+int ipmi_session_main(struct ipmi_intf *, int, char **);
+
+#endif /*IPMI_CHANNEL_H*/
diff --git a/lib/lanplus/inc/ipmitool/ipmi_sol.h b/lib/lanplus/inc/ipmitool/ipmi_sol.h
new file mode 100644
index 0000000..b4c0f6d
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_sol.h
@@ -0,0 +1,84 @@
+/*
+ * 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_SOL_H
+#define IPMI_SOL_H
+
+#include <ipmitool/ipmi.h>
+
+#define SOL_ESCAPE_CHARACTER_DEFAULT '~'
+#define SOL_KEEPALIVE_TIMEOUT 30
+
+#define IPMI_SOL_SERIAL_ALERT_MASK_SUCCEED 0x08
+#define IPMI_SOL_SERIAL_ALERT_MASK_DEFERRED 0x04
+#define IPMI_SOL_SERIAL_ALERT_MASK_FAIL 0x00
+#define IPMI_SOL_BMC_ASSERTS_CTS_MASK_TRUE 0x00
+#define IPMI_SOL_BMC_ASSERTS_CTS_MASK_FALSE 0x02
+
+
+struct sol_config_parameters {
+ uint8_t set_in_progress;
+ uint8_t enabled;
+ uint8_t force_encryption;
+ uint8_t force_authentication;
+ uint8_t privilege_level;
+ uint8_t character_accumulate_level;
+ uint8_t character_send_threshold;
+ uint8_t retry_count;
+ uint8_t retry_interval;
+ uint8_t non_volatile_bit_rate;
+ uint8_t volatile_bit_rate;
+ uint8_t payload_channel;
+ uint16_t payload_port;
+};
+
+
+/*
+ * The ACTIVATE PAYLOAD command reponse structure
+ * From table 24-2 of the IPMI v2.0 spec
+ */
+struct activate_payload_rsp {
+ uint8_t auxiliary_data[4];
+ uint8_t inbound_payload_size[2]; /* LS byte first */
+ uint8_t outbound_payload_size[2]; /* LS byte first */
+ uint8_t payload_udp_port[2]; /* LS byte first */
+ uint8_t payload_vlan_number[2]; /* LS byte first */
+} __attribute__ ((packed));
+
+
+int ipmi_sol_main(struct ipmi_intf *, int, char **);
+int ipmi_get_sol_info(struct ipmi_intf * intf,
+ uint8_t channel,
+ struct sol_config_parameters * params);
+
+
+#endif /* IPMI_SOL_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_strings.h b/lib/lanplus/inc/ipmitool/ipmi_strings.h
new file mode 100644
index 0000000..4116431
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_strings.h
@@ -0,0 +1,60 @@
+/*
+ * 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_STRINGS_H
+#define IPMI_STRINGS_H
+
+#include <ipmitool/helper.h>
+
+extern const struct valstr completion_code_vals[];
+extern const struct valstr entity_id_vals[];
+extern const struct valstr entity_device_type_vals[];
+extern const struct valstr ipmi_netfn_vals[];
+extern const struct valstr ipmi_channel_activity_type_vals[];
+extern const struct valstr ipmi_privlvl_vals[];
+extern const struct valstr impi_bit_rate_vals[];
+extern const struct valstr ipmi_set_in_progress_vals[];
+extern const struct valstr ipmi_authtype_session_vals[];
+extern const struct valstr ipmi_authtype_vals[];
+extern const struct valstr ipmi_channel_protocol_vals[];
+extern const struct valstr ipmi_channel_medium_vals[];
+extern const struct valstr ipmi_chassis_power_control_vals[];
+extern const struct valstr ipmi_auth_algorithms[];
+extern const struct valstr ipmi_integrity_algorithms[];
+extern const struct valstr ipmi_encryption_algorithms[];
+extern const struct valstr ipmi_oem_info[];
+
+extern const struct oemvalstr ipmi_oem_sdr_type_vals[];
+
+
+
+#endif /*IPMI_STRINGS_H*/
diff --git a/lib/lanplus/inc/ipmitool/ipmi_sunoem.h b/lib/lanplus/inc/ipmitool/ipmi_sunoem.h
new file mode 100644
index 0000000..b2cddd1
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_sunoem.h
@@ -0,0 +1,57 @@
+/*
+ * 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
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_sdr.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
+
+int ipmi_sunoem_main(struct ipmi_intf *, int, char **);
+
+struct ipmi_rs * sunoem_led_get(struct ipmi_intf * intf, struct sdr_record_generic_locator * dev, int ledtype);
+struct ipmi_rs * sunoem_led_set(struct ipmi_intf * intf, struct sdr_record_generic_locator * dev, int ledtype, int ledmode);
+
+#endif /*IPMI_SUNOEM_H*/
+
diff --git a/lib/lanplus/inc/ipmitool/ipmi_tsol.h b/lib/lanplus/inc/ipmitool/ipmi_tsol.h
new file mode 100644
index 0000000..8157cd8
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_tsol.h
@@ -0,0 +1,46 @@
+/*
+ * 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 <ipmitool/ipmi.h>
+
+#define IPMI_TSOL_CMD_SENDKEY 0x03
+#define IPMI_TSOL_CMD_START 0x06
+#define IPMI_TSOL_CMD_STOP 0x02
+
+#define IPMI_TSOL_DEF_PORT 6230
+
+int ipmi_tsol_main(struct ipmi_intf *, int, char **);
+
+#endif /* IPMI_TSOL_H */
diff --git a/lib/lanplus/inc/ipmitool/ipmi_user.h b/lib/lanplus/inc/ipmitool/ipmi_user.h
new file mode 100644
index 0000000..f8765ff
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/ipmi_user.h
@@ -0,0 +1,89 @@
+/*
+ * 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_USER_H
+#define IPMI_USER_H
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <ipmitool/ipmi.h>
+
+
+/*
+ * The GET USER ACCESS response from table 22-32 of the IMPI v2.0 spec
+ */
+struct user_access_rsp {
+#if WORDS_BIGENDIAN
+ uint8_t __reserved1 : 2;
+ uint8_t maximum_ids : 6;
+#else
+ uint8_t maximum_ids : 6;
+ uint8_t __reserved1 : 2;
+#endif
+
+#if WORDS_BIGENDIAN
+ uint8_t __reserved2 : 2;
+ uint8_t enabled_user_count : 6;
+#else
+ uint8_t enabled_user_count : 6;
+ uint8_t __reserved2 : 2;
+#endif
+
+#if WORDS_BIGENDIAN
+ uint8_t __reserved3 : 2;
+ uint8_t fixed_name_count : 6;
+#else
+ uint8_t fixed_name_count : 6;
+ uint8_t __reserved3 : 2;
+#endif
+
+#if WORDS_BIGENDIAN
+ uint8_t __reserved4 : 1;
+ uint8_t no_callin_access : 1;
+ uint8_t link_auth_access : 1;
+ uint8_t ipmi_messaging_access : 1;
+ uint8_t channel_privilege_limit : 4;
+#else
+ uint8_t channel_privilege_limit : 4;
+ uint8_t ipmi_messaging_access : 1;
+ uint8_t link_auth_access : 1;
+ uint8_t no_callin_access : 1;
+ uint8_t __reserved4 : 1;
+#endif
+} __attribute__ ((packed));
+
+
+
+int ipmi_user_main(struct ipmi_intf *, int, char **);
+
+#endif /* IPMI_USER_H */
diff --git a/lib/lanplus/inc/ipmitool/log.h b/lib/lanplus/inc/ipmitool/log.h
new file mode 100644
index 0000000..b5dd8c4
--- /dev/null
+++ b/lib/lanplus/inc/ipmitool/log.h
@@ -0,0 +1,74 @@
+/*
+ * 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 IPMITOOL_LOG_H
+#define IPMITOOL_LOG_H
+
+#ifdef WIN32
+#define LOG_EMERG 0
+#define LOG_ALERT 1
+#define LOG_CRIT 2
+#define LOG_ERR 3
+#define LOG_WARNING 4
+#define LOG_NOTICE 5
+#define LOG_INFO 6
+#define LOG_DEBUG 7
+#else
+#include <syslog.h>
+
+/* sys/syslog.h:
+ * LOG_EMERG 0 system is unusable
+ * LOG_ALERT 1 action must be taken immediately
+ * LOG_CRIT 2 critical conditions
+ * LOG_ERR 3 error conditions
+ * LOG_WARNING 4 warning conditions
+ * LOG_NOTICE 5 normal but significant condition
+ * LOG_INFO 6 informational
+ * LOG_DEBUG 7 debug-level messages
+ */
+#endif
+
+#define LOG_ERROR LOG_ERR
+#define LOG_WARN LOG_WARNING
+
+#define LOG_NAME_DEFAULT "ipmitool"
+#define LOG_MSG_LENGTH 1024
+
+void log_init(const char * name, int isdaemon, int verbose);
+void log_halt(void);
+void log_level_set(int level);
+int log_level_get(void);
+void lprintf(int level, const char * format, ...);
+void lperror(int level, const char * format, ...);
+
+#endif /*IPMITOOL_LOG_H*/
+
diff --git a/lib/lanplus/ipmi_strings.c b/lib/lanplus/ipmi_strings.c
new file mode 100644
index 0000000..1bdeca7
--- /dev/null
+++ b/lib/lanplus/ipmi_strings.c
@@ -0,0 +1,348 @@
+/*
+ * 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 <stddef.h>
+#include <ipmitool/ipmi_strings.h>
+#include <ipmitool/ipmi_constants.h>
+#include <ipmitool/ipmi_sensor.h>
+#include <ipmitool/ipmi_sel.h> /* for IPMI_OEM */
+
+const struct valstr ipmi_oem_info[] = {
+
+ { IPMI_OEM_UNKNOWN, "Unknown" },
+ { IPMI_OEM_SUN, "Sun Microsystems" },
+ { IPMI_OEM_INTEL, "Intel Corporation" },
+ { IPMI_OEM_TYAN, "Tyan Computer Corporation" },
+ { IPMI_OEM_NEWISYS, "Newisys" },
+ { IPMI_OEM_SUPERMICRO, "Supermicro" },
+ { IPMI_OEM_GOOGLE, "Google" },
+ { IPMI_OEM_KONTRON, "Kontron" },
+ { IPMI_OEM_NOKIA, "Nokia" },
+ { 0xffff , NULL },
+};
+
+const struct oemvalstr ipmi_oem_sdr_type_vals[] = {
+ /* Keep OEM grouped together */
+ { IPMI_OEM_KONTRON , 0xC0 , "OEM Firmware Info" },
+ { IPMI_OEM_KONTRON , 0xC2 , "OEM Init Agent" },
+ { IPMI_OEM_KONTRON , 0xC3 , "OEM IPMBL Link State" },
+ { IPMI_OEM_KONTRON , 0xC4 , "OEM Board Reset" },
+ { IPMI_OEM_KONTRON , 0xC5 , "OEM FRU Information Agent" },
+ { IPMI_OEM_KONTRON , 0xC6 , "OEM POST Value Sensor" },
+ { IPMI_OEM_KONTRON , 0xC7 , "OEM FWUM Status" },
+ { IPMI_OEM_KONTRON , 0xC8 , "OEM Switch Mngt Software Status" },
+
+ { IPMI_OEM_PICMG , 0xF0 , "PICMG FRU Hotswap" },
+ { IPMI_OEM_PICMG , 0xF1 , "PICMG IPMB0 Link State" },
+
+ { 0xffff, 0x00, NULL }
+};
+
+const struct valstr ipmi_netfn_vals[] = {
+ { IPMI_NETFN_CHASSIS, "Chassis" },
+ { IPMI_NETFN_BRIDGE, "Bridge" },
+ { IPMI_NETFN_SE, "SensorEvent" },
+ { IPMI_NETFN_APP, "Application" },
+ { IPMI_NETFN_FIRMWARE, "Firmware" },
+ { IPMI_NETFN_STORAGE, "Storage" },
+ { IPMI_NETFN_TRANSPORT, "Transport" },
+ { 0xff, NULL },
+};
+
+/*
+ * From table 26-4 of the IPMI v2 specification
+ */
+const struct valstr impi_bit_rate_vals[] = {
+ { 0x00, "IPMI-Over-Serial-Setting"}, /* Using the value in the IPMI Over Serial Config */
+ { 0x06, "9.6" },
+ { 0x07, "19.2" },
+ { 0x08, "38.4" },
+ { 0x09, "57.6" },
+ { 0x0A, "115.2" },
+ { 0x00, NULL },
+};
+
+const struct valstr ipmi_channel_activity_type_vals[] = {
+ { 0, "IPMI Messaging session active" },
+ { 1, "Callback Messaging session active" },
+ { 2, "Dial-out Alert active" },
+ { 3, "TAP Page Active" },
+ { 0x00, NULL },
+};
+
+
+const struct valstr ipmi_privlvl_vals[] = {
+ { IPMI_SESSION_PRIV_CALLBACK, "CALLBACK" },
+ { IPMI_SESSION_PRIV_USER, "USER" },
+ { IPMI_SESSION_PRIV_OPERATOR, "OPERATOR" },
+ { IPMI_SESSION_PRIV_ADMIN, "ADMINISTRATOR" },
+ { IPMI_SESSION_PRIV_OEM, "OEM" },
+ { 0xF, "NO ACCESS" },
+ { 0xFF, NULL },
+};
+
+
+const struct valstr ipmi_set_in_progress_vals[] = {
+ { IPMI_SET_IN_PROGRESS_SET_COMPLETE, "set-complete" },
+ { IPMI_SET_IN_PROGRESS_IN_PROGRESS, "set-in-progress" },
+ { IPMI_SET_IN_PROGRESS_COMMIT_WRITE, "commit-write" },
+ { 0, NULL },
+};
+
+
+const struct valstr ipmi_authtype_session_vals[] = {
+ { IPMI_SESSION_AUTHTYPE_NONE, "NONE" },
+ { IPMI_SESSION_AUTHTYPE_MD2, "MD2" },
+ { IPMI_SESSION_AUTHTYPE_MD5, "MD5" },
+ { IPMI_SESSION_AUTHTYPE_PASSWORD, "PASSWORD" },
+ { IPMI_SESSION_AUTHTYPE_OEM, "OEM" },
+ { 0xFF, NULL },
+};
+
+
+const struct valstr ipmi_authtype_vals[] = {
+ { IPMI_1_5_AUTH_TYPE_BIT_NONE, "NONE" },
+ { IPMI_1_5_AUTH_TYPE_BIT_MD2, "MD2" },
+ { IPMI_1_5_AUTH_TYPE_BIT_MD5, "MD5" },
+ { IPMI_1_5_AUTH_TYPE_BIT_PASSWORD, "PASSWORD" },
+ { IPMI_1_5_AUTH_TYPE_BIT_OEM, "OEM" },
+ { 0, NULL },
+};
+
+const struct valstr entity_id_vals[] = {
+ { 0x00, "Unspecified" },
+ { 0x01, "Other" },
+ { 0x02, "Unknown" },
+ { 0x03, "Processor" },
+ { 0x04, "Disk or Disk Bay" },
+ { 0x05, "Peripheral Bay" },
+ { 0x06, "System Management Module" },
+ { 0x07, "System Board" },
+ { 0x08, "Memory Module" },
+ { 0x09, "Processor Module" },
+ { 0x0a, "Power Supply" },
+ { 0x0b, "Add-in Card" },
+ { 0x0c, "Front Panel Board" },
+ { 0x0d, "Back Panel Board" },
+ { 0x0e, "Power System Board" },
+ { 0x0f, "Drive Backplane" },
+ { 0x10, "System Internal Expansion Board" },
+ { 0x11, "Other System Board" },
+ { 0x12, "Processor Board" },
+ { 0x13, "Power Unit" },
+ { 0x14, "Power Module" },
+ { 0x15, "Power Management" },
+ { 0x16, "Chassis Back Panel Board" },
+ { 0x17, "System Chassis" },
+ { 0x18, "Sub-Chassis" },
+ { 0x19, "Other Chassis Board" },
+ { 0x1a, "Disk Drive Bay" },
+ { 0x1b, "Peripheral Bay" },
+ { 0x1c, "Device Bay" },
+ { 0x1d, "Fan Device" },
+ { 0x1e, "Cooling Unit" },
+ { 0x1f, "Cable/Interconnect" },
+ { 0x20, "Memory Device" },
+ { 0x21, "System Management Software" },
+ { 0x22, "BIOS" },
+ { 0x23, "Operating System" },
+ { 0x24, "System Bus" },
+ { 0x25, "Group" },
+ { 0x26, "Remote Management Device" },
+ { 0x27, "External Environment" },
+ { 0x28, "Battery" },
+ { 0x29, "Processing Blade" },
+ { 0x2A, "Connectivity Switch" },
+ { 0x2B, "Processor/Memory Module" },
+ { 0x2C, "I/O Module" },
+ { 0x2D, "Processor/IO Module" },
+ { 0x2E, "Management Controller Firmware" },
+ { 0x2F, "IPMI Channel" },
+ { 0x30, "PCI Bus" },
+ { 0x31, "PCI Express Bus" },
+ { 0x32, "SCSI Bus (parallel)" },
+ { 0x33, "SATA/SAS Bus" },
+ { 0x34, "Processor/Front-Side Bus" },
+ /* PICMG */
+ { 0xA0, "PICMG Front Board" },
+ { 0xC0, "PICMG Rear Transition Module" },
+ { 0xC1, "PICMG AdvancedMC Module" },
+ { 0xF0, "PICMG Shelf Management Controller" },
+ { 0xF1, "PICMG Filtration Unit" },
+ { 0xF2, "PICMG Shelf FRU Information" },
+ { 0xF3, "PICMG Alarm Panel" },
+ { 0x00, NULL },
+};
+
+const struct valstr entity_device_type_vals[] = {
+ { 0x00, "Reserved" },
+ { 0x01, "Reserved" },
+ { 0x02, "DS1624 temperature sensor" },
+ { 0x03, "DS1621 temperature sensor" },
+ { 0x04, "LM75 Temperature Sensor" },
+ { 0x05, "Heceta ASIC" },
+ { 0x06, "Reserved" },
+ { 0x07, "Reserved" },
+ { 0x08, "EEPROM, 24C01" },
+ { 0x09, "EEPROM, 24C02" },
+ { 0x0a, "EEPROM, 24C04" },
+ { 0x0b, "EEPROM, 24C08" },
+ { 0x0c, "EEPROM, 24C16" },
+ { 0x0d, "EEPROM, 24C17" },
+ { 0x0e, "EEPROM, 24C32" },
+ { 0x0f, "EEPROM, 24C64" },
+ { 0x1000, "IPMI FRU Inventory" },
+ { 0x1001, "DIMM Memory ID" },
+ { 0x1002, "IPMI FRU Inventory" },
+ { 0x1003, "System Processor Cartridge FRU" },
+ { 0x11, "Reserved" },
+ { 0x12, "Reserved" },
+ { 0x13, "Reserved" },
+ { 0x14, "PCF 8570 256 byte RAM" },
+ { 0x15, "PCF 8573 clock/calendar" },
+ { 0x16, "PCF 8574A I/O Port" },
+ { 0x17, "PCF 8583 clock/calendar" },
+ { 0x18, "PCF 8593 clock/calendar" },
+ { 0x19, "Clock calendar" },
+ { 0x1a, "PCF 8591 A/D, D/A Converter" },
+ { 0x1b, "I/O Port" },
+ { 0x1c, "A/D Converter" },
+ { 0x1d, "D/A Converter" },
+ { 0x1e, "A/D, D/A Converter" },
+ { 0x1f, "LCD Controller/Driver" },
+ { 0x20, "Core Logic (Chip set) Device" },
+ { 0x21, "LMC6874 Intelligent Battery controller" },
+ { 0x22, "Intelligent Batter controller" },
+ { 0x23, "Combo Management ASIC" },
+ { 0x24, "Maxim 1617 Temperature Sensor" },
+ { 0xbf, "Other/Unspecified" },
+ { 0x00, NULL },
+};
+
+const struct valstr ipmi_channel_protocol_vals[] = {
+ { 0x00, "reserved" },
+ { 0x01, "IPMB-1.0" },
+ { 0x02, "ICMB-1.0" },
+ { 0x03, "reserved" },
+ { 0x04, "IPMI-SMBus" },
+ { 0x05, "KCS" },
+ { 0x06, "SMIC" },
+ { 0x07, "BT-10" },
+ { 0x08, "BT-15" },
+ { 0x09, "TMode" },
+ { 0x1c, "OEM 1" },
+ { 0x1d, "OEM 2" },
+ { 0x1e, "OEM 3" },
+ { 0x1f, "OEM 4" },
+ { 0x00, NULL },
+};
+
+
+const struct valstr ipmi_channel_medium_vals[] = {
+ { IPMI_CHANNEL_MEDIUM_RESERVED, "reserved" },
+ { IPMI_CHANNEL_MEDIUM_IPMB_I2C, "IPMB (I2C)" },
+ { IPMI_CHANNEL_MEDIUM_ICMB_1, "ICMB v1.0" },
+ { IPMI_CHANNEL_MEDIUM_ICMB_09, "ICMB v0.9" },
+ { IPMI_CHANNEL_MEDIUM_LAN, "802.3 LAN" },
+ { IPMI_CHANNEL_MEDIUM_SERIAL, "Serial/Modem" },
+ { IPMI_CHANNEL_MEDIUM_LAN_OTHER,"Other LAN" },
+ { IPMI_CHANNEL_MEDIUM_SMBUS_PCI,"PCI SMBus" },
+ { IPMI_CHANNEL_MEDIUM_SMBUS_1, "SMBus v1.0/v1.1" },
+ { IPMI_CHANNEL_MEDIUM_SMBUS_2, "SMBus v2.0" },
+ { IPMI_CHANNEL_MEDIUM_USB_1, "USB 1.x" },
+ { IPMI_CHANNEL_MEDIUM_USB_2, "USB 2.x" },
+ { IPMI_CHANNEL_MEDIUM_SYSTEM, "System Interface" },
+ { 0x00, NULL },
+};
+
+const struct valstr completion_code_vals[] = {
+ { 0x00, "Command completed normally" },
+ { 0xc0, "Node busy" },
+ { 0xc1, "Invalid command" },
+ { 0xc2, "Invalid command on LUN" },
+ { 0xc3, "Timeout" },
+ { 0xc4, "Out of space" },
+ { 0xc5, "Reservation 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 number of requested data bytes" },
+ { 0xcb, "Requested sensor, data, or record not found" },
+ { 0xcc, "Invalid data field in request" },
+ { 0xcd, "Command illegal for specified sensor or record type" },
+ { 0xce, "Command response could not be provided" },
+ { 0xcf, "Cannot execute duplicated request" },
+ { 0xd0, "SDR Repository in update mode" },
+ { 0xd1, "Device firmeware in update mode" },
+ { 0xd2, "BMC initialization in progress" },
+ { 0xd3, "Destination unavailable" },
+ { 0xd4, "Insufficient privilege level" },
+ { 0xd5, "Command not supported in present state" },
+ { 0xff, "Unspecified error" },
+ { 0x00, NULL }
+};
+
+const struct valstr ipmi_chassis_power_control_vals[] = {
+ { IPMI_CHASSIS_CTL_POWER_DOWN, "Down/Off" },
+ { IPMI_CHASSIS_CTL_POWER_UP, "Up/On" },
+ { IPMI_CHASSIS_CTL_POWER_CYCLE, "Cycle" },
+ { IPMI_CHASSIS_CTL_HARD_RESET, "Reset" },
+ { IPMI_CHASSIS_CTL_PULSE_DIAG, "Diag" },
+ { IPMI_CHASSIS_CTL_ACPI_SOFT, "Soft" },
+ { 0x00, NULL },
+};
+
+const struct valstr ipmi_auth_algorithms[] = {
+ { IPMI_AUTH_RAKP_NONE, "none" },
+ { IPMI_AUTH_RAKP_HMAC_SHA1, "hmac_sha1" },
+ { IPMI_AUTH_RAKP_HMAC_MD5, "hmac_md5" },
+ { IPMI_AUTH_RAKP_HMAC_SHA256, "hmac_sha256" },
+ { 0x00, NULL }
+};
+
+const struct valstr ipmi_integrity_algorithms[] = {
+ { IPMI_INTEGRITY_NONE, "none" },
+ { IPMI_INTEGRITY_HMAC_SHA1_96, "hmac_sha1_96" },
+ { IPMI_INTEGRITY_HMAC_MD5_128, "hmac_md5_128" },
+ { IPMI_INTEGRITY_MD5_128 , "md5_128" },
+ { IPMI_INTEGRITY_HMAC_SHA256_128, "hmac_sha256_128" },
+ { 0x00, NULL }
+};
+
+const struct valstr ipmi_encryption_algorithms[] = {
+ { IPMI_CRYPT_NONE, "none" },
+ { IPMI_CRYPT_AES_CBC_128, "aes_cbc_128" },
+ { IPMI_CRYPT_XRC4_128, "xrc4_128" },
+ { IPMI_CRYPT_XRC4_40, "xrc4_40" },
+ { 0x00, NULL }
+};
diff --git a/lib/lanplus/ipmiplus.mak b/lib/lanplus/ipmiplus.mak
new file mode 100644
index 0000000..9a1435a
--- /dev/null
+++ b/lib/lanplus/ipmiplus.mak
@@ -0,0 +1,67 @@
+# ipmiplus.mak
+# This makefile will build the ipmiutil lib\lanplus directory
+#
+# Make sure to download and build openssl for Windows first
+#
+
+# The ipmiutil lanplus directory
+SRC_D=.
+INC=/I$(SRC_D) /I$(SRC_D)\inc
+O_LIB=lanplus.lib
+
+# Set your compiler options
+CC=cl
+CF_EX=/DWIN32 $(INC) /D_CONSOLE /DNDEBUG /D_CRT_SECURE_NO_DEPRECATE
+# CFLAGS= /MD /W3 /WX /Ox /O2 /Ob2 /Gs0 /GF /Gy /nologo $(CF_EX)
+# CFLAGS= /W3 /Ox /O2 /Ob2 /Gs0 /GF /Gy /nologo $(CF_EX)
+# CFLAGS= /W3 /O2 /Zi /MD /GF /Gy /nologo $(CF_EX)
+# CFLAGS= /W3 /O2 /Zi /MD /nologo $(CF_EX)
+CFLAGS= /W3 /O2 /Zi /MT /nologo $(CF_EX)
+MKLIB=lib
+RM=del
+
+LIB_OBJ = lanplus.obj lanplus_crypt.obj lanplus_crypt_impl.obj \
+ lanplus_dump.obj lanplus_strings.obj helper.obj ipmi_strings.obj
+
+HEADERS =
+
+all: banner $(O_LIB)
+
+banner:
+ @echo Building ipmi lanplus library
+
+install:
+
+clean:
+ $(RM) *.obj 2>NUL
+ $(RM) $(O_LIB) 2>NUL
+
+distclean:
+ $(RM) *.obj 2>NUL
+ $(RM) $(O_LIB) 2>NUL
+ $(RM) *.lib 2>NUL
+
+lanplus.obj: lanplus.c
+ $(CC) /c $(CFLAGS) lanplus.c
+
+lanplus_crypt.obj: lanplus_crypt.c
+ $(CC) /c $(CFLAGS) lanplus_crypt.c
+
+lanplus_crypt_impl.obj: lanplus_crypt_impl.c
+ $(CC) /c $(CFLAGS) lanplus_crypt_impl.c
+
+lanplus_dump.obj: lanplus_dump.c
+ $(CC) /c $(CFLAGS) lanplus_dump.c
+
+lanplus_strings.obj: lanplus_strings.c
+ $(CC) /c $(CFLAGS) lanplus_strings.c
+
+ipmi_strings.obj: ipmi_strings.c
+ $(CC) /c $(CFLAGS) ipmi_strings.c
+
+helper.obj: helper.c
+ $(CC) /c $(CFLAGS) helper.c
+
+$(O_LIB): $(LIB_OBJ)
+ $(MKLIB) /OUT:$(O_LIB) /nologo $(LIB_OBJ)
+
diff --git a/lib/lanplus/lanplus.c b/lib/lanplus/lanplus.c
new file mode 100644
index 0000000..40d3ab4
--- /dev/null
+++ b/lib/lanplus/lanplus.c
@@ -0,0 +1,4036 @@
+/*
+ * 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.
+ */
+/* ARCress, TODO: improve error handling and remove all assert() calls here. */
+
+#ifdef WIN32
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes-win.h>
+#include <io.h>
+#include <signal.h>
+//#define HAVE_IPV6 1
+#ifdef HAVE_IPV6
+#include <winsock2.h>
+//#include <ws2tcpip.h>
+#else
+#include <winsock.h>
+#endif
+#include <time.h>
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <time.h>
+#include <fcntl.h>
+#include <assert.h>
+#endif
+#if defined(LINUX)
+#define HAVE_IPV6 1
+/* TODO: fixups in BSD/Solaris for ipv6 method */
+#endif
+#if defined(MACOS)
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <ipmitool/helper.h>
+#include <ipmitool/log.h>
+#include <ipmitool/ipmi.h>
+#include <ipmitool/ipmi_lanp.h>
+#include <ipmitool/ipmi_channel.h>
+#include <ipmitool/ipmi_intf.h>
+#include <ipmitool/ipmi_strings.h>
+#include <ipmitool/bswap.h>
+#include <openssl/rand.h>
+
+#include "lanplus.h"
+#include "lanplus_crypt.h"
+#include "lanplus_crypt_impl.h"
+#include "lanplus_dump.h"
+#include "rmcp.h"
+#include "asf.h"
+
+extern const struct valstr ipmi_rakp_return_codes[];
+extern const struct valstr ipmi_priv_levels[];
+extern const struct valstr ipmi_auth_algorithms[];
+extern const struct valstr ipmi_integrity_algorithms[];
+extern const struct valstr ipmi_encryption_algorithms[];
+
+#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
+#endif
+char lan2_nodename[80] = {0}; /*SZGNOE = 80*/
+static int lan2_timeout = IPMI_LAN_TIMEOUT; /*lanplus.h, usu =1*/
+static int slow_link = 0; /* flag, =1 if slow link, latency > 100ms */
+static int recv_delay = 100; /* delay before recv, usually 100us */
+static struct ipmi_rq_entry * ipmi_req_entries;
+static struct ipmi_rq_entry * ipmi_req_entries_tail;
+
+static int ipmi_lanplus_setup(struct ipmi_intf * intf);
+static int ipmi_lanplus_keepalive(struct ipmi_intf * intf);
+static int ipmi_lan_send_packet(struct ipmi_intf * intf, uint8_t * data, int data_len);
+static struct ipmi_rs * ipmi_lan_recv_packet(struct ipmi_intf * intf);
+static struct ipmi_rs * ipmi_lan_poll_recv(struct ipmi_intf * intf);
+static struct ipmi_rs * ipmi_lanplus_send_ipmi_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
+static struct ipmi_rs * ipmi_lanplus_send_payload(struct ipmi_intf * intf,
+ struct ipmi_v2_payload * payload);
+static void getIpmiPayloadWireRep(
+ struct ipmi_intf * intf,
+ struct ipmi_v2_payload * payload, /* in */
+ uint8_t * out,
+ struct ipmi_rq * req,
+ uint8_t rq_seq,
+ uint8_t curr_seq);
+static void getSolPayloadWireRep(
+ struct ipmi_intf * intf,
+ uint8_t * msg,
+ struct ipmi_v2_payload * payload);
+static void read_open_session_response(struct ipmi_rs * rsp, int offset);
+static void read_rakp2_message(struct ipmi_rs * rsp, int offset, uint8_t alg);
+static void read_rakp4_message(struct ipmi_rs * rsp, int offset, uint8_t alg);
+static int read_session_data(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s);
+static int read_session_data_v15(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s);
+static int read_session_data_v2x(struct ipmi_rs * rsp, int * offset, struct ipmi_session *s);
+static void read_ipmi_response(struct ipmi_rs * rsp, int * offset);
+static void read_sol_packet(struct ipmi_rs * rsp, int * offset);
+static struct ipmi_rs * ipmi_lanplus_recv_sol(struct ipmi_intf * intf);
+static struct ipmi_rs * ipmi_lanplus_send_sol( struct ipmi_intf * intf,
+ void * payload);
+static int check_sol_packet_for_new_data(
+ struct ipmi_intf * intf,
+ struct ipmi_rs *rsp);
+static void ack_sol_packet(
+ struct ipmi_intf * intf,
+ struct ipmi_rs * rsp);
+
+static uint8_t bridgePossible = 0;
+
+#if defined(WIN32) || defined(SOLARIS)
+struct ipmi_intf ipmi_lanplus_intf;
+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*/
+}
+#else
+struct ipmi_intf ipmi_lanplus_intf = {
+ name: "lanplus",
+ desc: "IPMI v2.0 RMCP+ LAN Interface",
+ setup: ipmi_lanplus_setup,
+ open: ipmi_lanplus_open,
+ close: ipmi_lanplus_close,
+ sendrecv: ipmi_lanplus_send_ipmi_cmd,
+ recv_sol: ipmi_lanplus_recv_sol,
+ send_sol: ipmi_lanplus_send_sol,
+ keepalive: ipmi_lanplus_keepalive,
+ target_addr: IPMI_BMC_SLAVE_ADDR,
+};
+void ipmilanplus_init(struct ipmi_intf *intf)
+{
+ return;
+}
+#endif
+
+
+extern int verbose;
+
+
+#ifdef WIN32
+WSADATA lan2_ws;
+
+#define assert(N) /*empty*/
+#endif
+
+static
+void lan2_usleep(int s, int u) /*lanplus copy of os_usleep*/
+{
+
+ if (s == 0) {
+#ifdef WIN32
+ if (u >= 1000) Sleep(u/1000);
+ } else {
+ Sleep(s * 1000);
+#else
+ usleep(u);
+ } else {
+ sleep(s);
+#endif
+ }
+}
+
+void show_lasterr(char *tag)
+{
+#ifdef WIN32
+ int rv = 0;
+ rv = WSAGetLastError();
+ fprintf(stderr,"%s LastError = %d\n",tag,rv);
+#else
+ fprintf(stderr,"%s errno = %d\n",tag,errno);
+#endif
+}
+
+/*
+ * lanplus_get_requested_ciphers
+ *
+ * Set the authentication, integrity and encryption algorithms based
+ * on the cipher suite ID. See table 22-19 in the IPMIv2 spec for the
+ * source of this information.
+ *
+ * param cipher_suite_id [in]
+ * param auth_alg [out]
+ * param integrity_alg [out]
+ * param crypt_alg [out]
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+int lanplus_get_requested_ciphers(int cipher_suite_id,
+ uint8_t * auth_alg,
+ uint8_t * integrity_alg,
+ uint8_t * crypt_alg)
+{
+ if ((cipher_suite_id < 0) || (cipher_suite_id > 17))
+ return 1;
+
+ /* See table 22-19 for the source of the statement */
+ switch (cipher_suite_id)
+ {
+ case 0:
+ *auth_alg = IPMI_AUTH_RAKP_NONE;
+ *integrity_alg = IPMI_INTEGRITY_NONE;
+ *crypt_alg = IPMI_CRYPT_NONE;
+ break;
+ case 1:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
+ *integrity_alg = IPMI_INTEGRITY_NONE;
+ *crypt_alg = IPMI_CRYPT_NONE;
+ break;
+ case 2:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
+ *crypt_alg = IPMI_CRYPT_NONE;
+ break;
+ case 3:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
+ *crypt_alg = IPMI_CRYPT_AES_CBC_128;
+ break;
+ case 4:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
+ *crypt_alg = IPMI_CRYPT_XRC4_128;
+ break;
+ case 5:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA1;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_SHA1_96;
+ *crypt_alg = IPMI_CRYPT_XRC4_40;
+ break;
+ case 6:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_NONE;
+ *crypt_alg = IPMI_CRYPT_NONE;
+ break;
+ case 7:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
+ *crypt_alg = IPMI_CRYPT_NONE;
+ break;
+ case 8:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
+ *crypt_alg = IPMI_CRYPT_AES_CBC_128;
+ break;
+ case 9:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
+ *crypt_alg = IPMI_CRYPT_XRC4_128;
+ break;
+ case 10:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_MD5_128;
+ *crypt_alg = IPMI_CRYPT_XRC4_40;
+ break;
+ case 11:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_MD5_128;
+ *crypt_alg = IPMI_CRYPT_NONE;
+ break;
+ case 12:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_MD5_128;
+ *crypt_alg = IPMI_CRYPT_AES_CBC_128;
+ break;
+ case 13:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_MD5_128;
+ *crypt_alg = IPMI_CRYPT_XRC4_128;
+ break;
+ case 14:
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_MD5;
+ *integrity_alg = IPMI_INTEGRITY_MD5_128;
+ *crypt_alg = IPMI_CRYPT_XRC4_40;
+ break;
+#if 0
+ case 15: // Note: Cipher Suite ID not (yet) confirmed in IPMI Spec or Errata 4
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA256;
+ *integrity_alg = IPMI_INTEGRITY_NONE;
+ *crypt_alg = IPMI_CRYPT_NONE;
+ break;
+ case 16: // Note: Cipher Suite ID not (yet) confirmed in IPMI Spec or Errata 4
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA256;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_SHA256_128;
+ *crypt_alg = IPMI_CRYPT_NONE;
+ break;
+#endif
+#ifdef HAVE_SHA256
+ /* based on an MD5_SHA256 patch from Holger Liebig */
+ case 17: // Note: Cipher Suite Id from DCMI 1.1 Spec
+ *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA256;
+ *integrity_alg = IPMI_INTEGRITY_HMAC_SHA256_128;
+ *crypt_alg = IPMI_CRYPT_AES_CBC_128;
+ break;
+#endif
+ default:
+ lprintf(LOG_ERR, "invalid cipher suite id %d",cipher_suite_id);
+ return 1;
+ break;
+
+ }
+
+ return 0;
+}
+
+
+
+/*
+ * Reverse the order of arbitrarily long strings of bytes
+ */
+void lanplus_swap(
+ uint8_t * buffer,
+ int length)
+{
+ int i;
+ uint8_t temp;
+
+ for (i =0; i < length/2; ++i)
+ {
+ temp = buffer[i];
+ buffer[i] = buffer[length - 1 - i];
+ buffer[length - 1 - i] = temp;
+ }
+}
+
+void lanplus_set_recvdelay( int delay)
+{
+ /* set the delay between send & recv in usec, default = 100us */
+ recv_delay = delay;
+ if (delay > 100) {
+ slow_link = 1;
+ lan2_timeout = 2;
+ }
+}
+
+
+static const struct valstr plus_payload_types_vals[] = {
+ { IPMI_PAYLOAD_TYPE_IPMI, "IPMI (0)" }, // IPMI Message
+ { IPMI_PAYLOAD_TYPE_SOL, "SOL (1)" }, // SOL (Serial over LAN)
+ { IPMI_PAYLOAD_TYPE_OEM, "OEM (2)" }, // OEM Explicid
+
+ { IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST, "OpenSession Req (0x10)" },
+ { IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE,"OpenSession Resp (0x11)" },
+ { IPMI_PAYLOAD_TYPE_RAKP_1, "RAKP1 (0x12)" },
+ { IPMI_PAYLOAD_TYPE_RAKP_2, "RAKP2 (0x13)" },
+ { IPMI_PAYLOAD_TYPE_RAKP_3, "RAKP3 (0x14)" },
+ { IPMI_PAYLOAD_TYPE_RAKP_4, "RAKP4 (0x15)" },
+ { 0x00, NULL },
+};
+
+
+static struct ipmi_rq_entry *
+ipmi_req_add_entry(struct ipmi_intf * intf, struct ipmi_rq * req, uint8_t req_seq)
+{
+ struct ipmi_rq_entry * e;
+
+ e = malloc(sizeof(struct ipmi_rq_entry));
+ if (e == NULL) {
+ lprintf(LOG_ERR, "lanplus: malloc failure");
+ return NULL;
+ }
+
+ memset(e, 0, sizeof(struct ipmi_rq_entry));
+ memcpy(&e->req, req, sizeof(struct ipmi_rq));
+
+ e->intf = intf;
+ e->rq_seq = req_seq;
+
+ if (ipmi_req_entries == NULL)
+ ipmi_req_entries = e;
+ else
+ ipmi_req_entries_tail->next = e;
+
+ ipmi_req_entries_tail = e;
+ lprintf(LOG_DEBUG+3, "added list entry seq=0x%02x cmd=0x%02x",
+ e->rq_seq, e->req.msg.cmd);
+ return e;
+}
+
+
+static struct ipmi_rq_entry *
+ipmi_req_lookup_entry(uint8_t seq, uint8_t cmd)
+{
+ struct ipmi_rq_entry * e = ipmi_req_entries;
+ while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) {
+ if (e == e->next)
+ return NULL;
+ e = e->next;
+ }
+ return e;
+}
+
+static void
+ipmi_req_remove_entry(uint8_t seq, uint8_t cmd)
+{
+ struct ipmi_rq_entry * p, * e, *saved_next_entry;
+
+ e = p = ipmi_req_entries;
+
+ while (e && (e->rq_seq != seq || e->req.msg.cmd != cmd)) {
+ p = e;
+ e = e->next;
+ }
+ if (e) {
+ lprintf(LOG_DEBUG+3, "removed list entry seq=0x%02x cmd=0x%02x",
+ seq, cmd);
+ saved_next_entry = e->next;
+ p->next = (p->next == e->next) ? NULL : e->next;
+ /* If entry being removed is first in list, fix up list head */
+ if (ipmi_req_entries == e) {
+ if (ipmi_req_entries != p)
+ ipmi_req_entries = p;
+ else
+ ipmi_req_entries = saved_next_entry;
+ }
+ /* If entry being removed is last in list, fix up list tail */
+ if (ipmi_req_entries_tail == e) {
+ if (ipmi_req_entries_tail != p)
+ ipmi_req_entries_tail = p;
+ else
+ ipmi_req_entries_tail = NULL;
+ }
+
+ if (e->msg_data)
+ free(e->msg_data);
+ free(e);
+ }
+}
+
+static void
+ipmi_req_clear_entries(void)
+{
+ struct ipmi_rq_entry * p, * e;
+
+ e = ipmi_req_entries;
+ while (e) {
+ lprintf(LOG_DEBUG+3, "cleared list entry seq=0x%02x cmd=0x%02x",
+ e->rq_seq, e->req.msg.cmd);
+ p = e->next;
+ if (e->msg_data) free(e->msg_data); /*added in v2.8.5*/
+ free(e);
+ e = p;
+ }
+ ipmi_req_entries = NULL;
+}
+
+
+int
+ipmi_lan_send_packet(
+ struct ipmi_intf * intf,
+ uint8_t * data, int
+ data_len)
+{
+ if (verbose >= 5)
+ printbuf(data, data_len, ">> sending packet");
+
+ return send(intf->fd, data, data_len, 0);
+}
+
+
+
+struct ipmi_rs *
+ipmi_lan_recv_packet(struct ipmi_intf * intf)
+{
+ static struct ipmi_rs rsp;
+ fd_set read_set, err_set;
+ struct timeval tmout;
+ int ret = 0;
+ int er,rd;
+
+ FD_ZERO(&read_set);
+ FD_SET(intf->fd, &read_set);
+
+ FD_ZERO(&err_set);
+ FD_SET(intf->fd, &err_set);
+
+ tmout.tv_sec = intf->session->timeout;
+ tmout.tv_usec = 0;
+ ret = select((int)(intf->fd + 1), &read_set, NULL, &err_set, &tmout);
+ er = FD_ISSET(intf->fd, &err_set);
+ rd = FD_ISSET(intf->fd, &read_set);
+ if (ret < 0 || er || !rd) {
+ if (verbose >= 5)
+ lprintf(LOG_INFO, "select1 error ret=%d, err=%d read=%d",
+ ret,er,rd);
+ return NULL;
+ }
+
+ /* the first read may return ECONNREFUSED because the rmcp ping
+ * packet--sent to UDP port 623--will be processed by both the
+ * BMC and the OS.
+ *
+ * The problem with this is that the ECONNREFUSED takes
+ * priority over any other received datagram; that means that
+ * the Connection Refused shows up _before_ the response packet,
+ * regardless of the order they were sent out. (unless the
+ * response is read before the connection refused is returned)
+ */
+#ifdef WIN32
+ ret = recv(intf->fd, &rsp.data[0], IPMI_BUF_SIZE, 0);
+#else
+ ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0);
+#endif
+
+ if (ret < 0) {
+ if (verbose >= 5) lprintf(LOG_INFO, "recv1 ret=%d",ret);
+ FD_ZERO(&read_set);
+ FD_SET(intf->fd, &read_set);
+
+ FD_ZERO(&err_set);
+ FD_SET(intf->fd, &err_set);
+
+ tmout.tv_sec = intf->session->timeout;
+ tmout.tv_usec = 0;
+
+ ret = select((int)(intf->fd + 1), &read_set, NULL, &err_set, &tmout);
+ if (ret < 0) {
+ if (FD_ISSET(intf->fd, &err_set) || !FD_ISSET(intf->fd, &read_set)) {
+ if (verbose >= 5)
+ lprintf(LOG_INFO,"select2 error ret=%d",ret);
+ return NULL;
+ }
+
+#ifdef WIN32
+ ret = recv(intf->fd, &rsp.data[0], IPMI_BUF_SIZE, 0);
+#else
+ ret = recv(intf->fd, &rsp.data, IPMI_BUF_SIZE, 0);
+#endif
+ if (ret < 0) {
+ if (verbose >= 5)
+ lprintf(LOG_INFO, "recv2 ret=%d",ret);
+ return NULL;
+ }
+ }
+ }
+
+ if (ret == 0) {
+ if (verbose >= 5) lprintf(LOG_INFO, "recv ret==0");
+ return NULL;
+ }
+
+ rsp.data[ret] = '\0';
+ rsp.data_len = ret;
+
+ if (verbose >= 5)
+ printbuf(rsp.data, rsp.data_len, "<< received packet");
+
+ return &rsp;
+}
+
+
+
+/*
+ * parse response RMCP "pong" packet
+ *
+ * return -1 if ping response not received
+ * returns 0 if IPMI is NOT supported
+ * returns 1 if IPMI is supported
+ *
+ * udp.source = 0x026f // RMCP_UDP_PORT
+ * udp.dest = ? // udp.source from rmcp-ping
+ * udp.len = ?
+ * udp.check = ?
+ * rmcp.ver = 0x06 // RMCP Version 1.0
+ * rmcp.__res = 0x00 // RESERVED
+ * rmcp.seq = 0xff // no RMCP ACK
+ * rmcp.class = 0x06 // RMCP_CLASS_ASF
+ * asf.iana = 0x000011be // ASF_RMCP_IANA
+ * asf.type = 0x40 // ASF_TYPE_PONG
+ * asf.tag = ? // asf.tag from rmcp-ping
+ * asf.__res = 0x00 // RESERVED
+ * asf.len = 0x10 // 16 bytes
+ * asf.data[3:0]= 0x000011be // IANA# = RMCP_ASF_IANA if no OEM
+ * asf.data[7:4]= 0x00000000 // OEM-defined (not for IPMI)
+ * asf.data[8] = 0x81 // supported entities
+ * // [7]=IPMI [6:4]=RES [3:0]=ASF_1.0
+ * asf.data[9] = 0x00 // supported interactions (reserved)
+ * asf.data[f:a]= 0x000000000000
+ */
+static int
+ipmi_handle_pong(struct ipmi_intf * intf, struct ipmi_rs * rsp)
+{
+ struct rmcp_pong {
+ struct rmcp_hdr rmcp;
+ struct asf_hdr asf;
+ uint32_t iana;
+ uint32_t oem;
+ uint8_t sup_entities;
+ uint8_t sup_interact;
+ uint8_t reserved[6];
+ } * pong;
+
+ if (!rsp)
+ return -1;
+
+ pong = (struct rmcp_pong *)rsp->data;
+
+ if (verbose)
+ printf("Received IPMI/RMCP response packet: "
+ "IPMI%s Supported\n",
+ (pong->sup_entities & 0x80) ? "" : " NOT");
+
+ if (verbose > 1)
+ printf(" ASF Version %s\n"
+ " RMCP Version %s\n"
+ " RMCP Sequence %d\n"
+ " IANA Enterprise %lu\n\n",
+ (pong->sup_entities & 0x01) ? "1.0" : "unknown",
+ (pong->rmcp.ver == 6) ? "1.0" : "unknown",
+ pong->rmcp.seq,
+ (unsigned long)ntohl(pong->iana));
+
+ return (pong->sup_entities & 0x80) ? 1 : 0;
+}
+
+
+/* build and send RMCP presence ping packet
+ *
+ * RMCP ping
+ *
+ * udp.source = ?
+ * udp.dest = 0x026f // RMCP_UDP_PORT
+ * udp.len = ?
+ * udp.check = ?
+ * rmcp.ver = 0x06 // RMCP Version 1.0
+ * rmcp.__res = 0x00 // RESERVED
+ * rmcp.seq = 0xff // no RMCP ACK
+ * rmcp.class = 0x06 // RMCP_CLASS_ASF
+ * asf.iana = 0x000011be // ASF_RMCP_IANA
+ * asf.type = 0x80 // ASF_TYPE_PING
+ * asf.tag = ? // ASF sequence number
+ * asf.__res = 0x00 // RESERVED
+ * asf.len = 0x00
+ *
+ */
+int
+ipmiv2_lan_ping(struct ipmi_intf * intf)
+{
+ uint8_t * data;
+ int rv;
+#if defined(WIN32) || defined(SOLARIS)
+ struct asf_hdr asf_ping;
+ struct rmcp_hdr rmcp_ping;
+ int len = sizeof(rmcp_ping) + sizeof(asf_ping);
+
+ asf_ping.iana = htonl(ASF_RMCP_IANA);
+ asf_ping.type = ASF_TYPE_PING;
+ rmcp_ping.ver = RMCP_VERSION_1;
+ rmcp_ping.__rsvd = 0;
+ rmcp_ping.class = RMCP_CLASS_ASF;
+ rmcp_ping.seq = 0xff;
+#else
+ struct asf_hdr asf_ping = {
+ .iana = htonl(ASF_RMCP_IANA),
+ .type = ASF_TYPE_PING,
+ };
+ struct rmcp_hdr rmcp_ping = {
+ .ver = RMCP_VERSION_1,
+ .__rsvd = 0,
+ .class = RMCP_CLASS_ASF,
+ .seq = 0xff,
+ };
+ int len = sizeof(rmcp_ping) + sizeof(asf_ping);
+#endif
+
+ data = malloc(len);
+ if (data == NULL) {
+ lprintf(LOG_ERR, "lanplus: malloc failure");
+ return -1;
+ }
+ memset(data, 0, len);
+ memcpy(data, &rmcp_ping, sizeof(rmcp_ping));
+ memcpy(data+sizeof(rmcp_ping), &asf_ping, sizeof(asf_ping));
+
+ lprintf(LOG_DEBUG, "Sending IPMI/RMCP presence ping packet");
+
+ rv = ipmi_lan_send_packet(intf, data, len);
+
+ free(data);
+
+ if (rv < 0) {
+ lprintf(LOG_ERR, "Unable to send IPMI presence ping packet");
+ return -1;
+ }
+
+ if (ipmi_lan_poll_recv(intf) == 0) /*NULL rsp*/
+ return 0;
+
+ return 1;
+}
+
+
+/**
+ *
+ * ipmi_lan_poll_recv
+ *
+ * Receive whatever comes back. Ignore received packets that don't correspond
+ * to a request we've sent.
+ *
+ * Returns: the ipmi_rs packet describing the/a reponse we expect.
+ */
+static struct ipmi_rs *
+ipmi_lan_poll_recv(struct ipmi_intf * intf)
+{
+ struct rmcp_hdr rmcp_rsp;
+ struct ipmi_rs * rsp;
+ struct ipmi_session * session = intf->session;
+ int offset, rv;
+ uint16_t payload_size;
+ uint8_t ourAddress = (uint8_t)intf->my_addr;
+
+ if (ourAddress == 0) {
+ ourAddress = IPMI_BMC_SLAVE_ADDR;
+ }
+
+ rsp = ipmi_lan_recv_packet(intf);
+
+ /*
+ * Not positive why we're looping. Do we sometimes get stuff we don't
+ * expect?
+ */
+ while (rsp != NULL) {
+
+ /* parse response headers */
+ memcpy(&rmcp_rsp, rsp->data, 4);
+
+ if (rmcp_rsp.class == RMCP_CLASS_ASF) {
+ /* might be ping response packet */
+ rv = ipmi_handle_pong(intf, rsp);
+ return (rv <= 0) ? NULL : rsp;
+ }
+
+ if (rmcp_rsp.class != RMCP_CLASS_IPMI) {
+ lprintf(LOG_DEBUG, "Invalid RMCP class: %x",
+ rmcp_rsp.class);
+ rsp = ipmi_lan_recv_packet(intf);
+ continue;
+ }
+
+
+ /*
+ * The authtype / payload type determines what we are receiving
+ */
+ offset = 4;
+
+
+ /*--------------------------------------------------------------
+ *
+ * The current packet could be one of several things:
+ *
+ * 1) An IPMI 1.5 packet (the response to our GET CHANNEL
+ * AUTHENTICATION CAPABILITIES request)
+ * 2) An RMCP+ message with an IPMI response payload
+ * 3) AN RMCP+ open session response
+ * 4) An RAKP-2 message (response to an RAKP 1 message)
+ * 5) An RAKP-4 message (response to an RAKP 3 message)
+ * 6) A Serial Over LAN packet
+ * 7) An Invalid packet (one that doesn't match a request)
+ * -------------------------------------------------------------
+ */
+ rv = read_session_data(rsp, &offset, intf->session);
+ if (rv != 0) return(NULL);
+
+ lprintf(LOG_INFO, "rsp session_id=%08lx session_seq=%08lx",
+ (long)rsp->session.id, (long)rsp->session.seq);
+
+ if (lanplus_has_valid_auth_code(rsp, intf->session) == 0)
+ {
+ lprintf(LOG_ERR, "ERROR: Received message with invalid authcode!");
+ return(NULL); /*was ipmi_lan_recv_packet, assert*/
+ }
+
+ if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) &&
+ (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
+ (rsp->session.bEncrypted))
+
+ {
+ lanplus_decrypt_payload(session->v2_data.crypt_alg,
+ session->v2_data.k2,
+ rsp->data + offset,
+ rsp->session.msglen,
+ rsp->data + offset,
+ &payload_size);
+ }
+ else
+ payload_size = rsp->session.msglen;
+
+ /*
+ * Handle IPMI responses (case #1 and #2) -- all IPMI reponses
+ */
+ if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_IPMI)
+ {
+ struct ipmi_rq_entry * entry;
+ int payload_start = offset;
+ int extra_data_length;
+ read_ipmi_response(rsp, &offset);
+
+ lprintf(LOG_DEBUG+1, "<< IPMI Response Session Header");
+ lprintf(LOG_DEBUG+1, "<< Authtype : %s",
+ val2str(rsp->session.authtype, ipmi_authtype_session_vals));
+ lprintf(LOG_DEBUG+1, "<< Payload type : %s",
+ val2str(rsp->session.payloadtype, plus_payload_types_vals));
+ lprintf(LOG_DEBUG+1, "<< Session ID : 0x%08lx",
+ (long)rsp->session.id);
+ lprintf(LOG_DEBUG+1, "<< Sequence : 0x%08lx",
+ (long)rsp->session.seq);
+ lprintf(LOG_DEBUG+1, "<< IPMI Msg/Payload Length : %d",
+ rsp->session.msglen);
+ lprintf(LOG_DEBUG+1, "<< IPMI Response Message Header");
+ lprintf(LOG_DEBUG+1, "<< Rq Addr : %02x",
+ rsp->payload.ipmi_response.rq_addr);
+ lprintf(LOG_DEBUG+1, "<< NetFn : %02x",
+ rsp->payload.ipmi_response.netfn);
+ lprintf(LOG_DEBUG+1, "<< Rq LUN : %01x",
+ rsp->payload.ipmi_response.rq_lun);
+ lprintf(LOG_DEBUG+1, "<< Rs Addr : %02x",
+ rsp->payload.ipmi_response.rs_addr);
+ lprintf(LOG_DEBUG+1, "<< Rq Seq : %02x",
+ rsp->payload.ipmi_response.rq_seq);
+ lprintf(LOG_DEBUG+1, "<< Rs Lun : %01x",
+ rsp->payload.ipmi_response.rs_lun);
+ lprintf(LOG_DEBUG+1, "<< Command : %02x",
+ rsp->payload.ipmi_response.cmd);
+ lprintf(LOG_DEBUG+1, "<< Compl Code : 0x%02x",
+ rsp->ccode);
+
+ /* Are we expecting this packet? */
+ entry = ipmi_req_lookup_entry(rsp->payload.ipmi_response.rq_seq,
+ rsp->payload.ipmi_response.cmd);
+ if (entry != NULL) {
+ lprintf(LOG_DEBUG+2, "IPMI Request Match found");
+ if ( intf->target_addr != intf->my_addr &&
+ bridgePossible && rsp->data_len &&
+ rsp->payload.ipmi_response.cmd == 0x34 )
+ {
+ /* Check completion code */
+ if (rsp->data[offset-1] == 0)
+ {
+ lprintf(LOG_DEBUG,
+ "Bridged command answer,"
+ " waiting for next answer... ");
+ ipmi_req_remove_entry(
+ rsp->payload.ipmi_response.rq_seq,
+ rsp->payload.ipmi_response.cmd);
+ return(ipmi_lan_poll_recv(intf));
+ } else {
+ lprintf(LOG_DEBUG, "WARNING: Bridged"
+ "cmd ccode = 0x%02x",
+ rsp->data[offset-1]);
+ }
+
+ if (rsp->data_len &&
+ rsp->payload.ipmi_response.cmd== 0x34) {
+
+ memcpy(rsp->data, &rsp->data[offset],
+ (rsp->data_len-offset));
+ printbuf( &rsp->data[offset],
+ (rsp->data_len-offset),
+ "bridge command response");
+ }
+ }
+ ipmi_req_remove_entry(
+ rsp->payload.ipmi_response.rq_seq,
+ rsp->payload.ipmi_response.cmd);
+
+ } else {
+ lprintf(LOG_INFO, "IPMI Request Match NOT FOUND");
+ rsp = ipmi_lan_recv_packet(intf);
+ continue;
+ }
+
+ /*
+ * Good packet. Shift response data to start of array.
+ * rsp->data becomes the variable length IPMI response data
+ * rsp->data_len becomes the length of that data
+ */
+ extra_data_length = payload_size - (offset - payload_start) - 1;
+ if (rsp != NULL && extra_data_length)
+ {
+ rsp->data_len = extra_data_length;
+ memmove(rsp->data, rsp->data + offset, extra_data_length);
+ }
+ else
+ rsp->data_len = 0;
+
+ break;
+ }
+
+
+ /*
+ * Open Response
+ */
+ else if (rsp->session.payloadtype ==
+ IPMI_PAYLOAD_TYPE_RMCP_OPEN_RESPONSE)
+ {
+ if (session->v2_data.session_state !=
+ LANPLUS_STATE_OPEN_SESSION_SENT)
+ {
+ lprintf(LOG_ERR, "Error: Received an Unexpected Open Session "
+ "Response");
+ rsp = ipmi_lan_recv_packet(intf);
+ continue;
+ }
+
+ read_open_session_response(rsp, offset);
+ break;
+ }
+
+
+ /*
+ * RAKP 2
+ */
+ else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_2)
+ {
+ if (session->v2_data.session_state != LANPLUS_STATE_RAKP_1_SENT)
+ {
+ lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 2 message");
+ rsp = ipmi_lan_recv_packet(intf);
+ continue;
+ }
+
+ read_rakp2_message(rsp, offset, session->v2_data.auth_alg);
+ break;
+ }
+
+
+ /*
+ * RAKP 4
+ */
+ else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_RAKP_4)
+ {
+ if (session->v2_data.session_state != LANPLUS_STATE_RAKP_3_SENT)
+ {
+ lprintf(LOG_ERR, "Error: Received an Unexpected RAKP 4 message");
+ rsp = ipmi_lan_recv_packet(intf);
+ continue;
+ }
+
+ read_rakp4_message(rsp, offset, session->v2_data.auth_alg);
+ break;
+ }
+
+
+ /*
+ * SOL
+ */
+ else if (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL)
+ {
+ int payload_start = offset;
+ int extra_data_length;
+
+ if (session->v2_data.session_state != LANPLUS_STATE_ACTIVE)
+ {
+ lprintf(LOG_ERR, "Error: Received an Unexpected SOL packet");
+ rsp = ipmi_lan_recv_packet(intf);
+ continue;
+ }
+
+ read_sol_packet(rsp, &offset);
+ extra_data_length = payload_size - (offset - payload_start);
+ if (rsp && extra_data_length)
+ {
+ rsp->data_len = extra_data_length;
+ memmove(rsp->data, rsp->data + offset, extra_data_length);
+ }
+ else
+ rsp->data_len = 0;
+
+ break;
+ }
+
+ else
+ {
+ lprintf(LOG_ERR, "Invalid RMCP+ payload type : 0x%x",
+ rsp->session.payloadtype);
+ return(NULL); //assert(0);
+ }
+ }
+
+ return rsp;
+}
+
+
+
+/*
+ * read_open_session_reponse
+ *
+ * Initialize the ipmi_rs from the IPMI 2.x open session response data.
+ *
+ * The offset should point to the first byte of the the Open Session Response
+ * payload when this function is called.
+ *
+ * param rsp [in/out] reading from the data and writing to the open_session_response
+ * section
+ * param offset [in] tells us where the Open Session Response payload starts
+ *
+ * returns 0 on success, 1 on error
+ */
+void
+read_open_session_response(struct ipmi_rs * rsp, int offset)
+{
+ memset(&rsp->payload.open_session_response, 0,
+ sizeof(rsp->payload.open_session_response));
+
+ /* Message tag */
+ rsp->payload.open_session_response.message_tag = rsp->data[offset];
+
+ /* RAKP reponse code */
+ rsp->payload.open_session_response.rakp_return_code = rsp->data[offset + 1];
+
+ /* Maximum privilege level */
+ rsp->payload.open_session_response.max_priv_level = rsp->data[offset + 2];
+
+ /*** offset + 3 is reserved ***/
+
+ /* Remote console session ID */
+ memcpy(&(rsp->payload.open_session_response.console_id),
+ rsp->data + offset + 4,
+ 4);
+ #if WORDS_BIGENDIAN
+ rsp->payload.open_session_response.console_id =
+ BSWAP_32(rsp->payload.open_session_response.console_id);
+ #endif
+
+ /* only tag, status, privlvl, and console id are returned if error */
+ if (rsp->payload.open_session_response.rakp_return_code !=
+ IPMI_RAKP_STATUS_NO_ERRORS)
+ return;
+
+ /* BMC session ID */
+ memcpy(&(rsp->payload.open_session_response.bmc_id),
+ rsp->data + offset + 8,
+ 4);
+ #if WORDS_BIGENDIAN
+ rsp->payload.open_session_response.bmc_id =
+ BSWAP_32(rsp->payload.open_session_response.bmc_id);
+ #endif
+
+ /* And of course, our negotiated algorithms */
+ rsp->payload.open_session_response.auth_alg = rsp->data[offset + 16];
+ rsp->payload.open_session_response.integrity_alg = rsp->data[offset + 24];
+ rsp->payload.open_session_response.crypt_alg = rsp->data[offset + 32];
+}
+
+
+
+/*
+ * read_rakp2_message
+ *
+ * Initialize the ipmi_rs from the IPMI 2.x RAKP 2 message
+ *
+ * The offset should point the first byte of the the RAKP 2 payload when this
+ * function is called.
+ *
+ * param rsp [in/out] reading from the data variable and writing to the rakp 2
+ * section
+ * param offset [in] tells us where hte rakp2 payload starts
+ * param auth_alg [in] describes the authentication algorithm was agreed upon in
+ * the open session request/response phase. We need to know that here so
+ * that we know how many bytes (if any) to read fromt the packet.
+ *
+ * returns 0 on success, 1 on error
+ */
+void
+read_rakp2_message(
+ struct ipmi_rs * rsp,
+ int offset,
+ uint8_t auth_alg)
+{
+ int i;
+
+ /* Message tag */
+ rsp->payload.rakp2_message.message_tag = rsp->data[offset];
+
+ /* RAKP reponse code */
+ rsp->payload.rakp2_message.rakp_return_code = rsp->data[offset + 1];
+
+ /* Console session ID */
+ memcpy(&(rsp->payload.rakp2_message.console_id),
+ rsp->data + offset + 4,
+ 4);
+ #if WORDS_BIGENDIAN
+ rsp->payload.rakp2_message.console_id =
+ BSWAP_32(rsp->payload.rakp2_message.console_id);
+ #endif
+
+ /* BMC random number */
+ memcpy(&(rsp->payload.rakp2_message.bmc_rand),
+ rsp->data + offset + 8,
+ 16);
+ #if WORDS_BIGENDIAN
+ lanplus_swap(rsp->payload.rakp2_message.bmc_rand, 16);
+ #endif
+
+ /* BMC GUID */
+ memcpy(&(rsp->payload.rakp2_message.bmc_guid),
+ rsp->data + offset + 24,
+ 16);
+ #if WORDS_BIGENDIAN
+ lanplus_swap(rsp->payload.rakp2_message.bmc_guid, 16);
+ #endif
+
+ /* Key exchange authentication code */
+ switch (auth_alg)
+ {
+ case IPMI_AUTH_RAKP_NONE:
+ /* Nothing to do here */
+ break;
+
+ case IPMI_AUTH_RAKP_HMAC_SHA1:
+ /* We need to copy 20 bytes */
+ for (i = 0; i < SHA_DIGEST_LENGTH; ++i)
+ rsp->payload.rakp2_message.key_exchange_auth_code[i] =
+ rsp->data[offset + 40 + i];
+ break;
+
+ case IPMI_AUTH_RAKP_HMAC_MD5:
+ /* We need to copy 16 bytes */
+ for (i = 0; i < MD5_DIGEST_LENGTH; ++i)
+ rsp->payload.rakp2_message.key_exchange_auth_code[i] =
+ rsp->data[offset + 40 + i];
+ break;
+
+ case IPMI_AUTH_RAKP_HMAC_SHA256:
+ /* We need to copy 32 bytes */
+ for (i = 0; i < SHA256_DIGEST_LENGTH; ++i)
+ rsp->payload.rakp2_message.key_exchange_auth_code[i] =
+ rsp->data[offset + 40 + i];
+ break;
+
+ default:
+ lprintf(LOG_ERR, "read_rakp2_message: no support for authentication algorithm 0x%x", auth_alg);
+ assert(0); /*void routine*/
+ break;
+ }
+}
+
+
+
+/*
+ * read_rakp4_message
+ *
+ * Initialize the ipmi_rs from the IPMI 2.x RAKP 4 message
+ *
+ * The offset should point the first byte of the the RAKP 4 payload when this
+ * function is called.
+ *
+ * param rsp [in/out] reading from the data variable and writing to the rakp
+ * 4 section
+ * param offset [in] tells us where hte rakp4 payload starts
+ * param integrity_alg [in] describes the authentication algorithm was
+ * agreed upon in the open session request/response phase. We need
+ * to know that here so that we know how many bytes (if any) to read
+ * from the packet.
+ *
+ * returns 0 on success, 1 on error
+ */
+void
+read_rakp4_message(
+ struct ipmi_rs * rsp,
+ int offset,
+ uint8_t auth_alg)
+{
+ int i;
+
+ /* Message tag */
+ rsp->payload.rakp4_message.message_tag = rsp->data[offset];
+
+ /* RAKP reponse code */
+ rsp->payload.rakp4_message.rakp_return_code = rsp->data[offset + 1];
+
+ /* Console session ID */
+ memcpy(&(rsp->payload.rakp4_message.console_id),
+ rsp->data + offset + 4,
+ 4);
+ #if WORDS_BIGENDIAN
+ rsp->payload.rakp4_message.console_id =
+ BSWAP_32(rsp->payload.rakp4_message.console_id);
+ #endif
+
+
+ /* Integrity check value */
+ switch (auth_alg)
+ {
+ case IPMI_AUTH_RAKP_NONE:
+ /* Nothing to do here */
+ break;
+
+ case IPMI_AUTH_RAKP_HMAC_SHA1:
+ /* We need to copy 12 bytes */
+ for (i = 0; i < IPMI_SHA1_AUTHCODE_SIZE; ++i)
+ rsp->payload.rakp4_message.integrity_check_value[i] =
+ rsp->data[offset + 8 + i];
+ break;
+
+ case IPMI_AUTH_RAKP_HMAC_MD5:
+ /* We need to copy 16 bytes */
+ for (i = 0; i < IPMI_HMAC_MD5_AUTHCODE_SIZE; ++i)
+ rsp->payload.rakp4_message.integrity_check_value[i] =
+ rsp->data[offset + 8 + i];
+ break;
+
+ case IPMI_AUTH_RAKP_HMAC_SHA256:
+ /* We need to copy 16 bytes */
+ for (i = 0; i < IPMI_HMAC_SHA256_AUTHCODE_SIZE; ++i)
+ rsp->payload.rakp4_message.integrity_check_value[i] =
+ rsp->data[offset + 8 + i];
+ break;
+
+ default:
+ lprintf(LOG_ERR, "read_rakp4_message: no support "
+ "for authentication algorithm 0x%x", auth_alg);
+ assert(0); /*void routine*/
+ break;
+ }
+}
+
+
+
+
+/*
+ * read_session_data
+ *
+ * Initialize the ipmi_rsp from the session data in the packet
+ *
+ * The offset should point the first byte of the the IPMI session when this
+ * function is called.
+ *
+ * param rsp [in/out] we read from the data buffer and populate the session
+ * specific fields.
+ * param offset [in/out] should point to the beginning of the session when
+ * this function is called. The offset will be adjusted to
+ * point to the end of the session when this function exits.
+ * param session holds our session state
+ */
+int
+read_session_data(
+ struct ipmi_rs * rsp,
+ int * offset,
+ struct ipmi_session * s)
+{
+ int rv;
+ /* We expect to read different stuff depending on the authtype */
+ rsp->session.authtype = rsp->data[*offset];
+
+ if (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS)
+ rv = read_session_data_v2x(rsp, offset, s);
+ else
+ rv = read_session_data_v15(rsp, offset, s);
+ return(rv);
+}
+
+
+
+/*
+ * read_session_data_v2x
+ *
+ * Initialize the ipmi_rsp from the v2.x session header of the packet.
+ *
+ * The offset should point to the first byte of the the IPMI session when this
+ * function is called. When this function exits, offset will point to the
+ * start of payload.
+ *
+ * Should decrypt and perform integrity checking here?
+ *
+ * param rsp [in/out] we read from the data buffer and populate the session
+ * specific fields.
+ * param offset [in/out] should point to the beginning of the session when this
+ * function is called. The offset will be adjusted to point to
+ * the end of the session when this function exits.
+ * param s holds our session state
+ */
+int
+read_session_data_v2x(
+ struct ipmi_rs * rsp,
+ int * offset,
+ struct ipmi_session * s)
+{
+ rsp->session.authtype = rsp->data[(*offset)++];
+
+ rsp->session.bEncrypted = (rsp->data[*offset] & 0x80 ? 1 : 0);
+ rsp->session.bAuthenticated = (rsp->data[*offset] & 0x40 ? 1 : 0);
+
+
+ /* Payload type */
+ rsp->session.payloadtype = rsp->data[(*offset)++] & 0x3F;
+
+ /* Session ID */
+ memcpy(&rsp->session.id, rsp->data + *offset, 4);
+ *offset += 4;
+ #if WORDS_BIGENDIAN
+ rsp->session.id = BSWAP_32(rsp->session.id);
+ #endif
+
+
+ /*
+ * Verify that the session ID is what we think it should be
+ */
+ if ((s->v2_data.session_state == LANPLUS_STATE_ACTIVE) &&
+ (rsp->session.id != s->v2_data.console_id))
+ {
+ lprintf(LOG_ERR, "packet session id 0x%x does not "
+ "match active session 0x%0x",
+ rsp->session.id, s->v2_data.console_id);
+ /* assert(0); * the session is broken, cannot proceed */
+ /* return and abort session here. */
+ return(-13); /* LAN_ERR_OTHER = -13 */
+ }
+
+
+ /* Ignored, so far */
+ memcpy(&rsp->session.seq, rsp->data + *offset, 4);
+ *offset += 4;
+ #if WORDS_BIGENDIAN
+ rsp->session.seq = BSWAP_32(rsp->session.seq);
+ #endif
+
+ memcpy(&rsp->session.msglen, rsp->data + *offset, 2);
+ *offset += 2;
+ #if WORDS_BIGENDIAN
+ rsp->session.msglen = BSWAP_16(rsp->session.msglen);
+ #endif
+ return(0);
+}
+
+
+
+/*
+ * read_session_data_v15
+ *
+ * Initialize the ipmi_rsp from the session header of the packet.
+ *
+ * The offset should point the first byte of the the IPMI session when this
+ * function is called. When this function exits, the offset will point to
+ * the start of the IPMI message.
+ *
+ * param rsp [in/out] we read from the data buffer and populate the session
+ * specific fields.
+ * param offset [in/out] should point to the beginning of the session when this
+ * function is called. The offset will be adjusted to point to the
+ * end of the session when this function exits.
+ * param s holds our session state
+ */
+int read_session_data_v15(
+ struct ipmi_rs * rsp,
+ int * offset,
+ struct ipmi_session * s)
+{
+ /* All v15 messages are IPMI messages */
+ rsp->session.payloadtype = IPMI_PAYLOAD_TYPE_IPMI;
+
+ rsp->session.authtype = rsp->data[(*offset)++];
+
+ /* All v15 messages that we will receive are unencrypted/unauthenticated */
+ rsp->session.bEncrypted = 0;
+ rsp->session.bAuthenticated = 0;
+
+ /* skip the session id and sequence number fields */
+ *offset += 8;
+
+ /* This is the size of the whole payload */
+ rsp->session.msglen = rsp->data[(*offset)++];
+ return(0);
+}
+
+
+
+/*
+ * read_ipmi_response
+ *
+ * Initialize the impi_rs from with the IPMI response specific data
+ *
+ * The offset should point the first byte of the the IPMI payload when this
+ * function is called.
+ *
+ * param rsp [in/out] we read from the data buffer and populate the IPMI
+ * specific fields.
+ * param offset [in/out] should point to the beginning of the IPMI payload when
+ * this function is called.
+ */
+void read_ipmi_response(struct ipmi_rs * rsp, int * offset)
+{
+ /*
+ * The data here should be decrypted by now.
+ */
+ rsp->payload.ipmi_response.rq_addr = rsp->data[(*offset)++];
+ rsp->payload.ipmi_response.netfn = rsp->data[*offset] >> 2;
+ rsp->payload.ipmi_response.rq_lun = rsp->data[(*offset)++] & 0x3;
+ (*offset)++; /* checksum */
+ rsp->payload.ipmi_response.rs_addr = rsp->data[(*offset)++];
+ rsp->payload.ipmi_response.rq_seq = rsp->data[*offset] >> 2;
+ rsp->payload.ipmi_response.rs_lun = rsp->data[(*offset)++] & 0x3;
+ rsp->payload.ipmi_response.cmd = rsp->data[(*offset)++];
+ rsp->ccode = rsp->data[(*offset)++];
+
+}
+
+
+
+/*
+ * read_sol_packet
+ *
+ * Initialize the ipmi_rs with the SOL response data
+ *
+ * The offset should point the first byte of the the SOL payload when this
+ * function is called.
+ *
+ * param rsp [in/out] we read from the data buffer and populate the
+ * SOL specific fields.
+ * param offset [in/out] should point to the beginning of the SOL payload
+ * when this function is called.
+ */
+void read_sol_packet(struct ipmi_rs * rsp, int * offset)
+{
+
+ /*
+ * The data here should be decrypted by now.
+ */
+ rsp->payload.sol_packet.packet_sequence_number =
+ rsp->data[(*offset)++] & 0x0F;
+
+ rsp->payload.sol_packet.acked_packet_number =
+ rsp->data[(*offset)++] & 0x0F;
+
+ rsp->payload.sol_packet.accepted_character_count =
+ rsp->data[(*offset)++];
+
+ rsp->payload.sol_packet.is_nack =
+ rsp->data[*offset] & 0x40;
+
+ rsp->payload.sol_packet.transfer_unavailable =
+ rsp->data[*offset] & 0x20;
+
+ rsp->payload.sol_packet.sol_inactive =
+ rsp->data[*offset] & 0x10;
+
+ rsp->payload.sol_packet.transmit_overrun =
+ rsp->data[*offset] & 0x08;
+
+ rsp->payload.sol_packet.break_detected =
+ rsp->data[(*offset)++] & 0x04;
+
+ lprintf(LOG_DEBUG, "<<<<<<<<<< RECV FROM BMC <<<<<<<<<<<");
+ lprintf(LOG_DEBUG, "< SOL sequence number : 0x%02x",
+ rsp->payload.sol_packet.packet_sequence_number);
+ lprintf(LOG_DEBUG, "< SOL acked packet : 0x%02x",
+ rsp->payload.sol_packet.acked_packet_number);
+ lprintf(LOG_DEBUG, "< SOL accepted char count : 0x%02x",
+ rsp->payload.sol_packet.accepted_character_count);
+ lprintf(LOG_DEBUG, "< SOL is nack : %s",
+ rsp->payload.sol_packet.is_nack? "true" : "false");
+ lprintf(LOG_DEBUG, "< SOL xfer unavailable : %s",
+ rsp->payload.sol_packet.transfer_unavailable? "true" : "false");
+ lprintf(LOG_DEBUG, "< SOL inactive : %s",
+ rsp->payload.sol_packet.sol_inactive? "true" : "false");
+ lprintf(LOG_DEBUG, "< SOL transmit overrun : %s",
+ rsp->payload.sol_packet.transmit_overrun? "true" : "false");
+ lprintf(LOG_DEBUG, "< SOL break detected : %s",
+ rsp->payload.sol_packet.break_detected? "true" : "false");
+ lprintf(LOG_DEBUG, "< rs Session sequence num : %d",
+ rsp->session.seq);
+ lprintf(LOG_DEBUG, "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
+
+ if (verbose >= 5)
+ printbuf(rsp->data + *offset - 4, 4, "SOL MSG FROM BMC");
+}
+
+
+
+/*
+ * getIpmiPayloadWireRep
+ *
+ * param out [out] will contain our wire representation
+ * param req [in] is the IPMI request to be written
+ * param crypt_alg [in] specifies the encryption to use
+ * param rq_seq [in] is the IPMI command sequence number.
+ */
+void getIpmiPayloadWireRep(
+ struct ipmi_intf * intf, /* in out */
+ struct ipmi_v2_payload * payload, /* in */
+ uint8_t * msg,
+ struct ipmi_rq * req,
+ uint8_t rq_seq,
+ uint8_t curr_seq)
+{
+ int cs, tmp, len;
+ int cs2 = 0;
+ int cs3 = 0;
+ uint8_t ourAddress = (uint8_t)intf->my_addr;
+ uint8_t bridgedRequest = 0;
+
+ if (ourAddress == 0)
+ ourAddress = IPMI_BMC_SLAVE_ADDR;
+
+ len = 0;
+
+ /* IPMI Message Header -- Figure 13-4 of the IPMI v2.0 spec */
+ if ((intf->target_addr == ourAddress) || (!bridgePossible))
+ cs = len;
+ else {
+ bridgedRequest = 1;
+ if(intf->transit_addr != ourAddress && intf->transit_addr != 0)
+ {
+ bridgedRequest++;
+ }
+ /* bridged request: encapsulate w/in Send Message */
+ cs = len;
+ msg[len++] = IPMI_BMC_SLAVE_ADDR;
+ msg[len++] = IPMI_NETFN_APP << 2;
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+ cs2 = len;
+ msg[len++] = IPMI_REMOTE_SWID;
+ msg[len++] = curr_seq << 2;
+ msg[len++] = 0x34; /* Send Message rqst */
+ if(bridgedRequest == 2)
+ msg[len++] = (0x40|intf->transit_channel); /* Track request*/
+ else
+ msg[len++] = (0x40|intf->target_channel); /* Track request*/
+#if 0 /* From lan.c example */
+ entry->req.msg.target_cmd = entry->req.msg.cmd; /* Save target command */
+ entry->req.msg.cmd = 0x34; /* (fixup request entry) */
+#endif
+ payload->payload_length += 7;
+ cs = len;
+ if(bridgedRequest == 2)
+ {
+ /* bridged request: encapsulate w/in Send Message */
+ cs = len;
+ msg[len++] = (uint8_t)intf->transit_addr;
+ msg[len++] = IPMI_NETFN_APP << 2;
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+ cs3 = len;
+ msg[len++] = (uint8_t)intf->my_addr;
+ msg[len++] = curr_seq << 2;
+ msg[len++] = 0x34; /* Send Message rqst */
+ msg[len++] = (0x40|intf->target_channel); /* Track request*/
+ payload->payload_length += 7;
+ cs = len;
+ }
+ }
+
+ /* rsAddr */
+ msg[len++] = (uint8_t)intf->target_addr; /* IPMI_BMC_SLAVE_ADDR; */
+
+ /* net Fn */
+ msg[len++] = req->msg.netfn << 2 | (req->msg.lun & 3);
+ tmp = len - cs;
+
+ /* checkSum */
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+ cs = len;
+
+ /* rqAddr */
+ if (!bridgedRequest)
+ msg[len++] = IPMI_REMOTE_SWID;
+ else /* Bridged message */
+ msg[len++] = (uint8_t)intf->my_addr;
+
+ /* rqSeq / rqLUN */
+ msg[len++] = rq_seq << 2;
+
+ /* cmd */
+ msg[len++] = req->msg.cmd;
+
+ /* message data */
+ if (req->msg.data_len) {
+ memcpy(msg + len, req->msg.data, req->msg.data_len);
+ len += req->msg.data_len;
+ }
+
+ /* second checksum */
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+
+ /* Dual bridged request: 2nd checksum */
+ if (bridgedRequest == 2) {
+ tmp = len - cs3;
+ msg[len++] = ipmi_csum(msg+cs3, tmp);
+ payload->payload_length += 1;
+ }
+
+ /* bridged request: 2nd checksum */
+ if (bridgedRequest) {
+ tmp = len - cs2;
+ msg[len++] = ipmi_csum(msg+cs2, tmp);
+ payload->payload_length += 1;
+ if (verbose)
+ printbuf(msg,len,"Bridged Request");
+ }
+}
+
+
+
+/*
+ * getSolPayloadWireRep
+ *
+ * param msg [out] will contain our wire representation
+ * param payload [in] holds the v2 payload with our SOL data
+ */
+void getSolPayloadWireRep(
+ struct ipmi_intf * intf, /* in out */
+ uint8_t * msg, /* output */
+ struct ipmi_v2_payload * payload) /* input */
+{
+ int i = 0;
+
+ lprintf(LOG_DEBUG, ">>>>>>>>>> SENDING TO BMC >>>>>>>>>>");
+ lprintf(LOG_DEBUG, "> SOL sequence number : 0x%02x",
+ payload->payload.sol_packet.packet_sequence_number);
+ lprintf(LOG_DEBUG, "> SOL acked packet : 0x%02x",
+ payload->payload.sol_packet.acked_packet_number);
+ lprintf(LOG_DEBUG, "> SOL accepted char count : 0x%02x",
+ payload->payload.sol_packet.accepted_character_count);
+ lprintf(LOG_DEBUG, "> SOL is nack : %s",
+ payload->payload.sol_packet.is_nack ? "true" : "false");
+ lprintf(LOG_DEBUG, "> SOL assert ring wor : %s",
+ payload->payload.sol_packet.assert_ring_wor ? "true" : "false");
+ lprintf(LOG_DEBUG, "> SOL generate break : %s",
+ payload->payload.sol_packet.generate_break ? "true" : "false");
+ lprintf(LOG_DEBUG, "> SOL deassert cts : %s",
+ payload->payload.sol_packet.deassert_cts ? "true" : "false");
+ lprintf(LOG_DEBUG, "> SOL deassert dcd dsr : %s",
+ payload->payload.sol_packet.deassert_dcd_dsr ? "true" : "false");
+ lprintf(LOG_DEBUG, "> SOL flush inbound : %s",
+ payload->payload.sol_packet.flush_inbound ? "true" : "false");
+ lprintf(LOG_DEBUG, "> SOL flush outbound : %s",
+ payload->payload.sol_packet.flush_outbound ? "true" : "false");
+
+ msg[i++] = payload->payload.sol_packet.packet_sequence_number;
+ msg[i++] = payload->payload.sol_packet.acked_packet_number;
+ msg[i++] = payload->payload.sol_packet.accepted_character_count;
+
+ msg[i] = payload->payload.sol_packet.is_nack ? 0x40 : 0;
+ msg[i] |= payload->payload.sol_packet.assert_ring_wor ? 0x20 : 0;
+ msg[i] |= payload->payload.sol_packet.generate_break ? 0x10 : 0;
+ msg[i] |= payload->payload.sol_packet.deassert_cts ? 0x08 : 0;
+ msg[i] |= payload->payload.sol_packet.deassert_dcd_dsr ? 0x04 : 0;
+ msg[i] |= payload->payload.sol_packet.flush_inbound ? 0x02 : 0;
+ msg[i++] |= payload->payload.sol_packet.flush_outbound ? 0x01 : 0;
+
+ /* We may have data to add */
+ memcpy(msg + i,
+ payload->payload.sol_packet.data,
+ payload->payload.sol_packet.character_count);
+
+ lprintf(LOG_DEBUG, "> SOL character count : %d",
+ payload->payload.sol_packet.character_count);
+ lprintf(LOG_DEBUG, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
+
+ if (verbose >= 5 && payload->payload.sol_packet.character_count)
+ printbuf(payload->payload.sol_packet.data, payload->payload.sol_packet.character_count, "SOL SEND DATA");
+
+ /*
+ * At this point, the payload length becomes the whole payload
+ * length, including the 4 bytes at the beginning of the SOL
+ * packet
+ */
+ payload->payload_length = payload->payload.sol_packet.character_count + 4;
+}
+
+
+
+/*
+ * ipmi_lanplus_build_v2x_msg
+ *
+ * Encapsulates the payload data to create the IPMI v2.0 / RMCP+ packet.
+ *
+ *
+ * IPMI v2.0 LAN Request Message Format
+ * +----------------------+
+ * | rmcp.ver | 4 bytes
+ * | rmcp.__rsvd |
+ * | rmcp.seq |
+ * | rmcp.class |
+ * +----------------------+
+ * | session.authtype | 10 bytes
+ * | session.payloadtype |
+ * | session.id |
+ * | session.seq |
+ * +----------------------+
+ * | message length | 2 bytes
+ * +----------------------+
+ * | Confidentiality Hdr | var (possibly absent)
+ * +----------------------+
+ * | Payload | var Payload
+ * +----------------------+
+ * | Confidentiality Trlr | var (possibly absent)
+ * +----------------------+
+ * | Integrity pad | var (possibly absent)
+ * +----------------------+
+ * | Pad length | 1 byte (WTF?)
+ * +----------------------+
+ * | Next Header | 1 byte (WTF?)
+ * +----------------------+
+ * | Authcode | var (possibly absent)
+ * +----------------------+
+ */
+int
+ipmi_lanplus_build_v2x_msg(
+ struct ipmi_intf * intf, /* in */
+ struct ipmi_v2_payload * payload, /* in */
+ int * msg_len, /* out */
+ uint8_t ** msg_data, /* out */
+ uint8_t curr_seq)
+{
+ uint32_t session_trailer_length = 0;
+ struct ipmi_session * session = intf->session;
+ /* msg will hold the entire message to be sent */
+ uint8_t * msg;
+ int len = 0;
+ int rv = 0;
+#if defined(WIN32) || defined(SOLARIS)
+ struct rmcp_hdr rmcp;
+
+ rmcp.ver = RMCP_VERSION_1;
+ rmcp.class = RMCP_CLASS_IPMI;
+ rmcp.seq = 0xff;
+ rmcp.__rsvd = 0;
+#else
+ struct rmcp_hdr rmcp = {
+ .ver = RMCP_VERSION_1,
+ .__rsvd = 0,
+ .class = RMCP_CLASS_IPMI,
+ .seq = 0xff,
+ };
+#endif
+
+ len =
+ sizeof(rmcp) + // RMCP Header (4)
+ 10 + // IPMI Session Header
+ 2 + // Message length
+ payload->payload_length + // The actual payload
+ IPMI_MAX_INTEGRITY_PAD_SIZE + // Integrity Pad
+ 1 + // Pad Length
+ 1 + // Next Header
+ IPMI_MAX_AUTH_CODE_SIZE; // Authcode (usu 20+16)
+
+ msg = malloc(len);
+ if (msg == NULL) {
+ lprintf(LOG_ERR, "lanplus: malloc failure");
+ return -1;
+ }
+ memset(msg, 0, len);
+
+ /*
+ *------------------------------------------
+ * RMCP HEADER
+ *------------------------------------------
+ */
+ memcpy(msg, &rmcp, sizeof(rmcp));
+ len = sizeof(rmcp);
+
+
+ /*
+ *------------------------------------------
+ * IPMI SESSION HEADER
+ *------------------------------------------
+ */
+ /* ipmi session Auth Type / Format is always 0x06 for IPMI v2 */
+ msg[IPMI_LANPLUS_OFFSET_AUTHTYPE] = 0x06;
+
+ /* Payload Type -- also specifies whether were authenticated/encyrpted */
+ msg[IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE] = payload->payload_type;
+
+ if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE)
+ {
+ msg[IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE] |=
+ ((session->v2_data.crypt_alg != IPMI_CRYPT_NONE )? 0x80 : 0x00);
+ msg[IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE] |=
+ ((session->v2_data.integrity_alg != IPMI_INTEGRITY_NONE)? 0x40 : 0x00);
+ }
+
+ if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE)
+ {
+ /* Session ID -- making it LSB */
+ msg[IPMI_LANPLUS_OFFSET_SESSION_ID ] = session->v2_data.bmc_id & 0xff;
+ msg[IPMI_LANPLUS_OFFSET_SESSION_ID + 1] = (session->v2_data.bmc_id >> 8) & 0xff;
+ msg[IPMI_LANPLUS_OFFSET_SESSION_ID + 2] = (session->v2_data.bmc_id >> 16) & 0xff;
+ msg[IPMI_LANPLUS_OFFSET_SESSION_ID + 3] = (session->v2_data.bmc_id >> 24) & 0xff;
+
+ /* Sequence Number -- making it LSB */
+ msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM ] = session->out_seq & 0xff;
+ msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM + 1] = (session->out_seq >> 8) & 0xff;
+ msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM + 2] = (session->out_seq >> 16) & 0xff;
+ msg[IPMI_LANPLUS_OFFSET_SEQUENCE_NUM + 3] = (session->out_seq >> 24) & 0xff;
+ }
+
+ /*
+ * Payload Length is set below (we don't know how big the payload is until after
+ * encryption).
+ */
+
+ /*
+ * Payload
+ *
+ * At this point we are ready to slam the payload in.
+ * This includes:
+ * 1) The confidentiality header
+ * 2) The payload proper (possibly encrypted)
+ * 3) The confidentiality trailer
+ *
+ */
+ switch (payload->payload_type)
+ {
+ case IPMI_PAYLOAD_TYPE_IPMI:
+ getIpmiPayloadWireRep(intf,
+ payload, /* in */
+ msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
+ payload->payload.ipmi_request.request,
+ payload->payload.ipmi_request.rq_seq,
+ curr_seq);
+ break;
+
+ case IPMI_PAYLOAD_TYPE_SOL:
+ getSolPayloadWireRep(intf,
+ msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
+ payload);
+
+ if (verbose >= 5)
+ printbuf(msg + IPMI_LANPLUS_OFFSET_PAYLOAD, 4, "SOL MSG TO BMC");
+
+ len += payload->payload_length;
+
+ break;
+
+ case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST:
+ /* never encrypted, so our job is easy */
+ memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
+ payload->payload.open_session_request.request,
+ payload->payload_length);
+ len += payload->payload_length;
+ break;
+
+ case IPMI_PAYLOAD_TYPE_RAKP_1:
+ /* never encrypted, so our job is easy */
+ memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
+ payload->payload.rakp_1_message.message,
+ payload->payload_length);
+ len += payload->payload_length;
+ break;
+
+ case IPMI_PAYLOAD_TYPE_RAKP_3:
+ /* never encrypted, so our job is easy */
+ memcpy(msg + IPMI_LANPLUS_OFFSET_PAYLOAD,
+ payload->payload.rakp_3_message.message,
+ payload->payload_length);
+ len += payload->payload_length;
+ break;
+
+ default:
+ lprintf(LOG_ERR, "unsupported payload type 0x%x",
+ payload->payload_type);
+ free(msg);
+ return -1;
+ break;
+ }
+
+
+ /*
+ *------------------------------------------
+ * ENCRYPT THE PAYLOAD IF NECESSARY
+ *------------------------------------------
+ */
+ if (session->v2_data.session_state == LANPLUS_STATE_ACTIVE)
+ {
+ /* Payload len is adjusted as necessary by lanplus_encrypt_payload */
+ lanplus_encrypt_payload(session->v2_data.crypt_alg, /* input */
+ session->v2_data.k2, /* input */
+ msg + IPMI_LANPLUS_OFFSET_PAYLOAD, /* input */
+ payload->payload_length, /* input */
+ msg + IPMI_LANPLUS_OFFSET_PAYLOAD, /* output */
+ &(payload->payload_length)); /* output */
+
+ }
+
+ /* Now we know the payload length */
+ msg[IPMI_LANPLUS_OFFSET_PAYLOAD_SIZE ] =
+ payload->payload_length & 0xff;
+ msg[IPMI_LANPLUS_OFFSET_PAYLOAD_SIZE + 1] =
+ (payload->payload_length >> 8) & 0xff;
+
+
+ /*
+ *------------------------------------------
+ * SESSION TRAILER
+ *------------------------------------------
+ */
+ if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) &&
+ (session->v2_data.integrity_alg != IPMI_INTEGRITY_NONE))
+ {
+ uint32_t hmac_length, hmac_input_size;
+ uint32_t i, auth_length = 0, integrity_pad_size = 0;
+ uint8_t * hmac_output;
+ uint32_t start_of_session_trailer =
+ IPMI_LANPLUS_OFFSET_PAYLOAD +
+ payload->payload_length;
+
+
+ /*
+ * Determine the required integrity pad length. We have to make the
+ * data range covered by the authcode a multiple of 4.
+ */
+ uint32_t length_before_authcode;
+
+ if (ipmi_oem_active(intf, "icts")) {
+ length_before_authcode =
+ 12 + /* the stuff before the payload */
+ payload->payload_length;
+ } else {
+ length_before_authcode =
+ 12 + /* the stuff before the payload */
+ payload->payload_length +
+ 1 + /* pad length field */
+ 1; /* next header field */
+ }
+
+ if (length_before_authcode % 4)
+ integrity_pad_size = 4 - (length_before_authcode % 4);
+
+ for (i = 0; i < integrity_pad_size; ++i)
+ msg[start_of_session_trailer + i] = 0xFF;
+
+ /* Pad length */
+ msg[start_of_session_trailer + integrity_pad_size] = (uint8_t)integrity_pad_size;
+
+ /* Next Header */
+ msg[start_of_session_trailer + integrity_pad_size + 1] =
+ 0x07; /* Hardcoded per the spec, table 13-8 */
+
+ hmac_input_size =
+ 12 +
+ payload->payload_length +
+ integrity_pad_size +
+ 2;
+
+ hmac_output =
+ msg +
+ IPMI_LANPLUS_OFFSET_PAYLOAD +
+ payload->payload_length +
+ integrity_pad_size +
+ 2;
+
+ if (verbose > 2)
+ printbuf(msg + IPMI_LANPLUS_OFFSET_AUTHTYPE, hmac_input_size, "authcode input");
+
+ /* Auth Code */
+ hmac_length = 20; /* init length, just in case*/
+ lanplus_HMAC(session->v2_data.integrity_alg,
+ session->v2_data.k1, /*key */
+ session->v2_data.k1_len, /*key length*/
+ msg + IPMI_LANPLUS_OFFSET_AUTHTYPE, /*hmac input*/
+ hmac_input_size,
+ hmac_output,
+ &hmac_length);
+
+ switch(session->v2_data.integrity_alg)
+ {
+ case IPMI_INTEGRITY_HMAC_SHA1_96:
+ if (hmac_length != SHA_DIGEST_LENGTH) rv = -1;
+ auth_length = IPMI_SHA1_AUTHCODE_SIZE;
+ break;
+ case IPMI_INTEGRITY_HMAC_MD5_128 :
+ if (hmac_length != MD5_DIGEST_LENGTH) rv = -1;
+ auth_length = IPMI_HMAC_MD5_AUTHCODE_SIZE;
+ break;
+#ifdef HAVE_SHA256
+ /* based on an MD5_SHA256 patch from Holger Liebig */
+ case IPMI_INTEGRITY_HMAC_SHA256_128:
+ if (hmac_length != SHA256_DIGEST_LENGTH) rv = -1;
+ auth_length = IPMI_HMAC_SHA256_AUTHCODE_SIZE;
+ break;
+#endif
+ default:
+ lprintf(LOG_ERR,"unsupported integrity_alg 0x%x",
+ session->v2_data.integrity_alg);
+ free(msg);
+ return -1; //assert(0);
+ break;
+ }
+ if (rv != 0) {
+ lprintf(LOG_ERR,"Invalid alg %d length %d",
+ session->v2_data.integrity_alg, hmac_length);
+ return(rv);
+ }
+
+ if (verbose > 2)
+ printbuf(hmac_output, auth_length, "authcode output");
+
+ /* Set session_trailer_length appropriately */
+ session_trailer_length =
+ integrity_pad_size +
+ 2 + /* pad length + next header */
+ auth_length; /* Size of the authcode (we only use the first 12 bytes) */
+ }
+
+
+ ++(session->out_seq);
+ if (!session->out_seq)
+ ++(session->out_seq);
+
+ *msg_len =
+ IPMI_LANPLUS_OFFSET_PAYLOAD +
+ payload->payload_length +
+ session_trailer_length;
+ *msg_data = msg;
+ return 0;
+}
+
+
+
+/*
+ * ipmi_lanplus_build_v2x_ipmi_cmd
+ *
+ * Wraps ipmi_lanplus_build_v2x_msg and returns a new entry object for the
+ * command
+ *
+ */
+static struct ipmi_rq_entry *
+ipmi_lanplus_build_v2x_ipmi_cmd(
+ struct ipmi_intf * intf,
+ struct ipmi_rq * req)
+{
+ struct ipmi_v2_payload v2_payload;
+ struct ipmi_rq_entry * entry;
+ int rv;
+
+ /*
+ * We have a problem. we need to know the sequence number here,
+ * because we use it in our stored entry. But we also need to
+ * know the sequence number when we generate our IPMI
+ * representation far below.
+ */
+ static uint8_t curr_seq = 0;
+
+ curr_seq += 1;
+
+ if (curr_seq >= 64)
+ curr_seq = 0;
+
+ /* IPMI Message Header -- Figure 13-4 of the IPMI v2.0 spec */
+ if ((intf->target_addr == intf->my_addr) || (!bridgePossible))
+ {
+ entry = ipmi_req_add_entry(intf, req, curr_seq);
+ }
+ else /* it's a bridge command */
+ {
+ unsigned char backup_cmd;
+
+ /* Add entry for cmd */
+ entry = ipmi_req_add_entry(intf, req, curr_seq);
+
+ if (entry)
+ {
+ /* Add entry for bridge cmd */
+ backup_cmd = req->msg.cmd;
+ req->msg.cmd = 0x34;
+ entry = ipmi_req_add_entry(intf, req, curr_seq);
+ req->msg.cmd = backup_cmd;
+ }
+ }
+
+ if (entry == NULL)
+ return NULL;
+
+ // Build our payload
+ v2_payload.payload_type = IPMI_PAYLOAD_TYPE_IPMI;
+ v2_payload.payload_length = req->msg.data_len + 7;
+ v2_payload.payload.ipmi_request.request = req;
+ v2_payload.payload.ipmi_request.rq_seq = curr_seq;
+
+ rv = ipmi_lanplus_build_v2x_msg(intf, // in
+ &v2_payload, // in
+ &(entry->msg_len), // out
+ &(entry->msg_data), // out
+ curr_seq); // in
+ if (rv != 0) return NULL;
+
+ return entry;
+}
+
+
+
+
+
+/*
+ * IPMI LAN Request Message Format
+ * +--------------------+
+ * | rmcp.ver | 4 bytes
+ * | rmcp.__rsvd |
+ * | rmcp.seq |
+ * | rmcp.class |
+ * +--------------------+
+ * | session.authtype | 9 bytes
+ * | session.seq |
+ * | session.id |
+ * +--------------------+
+ * | [session.authcode] | 16 bytes (AUTHTYPE != none)
+ * +--------------------+
+ * | message length | 1 byte
+ * +--------------------+
+ * | message.rs_addr | 6 bytes
+ * | message.netfn_lun |
+ * | message.checksum |
+ * | message.rq_addr |
+ * | message.rq_seq |
+ * | message.cmd |
+ * +--------------------+
+ * | [request data] | data_len bytes
+ * +--------------------+
+ * | checksum | 1 byte
+ * +--------------------+
+ */
+static struct ipmi_rq_entry *
+ipmi_lanplus_build_v15_ipmi_cmd(
+ struct ipmi_intf * intf,
+ struct ipmi_rq * req)
+{
+ uint8_t * msg;
+ int cs, mp, len = 0, tmp;
+ struct ipmi_session * session = intf->session;
+ struct ipmi_rq_entry * entry;
+#if defined(WIN32) || defined(SOLARIS)
+ struct rmcp_hdr rmcp;
+
+ rmcp.ver = RMCP_VERSION_1;
+ rmcp.class = RMCP_CLASS_IPMI;
+ rmcp.seq = 0xff;
+ rmcp.__rsvd = 0;
+#else
+ struct rmcp_hdr rmcp = {
+ .ver = RMCP_VERSION_1,
+ .__rsvd = 0,
+ .class = RMCP_CLASS_IPMI,
+ .seq = 0xff,
+ };
+#endif
+
+ entry = ipmi_req_add_entry(intf, req, 0);
+ if (entry == NULL)
+ return NULL;
+
+ len = req->msg.data_len + 21;
+
+ msg = malloc(len);
+ if (msg == NULL) {
+ lprintf(LOG_ERR, "lanplus: malloc failure");
+ free(entry);
+ return NULL;
+ }
+ memset(msg, 0, len);
+
+ /* rmcp header */
+ memcpy(msg, &rmcp, sizeof(rmcp));
+ len = sizeof(rmcp);
+
+ /*
+ * ipmi session header
+ */
+ /* Authtype should always be none for 1.5 packets sent from this
+ * interface
+ */
+ msg[len++] = IPMI_SESSION_AUTHTYPE_NONE;
+
+ msg[len++] = session->out_seq & 0xff;
+ msg[len++] = (session->out_seq >> 8) & 0xff;
+ msg[len++] = (session->out_seq >> 16) & 0xff;
+ msg[len++] = (session->out_seq >> 24) & 0xff;
+
+ /*
+ * The session ID should be all zeroes for pre-session commands. We
+ * should only be using the 1.5 interface for the pre-session Get
+ * Channel Authentication Capabilities command
+ */
+ msg[len++] = 0;
+ msg[len++] = 0;
+ msg[len++] = 0;
+ msg[len++] = 0;
+
+ /* message length */
+ msg[len++] = req->msg.data_len + 7;
+
+ /* ipmi message header */
+ cs = mp = len;
+ msg[len++] = IPMI_BMC_SLAVE_ADDR;
+ msg[len++] = req->msg.netfn << 2;
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+ cs = len;
+ msg[len++] = IPMI_REMOTE_SWID;
+
+ entry->rq_seq = 0; /*should swseq start w 1?*/
+
+ msg[len++] = entry->rq_seq << 2;
+ msg[len++] = req->msg.cmd;
+
+ lprintf(LOG_DEBUG+1, ">> IPMI Request Session Header");
+ lprintf(LOG_DEBUG+1, ">> Authtype : %s",
+ val2str(IPMI_SESSION_AUTHTYPE_NONE, ipmi_authtype_session_vals));
+ lprintf(LOG_DEBUG+1, ">> Sequence : 0x%08lx",
+ (long)session->out_seq);
+ lprintf(LOG_DEBUG+1, ">> Session ID : 0x%08lx",
+ (long)0);
+
+ lprintf(LOG_DEBUG+1, ">> IPMI Request Message Header");
+ lprintf(LOG_DEBUG+1, ">> Rs Addr : %02x", IPMI_BMC_SLAVE_ADDR);
+ lprintf(LOG_DEBUG+1, ">> NetFn : %02x", req->msg.netfn);
+ lprintf(LOG_DEBUG+1, ">> Rs LUN : %01x", 0);
+ lprintf(LOG_DEBUG+1, ">> Rq Addr : %02x", IPMI_REMOTE_SWID);
+ lprintf(LOG_DEBUG+1, ">> Rq Seq : %02x", entry->rq_seq);
+ lprintf(LOG_DEBUG+1, ">> Rq Lun : %01x", 0);
+ lprintf(LOG_DEBUG+1, ">> Command : %02x", req->msg.cmd);
+
+ /* message data */
+ if (req->msg.data_len) {
+ memcpy(msg+len, req->msg.data, req->msg.data_len);
+ len += req->msg.data_len;
+ }
+
+ /* second checksum */
+ tmp = len - cs;
+ msg[len++] = ipmi_csum(msg+cs, tmp);
+
+ entry->msg_len = len;
+ entry->msg_data = msg;
+
+ return entry;
+}
+
+
+
+/*
+ * is_sol_packet
+ */
+static int
+is_sol_packet(struct ipmi_rs * rsp)
+{
+ return (rsp &&
+ (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
+ (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL));
+}
+
+
+
+/*
+ * sol_response_acks_packet
+ */
+static int
+sol_response_acks_packet(
+ struct ipmi_rs * rsp,
+ struct ipmi_v2_payload * payload)
+{
+ return (is_sol_packet(rsp) &&
+ payload &&
+ (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL) &&
+ (rsp->payload.sol_packet.acked_packet_number ==
+ payload->payload.sol_packet.packet_sequence_number));
+}
+
+
+
+/*
+ * ipmi_lanplus_send_payload
+ *
+ */
+struct ipmi_rs *
+ipmi_lanplus_send_payload(
+ struct ipmi_intf * intf,
+ struct ipmi_v2_payload * payload)
+{
+ struct ipmi_rs * rsp = NULL;
+ uint8_t * msg_data = NULL;
+ int msg_length;
+ struct ipmi_session * session = intf->session;
+ int itry = 0;
+ int xmit = 1;
+ time_t ltime;
+ int rv = 0;
+ struct ipmi_rq_entry *entry = NULL;
+
+ if (!intf->opened && intf->open && intf->open(intf) < 0)
+ return NULL;
+
+ while (itry < session->retry) {
+ ltime = time(NULL);
+
+ if (xmit) {
+
+ if (payload->payload_type == IPMI_PAYLOAD_TYPE_IPMI)
+ {
+ /*
+ * Build an IPMI v1.5 or v2 command
+ */
+ struct ipmi_rq * ipmi_request = payload->payload.ipmi_request.request;
+
+ lprintf(LOG_DEBUG, "");
+ lprintf(LOG_DEBUG, ">> Sending IPMI command payload");
+ lprintf(LOG_DEBUG, ">> netfn : 0x%02x", ipmi_request->msg.netfn);
+ lprintf(LOG_DEBUG, ">> command : 0x%02x", ipmi_request->msg.cmd);
+ lprintf(LOG_DEBUG, ">> data_len: %d", ipmi_request->msg.data_len);
+
+ if (verbose > 1)
+ {
+ char msg[256];
+ uint16_t i; size_t n;
+ sprintf(msg, ">> data : ");
+ n = strlen(msg);
+ for (i = 0; i < ipmi_request->msg.data_len; ++i) {
+ sprintf(&msg[n], "0x%02x ", ipmi_request->msg.data[i]);
+ n += 5;
+ if ((n+5) >= sizeof(msg)) break;
+ }
+ // strcat(msg,"\n");
+ lprintf(LOG_DEBUG, msg);
+ }
+
+
+ /*
+ * If we are presession, and the command is GET CHANNEL AUTHENTICATION
+ * CAPABILITIES, we will build the command in v1.5 format. This is so
+ * that we can ask any server whether it supports IPMI v2 / RMCP+
+ * before we attempt to open a v2.x session.
+ */
+ if ((ipmi_request->msg.netfn == IPMI_NETFN_APP) &&
+ (ipmi_request->msg.cmd == IPMI_GET_CHANNEL_AUTH_CAP) &&
+ // (!ipmi_oem_active(intf, "hp")) &&
+ (session->v2_data.bmc_id == 0)) // jme - check
+ {
+ lprintf(LOG_DEBUG+1, "BUILDING A v1.5 COMMAND");
+ entry = ipmi_lanplus_build_v15_ipmi_cmd(intf, ipmi_request);
+ }
+ else
+ {
+ lprintf(LOG_DEBUG+1, "BUILDING A v2 COMMAND");
+ entry = ipmi_lanplus_build_v2x_ipmi_cmd(intf, ipmi_request);
+ }
+
+ if (entry == NULL) {
+ lprintf(LOG_ERR, "Aborting send command, unable to build");
+ return NULL;
+ }
+
+ msg_data = entry->msg_data;
+ msg_length = entry->msg_len;
+ // entry is freed later for IPMI payloads
+ }
+
+ else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST)
+ {
+ lprintf(LOG_DEBUG, ">> SENDING AN OPEN SESSION REQUEST\n");
+ /* assert(session->v2_data.session_state == LANPLUS_STATE_PRESESSION); */
+ if (session->v2_data.session_state != LANPLUS_STATE_PRESESSION) {
+ /* Sometimes state==OPEN_SESSION_SENT(1) */
+ lprintf(LOG_ERR, "lanplus open session_state %x != LANPLUSLANPLUS_STATE_PRESESSION\n",session->v2_data.session_state);
+ return NULL;
+ } /*ARC, removed assert*/
+
+ rv = ipmi_lanplus_build_v2x_msg(intf, /* in */
+ payload, /* in */
+ &msg_length, /* out*/
+ &msg_data, /* out*/
+ 0); /* irrelevant for this msg*/
+ if (rv != 0) return NULL;
+
+ }
+
+ else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RAKP_1)
+ {
+ lprintf(LOG_DEBUG, ">> SENDING A RAKP 1 MESSAGE\n");
+ /* sometimes hit this assert - ARC */
+ // assert(session->v2_data.session_state ==
+ // LANPLUS_STATE_OPEN_SESSION_RECEIEVED);
+ if (session->v2_data.session_state !=
+ LANPLUS_STATE_OPEN_SESSION_RECEIEVED) {
+ lprintf(LOG_ERR, "lanplus rakp1 payload: session_state %x != LANPLUS_STATE_OPEN_SESSION_RECEIEVED\n",session->v2_data.session_state);
+ return NULL;
+ }
+
+ rv = ipmi_lanplus_build_v2x_msg(intf, /* in */
+ payload, /* in */
+ &msg_length, /* out*/
+ &msg_data, /* out*/
+ 0); /* irrelevant for this msg*/
+ if (rv != 0) return NULL;
+
+ }
+
+ else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RAKP_3)
+ {
+ lprintf(LOG_DEBUG, ">> SENDING A RAKP 3 MESSAGE\n");
+ // assert(session->v2_data.session_state ==
+ // LANPLUS_STATE_RAKP_2_RECEIVED);
+ if (session->v2_data.session_state !=
+ LANPLUS_STATE_RAKP_2_RECEIVED) {
+ /* Sometimes state==RAKP_3_SENT(5) */
+ lprintf(LOG_ERR, "lanplus rakp3 payload: session_state %x != LANPLUS_STATE_RAKP_2_RECEIVED, try=%d\n",session->v2_data.session_state,itry);
+ return NULL;
+ }
+
+ rv = ipmi_lanplus_build_v2x_msg(intf, /* in */
+ payload, /* in */
+ &msg_length, /* out*/
+ &msg_data, /* out*/
+ 0); /* irrelevant for this msg*/
+ if (rv != 0) return NULL;
+
+ }
+
+ else if (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL)
+ {
+ lprintf(LOG_DEBUG, ">> SENDING A SOL MESSAGE\n");
+ // assert(session->v2_data.session_state == LANPLUS_STATE_ACTIVE);
+ if (session->v2_data.session_state != LANPLUS_STATE_ACTIVE) {
+ lprintf(LOG_ERR, "lanplus session_state %x != LANPLUS_STATE_ACTIVE, try=%d\n",session->v2_data.session_state, itry);
+ return NULL;
+ } /*ARC, removed assert*/
+
+ rv = ipmi_lanplus_build_v2x_msg(intf, /* in */
+ payload, /* in */
+ &msg_length, /* out*/
+ &msg_data, /* out*/
+ 0); /* irrelevant for this msg*/
+ if (rv != 0) return NULL;
+ }
+
+ else
+ {
+ lprintf(LOG_ERR, "Payload type 0x%0x is unsupported!",
+ payload->payload_type);
+ // assert(0);
+ return NULL;
+ }
+
+
+ if (ipmi_lan_send_packet(intf, msg_data, msg_length) < 0) {
+ lprintf(LOG_ERR, "IPMI LAN send command failed");
+ free(msg_data); /*added in v2.8.5*/
+ return(NULL);
+ }
+ }
+
+ /* if we are set to noanswer we do not expect response */
+ if (intf->noanswer)
+ break;
+
+ lan2_usleep(0,recv_delay); /* wait 100us before doing recv */
+
+ /* Remember our connection state */
+ switch (payload->payload_type)
+ {
+ case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST:
+ session->v2_data.session_state = LANPLUS_STATE_OPEN_SESSION_SENT;
+ break;
+ case IPMI_PAYLOAD_TYPE_RAKP_1:
+ session->v2_data.session_state = LANPLUS_STATE_RAKP_1_SENT;
+ break;
+ case IPMI_PAYLOAD_TYPE_RAKP_3:
+ session->v2_data.session_state = LANPLUS_STATE_RAKP_3_SENT;
+ break;
+ }
+
+
+ /*
+ * Special case for SOL outbound packets.
+ */
+ if (payload->payload_type == IPMI_PAYLOAD_TYPE_SOL)
+ {
+ if (!payload->payload.sol_packet.packet_sequence_number)
+ {
+ /* We're just sending an ACK. No need to retry. */
+ if (verbose > 2)
+ lprintf(LOG_INFO, "send_payload(SOL,ack) nowait"); /*ARC*/
+ break;
+ }
+ if (verbose > 2)
+ lprintf(LOG_INFO, "send_payload(SOL,timeout=%d)",intf->session->timeout); /*ARC*/
+
+ rsp = ipmi_lanplus_recv_sol(intf); /* Grab the next packet */
+
+ if (sol_response_acks_packet(rsp, payload)) {
+ if (verbose > 2)
+ lprintf(LOG_INFO, /*ARC*/
+ "send_payload(SOL) rsp acks_packet %d",
+ payload->payload.sol_packet.packet_sequence_number);
+ break;
+ }
+
+ else if (is_sol_packet(rsp) && rsp->data_len)
+ {
+ lprintf(LOG_INFO, /*ARC*/
+ "send_payload(SOL,%d,%d), rlen=%d seq=%d, no ack yet",
+ intf->session->timeout,itry,rsp->data_len,
+ payload->payload.sol_packet.packet_sequence_number);
+ /*
+ * We're still waiting for our ACK, but we got
+ * more data from the BMC. Send to handler.
+ */
+ intf->session->sol_data.sol_input_handler(rsp);
+ /* In order to avoid duplicate output, just set data_len to 0 */
+ rsp->data_len = 0; /*added 04/17/08*/
+ if (slow_link) break; /*ARC 09/01/09*/
+ }
+ else {
+ lprintf(LOG_INFO, /*ARC*/
+ "send_payload(SOL,%d,%d) sol_seq=%d rsp=%p no ack",
+ intf->session->timeout,itry,
+ payload->payload.sol_packet.packet_sequence_number,
+ rsp);
+ }
+ }
+
+
+ /* Non-SOL processing */
+ else
+ {
+ lprintf(LOG_INFO,
+ "send_payload(non-SOL) type=%d data",
+ payload->payload_type);
+ rsp = ipmi_lan_poll_recv(intf);
+ if (rsp) {
+ lprintf(LOG_INFO,
+ "send_payload(non-SOL) rsp dlen=%d, rs_seq=%d",
+ rsp->data_len,rsp->session.seq);
+ break;
+ }
+ }
+
+ xmit = ((u_long)(time(NULL) - ltime) >= intf->session->timeout);
+
+ lan2_usleep(0,5000); /*sleep 5.0ms before next try*/
+
+ if (xmit) {
+ /* incremet session timeout each try */
+ intf->session->timeout++;
+ }
+
+ itry++;
+ }
+
+ /* Reset timeout after retry loop completes */
+ intf->session->timeout = lan2_timeout;
+
+ /* IPMI messages are deleted under ipmi_lan_poll_recv() */
+ switch (payload->payload_type) {
+ case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST:
+ case IPMI_PAYLOAD_TYPE_RAKP_1:
+ case IPMI_PAYLOAD_TYPE_RAKP_3:
+ free(msg_data);
+ break;
+ }
+ return rsp;
+}
+
+
+
+/*
+ * is_sol_partial_ack
+ *
+ * Determine if the response is a partial ACK/NACK that indicates
+ * we need to resend part of our packet.
+ *
+ * returns the number of characters we need to resend, or
+ * 0 if this isn't an ACK or we don't need to resend anything
+ */
+int is_sol_partial_ack(
+ struct ipmi_intf * intf,
+ struct ipmi_v2_payload * v2_payload,
+ struct ipmi_rs * rs)
+{
+ int chars_to_resend = 0;
+
+ if (v2_payload &&
+ rs &&
+ is_sol_packet(rs) &&
+ sol_response_acks_packet(rs, v2_payload) &&
+ (rs->payload.sol_packet.accepted_character_count <
+ v2_payload->payload.sol_packet.character_count))
+ {
+ lprintf(LOG_INFO, "is_sol_partial_ack: count=%d > accepted=%d",
+ v2_payload->payload.sol_packet.character_count,
+ rs->payload.sol_packet.accepted_character_count );
+ if (ipmi_oem_active(intf, "intelplus") &&
+ rs->payload.sol_packet.accepted_character_count == 0)
+ return 0;
+
+ chars_to_resend =
+ v2_payload->payload.sol_packet.character_count -
+ rs->payload.sol_packet.accepted_character_count;
+ }
+
+ return chars_to_resend;
+}
+
+
+
+/*
+ * set_sol_packet_sequence_number
+ */
+static void set_sol_packet_sequence_number(
+ struct ipmi_intf * intf,
+ struct ipmi_v2_payload * v2_payload)
+{
+ /* Keep our sequence number sane */
+ if (intf->session->sol_data.sequence_number > 0x0F)
+ intf->session->sol_data.sequence_number = 1;
+
+ v2_payload->payload.sol_packet.packet_sequence_number =
+ intf->session->sol_data.sequence_number++;
+}
+
+
+
+/*
+ * ipmi_lanplus_send_sol
+ *
+ * Sends a SOL packet.. We handle partial ACK/NACKs from the BMC here.
+ *
+ * Returns a pointer to the SOL ACK we received, or
+ * 0 on failure
+ *
+ */
+struct ipmi_rs *
+ipmi_lanplus_send_sol(
+ struct ipmi_intf * intf,
+ void * v2_in)
+{
+ struct ipmi_v2_payload * v2_payload = v2_in;
+ struct ipmi_rs * rs;
+
+ /*
+ * chars_to_resend indicates either that we got a NACK telling us
+ * that we need to resend some part of our data.
+ */
+ int chars_to_resend = 0;
+
+ v2_payload->payload_type = IPMI_PAYLOAD_TYPE_SOL;
+
+ /*
+ * Payload length is just the length of the character
+ * data here.
+ */
+ v2_payload->payload_length = v2_payload->payload.sol_packet.character_count;
+
+ v2_payload->payload.sol_packet.acked_packet_number = 0; /* NA */
+
+ set_sol_packet_sequence_number(intf, v2_payload);
+
+ v2_payload->payload.sol_packet.accepted_character_count = 0; /* NA */
+
+ rs = ipmi_lanplus_send_payload(intf, v2_payload);
+
+ /* Determine if we need to resend some of our data */
+ chars_to_resend = is_sol_partial_ack(intf, v2_payload, rs);
+
+ if ((verbose > 2) && (chars_to_resend > 0)) { /*show warnings if here*/
+ if (rs == NULL)
+ lprintf(LOG_INFO,"send_sol: nresend=%d no rs",chars_to_resend);
+ else
+ lprintf(LOG_INFO,"send_sol: nresend=%d unavail=%d nack=%d",
+ chars_to_resend,
+ rs->payload.sol_packet.transfer_unavailable,
+ rs->payload.sol_packet.is_nack);
+ }
+
+ while (rs && !rs->payload.sol_packet.transfer_unavailable &&
+ !rs->payload.sol_packet.is_nack &&
+ chars_to_resend)
+ {
+ /*
+ * We first need to handle any new data we might have
+ * received in our NACK
+ */
+ if (rs->data_len)
+ intf->session->sol_data.sol_input_handler(rs);
+
+ set_sol_packet_sequence_number(intf, v2_payload);
+
+ /* Just send the required data */
+ memmove(v2_payload->payload.sol_packet.data,
+ v2_payload->payload.sol_packet.data +
+ rs->payload.sol_packet.accepted_character_count,
+ chars_to_resend);
+
+ v2_payload->payload.sol_packet.character_count = (uint16_t)chars_to_resend;
+
+ v2_payload->payload_length = v2_payload->payload.sol_packet.character_count;
+
+ rs = ipmi_lanplus_send_payload(intf, v2_payload);
+
+ chars_to_resend = is_sol_partial_ack(intf, v2_payload, rs);
+ }
+
+ return rs;
+}
+
+
+
+/*
+ * check_sol_packet_for_new_data
+ *
+ * Determine whether the SOL packet has already been seen
+ * and whether the packet has new data for us.
+ *
+ * This function has the side effect of removing an previously
+ * seen data, and moving new data to the front.
+ *
+ * It also "Remembers" the data so we don't get repeats.
+ *
+ * returns the number of new bytes in the SOL packet
+ */
+static int
+check_sol_packet_for_new_data(
+ struct ipmi_intf * intf,
+ struct ipmi_rs *rsp)
+{
+ static uint8_t last_received_sequence_number = 0;
+ static uint8_t last_received_byte_count = 0;
+ int new_data_size = 0;
+
+
+ if (rsp &&
+ (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
+ (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL))
+ {
+ /* Store the data length before we mod it */
+ uint8_t unaltered_data_len = (uint8_t)rsp->data_len;
+
+ lprintf(LOG_INFO,"check_sol_packet_for_new_data: "
+ "rsp dlen=%d rs_seq=%d sol_rseq=%d",
+ rsp->data_len, rsp->session.seq,
+ rsp->payload.sol_packet.packet_sequence_number);
+ if (rsp->payload.sol_packet.packet_sequence_number ==
+ last_received_sequence_number)
+ {
+ if (verbose > 2)
+ lprintf(LOG_INFO,"check_sol: seq=%x retry match len=%d nlast=%d",
+ rsp->payload.sol_packet.packet_sequence_number,
+ rsp->data_len, last_received_byte_count);
+ /*
+ * This is the same as the last packet, but may include
+ * extra data
+ */
+ new_data_size = rsp->data_len - last_received_byte_count;
+
+ if (new_data_size > 0)
+ {
+ /* We have more data to process */
+ memmove(rsp->data,
+ rsp->data +
+ rsp->data_len - new_data_size,
+ new_data_size);
+ }
+
+ rsp->data_len = new_data_size;
+ }
+
+ /*
+ * Remember the data for next round
+ * if non-zero sequence number
+ */
+ if (rsp->payload.sol_packet.packet_sequence_number)
+ {
+ last_received_sequence_number =
+ rsp->payload.sol_packet.packet_sequence_number;
+
+ last_received_byte_count = unaltered_data_len;
+ }
+ else if (rsp->data_len > 0)
+ { /* rsp sol seq is zero, so ignore any data */
+ lprintf(LOG_INFO,"check_sol: rseq=%d rlen=%d ack, zero data",
+ rsp->payload.sol_packet.packet_sequence_number,
+ rsp->data_len);
+ rsp->data_len = 0;
+ }
+ }
+
+
+ return new_data_size;
+}
+
+
+
+/*
+ * ack_sol_packet
+ *
+ * Provided the specified packet looks reasonable, ACK it.
+ */
+static void
+ack_sol_packet(
+ struct ipmi_intf * intf,
+ struct ipmi_rs * rsp)
+{
+ if (rsp &&
+ (rsp->session.authtype == IPMI_SESSION_AUTHTYPE_RMCP_PLUS) &&
+ (rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) &&
+ (rsp->payload.sol_packet.packet_sequence_number))
+ {
+ struct ipmi_v2_payload ack;
+
+ memset(&ack, 0, sizeof(struct ipmi_v2_payload));
+
+ ack.payload_type = IPMI_PAYLOAD_TYPE_SOL;
+
+ /*
+ * Payload length is just the length of the character
+ * data here.
+ */
+ ack.payload_length = 0;
+
+ /* ACK packets have sequence numbers of 0 */
+ ack.payload.sol_packet.packet_sequence_number = 0;
+
+ ack.payload.sol_packet.acked_packet_number =
+ rsp->payload.sol_packet.packet_sequence_number;
+
+ ack.payload.sol_packet.accepted_character_count = (uint8_t)rsp->data_len;
+
+ if (verbose > 2)
+ lprintf(LOG_INFO,"ack of seq_num 0x%x",rsp->payload.sol_packet.packet_sequence_number);
+ ipmi_lanplus_send_payload(intf, &ack);
+ }
+}
+
+
+
+/*
+ * ipmi_lanplus_recv_sol
+ *
+ * Receive a SOL packet and send an ACK in response.
+ *
+ */
+struct ipmi_rs *
+ipmi_lanplus_recv_sol(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp = ipmi_lan_poll_recv(intf);
+
+ if (rsp && rsp->session.authtype != 0)
+ {
+ ack_sol_packet(intf, rsp);
+
+ /*
+ * Remembers the data sent, and alters the data to just
+ * include the new stuff.
+ */
+ check_sol_packet_for_new_data(intf, rsp);
+ }
+ return rsp;
+}
+
+
+
+/**
+ * ipmi_lanplus_send_ipmi_cmd
+ *
+ * Build a payload request and dispatch it.
+ */
+struct ipmi_rs *
+ipmi_lanplus_send_ipmi_cmd(
+ struct ipmi_intf * intf,
+ struct ipmi_rq * req)
+{
+ struct ipmi_v2_payload v2_payload;
+
+ v2_payload.payload_type = IPMI_PAYLOAD_TYPE_IPMI;
+ // v2_payload.payload_length = 7 + req->msg.data_len; /*initial ++++*/
+ v2_payload.payload.ipmi_request.request = req;
+
+ // if (verbose > 2) lprintf(LOG_INFO,"ipmi cmd payload"); /*++++*/
+ return ipmi_lanplus_send_payload(intf, &v2_payload);
+}
+
+
+/*
+ * ipmi_get_auth_capabilities_cmd
+ *
+ * This command may have to be sent twice. We first ask for the
+ * authentication capabilities with the "request IPMI v2 data bit"
+ * set. If this fails, we send the same command without that bit
+ * set.
+ *
+ * param intf is the initialized (but possibly) pre-session interface
+ * on which we will send the command
+ * param auth_cap [out] will be initialized to hold the Get Channel
+ * Authentication Capabilities return data on success. Its
+ * contents will be undefined on error.
+ *
+ * returns 0 on success
+ * non-zero if we were unable to contact the BMC, or we cannot
+ * get a successful response
+ *
+ */
+static int
+ipmi_get_auth_capabilities_cmd(
+ struct ipmi_intf * intf,
+ struct get_channel_auth_cap_rsp * auth_cap)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req;
+ uint8_t msg_data[2];
+ uint8_t backupBridgePossible;
+
+ backupBridgePossible = bridgePossible;
+
+ bridgePossible = 0;
+
+ msg_data[0] = IPMI_LAN_CHANNEL_E | 0x80; // Ask for IPMI v2 data as well
+ msg_data[1] = intf->session->privlvl;
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_APP; // 0x06
+ req.msg.cmd = IPMI_GET_CHANNEL_AUTH_CAP; // 0x38
+ req.msg.data = msg_data;
+ req.msg.data_len = 2;
+
+ rsp = intf->sendrecv(intf, &req);
+
+ if (rsp == NULL || rsp->ccode > 0) {
+ /*
+ * It's very possible that this failed because we asked for IPMI
+ * v2 data. Ask again, without requesting IPMI v2 data.
+ */
+ msg_data[0] &= 0x7F;
+
+ rsp = intf->sendrecv(intf, &req);
+
+ if (rsp == NULL) {
+ lprintf(LOG_INFO, "Get Auth Capabilities error");
+ return 1;
+ }
+ if (rsp->ccode > 0) {
+ lprintf(LOG_INFO, "Get Auth Capabilities error: %s",
+ val2str(rsp->ccode, completion_code_vals));
+ return 1;
+ }
+ }
+
+
+ memcpy(auth_cap,
+ rsp->data,
+ sizeof(struct get_channel_auth_cap_rsp));
+
+ bridgePossible = backupBridgePossible;
+
+ return 0;
+}
+
+
+
+static int
+ipmi_close_session_cmd(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req;
+ uint8_t msg_data[4];
+ uint32_t bmc_session_lsbf;
+ uint8_t backupBridgePossible;
+
+ if (intf->session->v2_data.session_state != LANPLUS_STATE_ACTIVE)
+ return -1;
+
+ backupBridgePossible = bridgePossible;
+
+ intf->target_addr = IPMI_BMC_SLAVE_ADDR;
+ bridgePossible = 0;
+
+ bmc_session_lsbf = intf->session->v2_data.bmc_id;
+#if WORDS_BIGENDIAN
+ bmc_session_lsbf = BSWAP_32(bmc_session_lsbf);
+#endif
+
+ memcpy(&msg_data, &bmc_session_lsbf, 4);
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.cmd = 0x3c;
+ req.msg.data = msg_data;
+ req.msg.data_len = 4;
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ /* Looks like the session was closed */
+ lprintf(LOG_ERR, "Close Session command failed");
+ return -1;
+ }
+ if (verbose > 2)
+ printbuf(rsp->data, rsp->data_len, "close_session");
+
+ if (rsp->ccode == 0x87) {
+ lprintf(LOG_ERR, "Failed to Close Session: invalid "
+ "session ID %08lx",
+ (long)intf->session->v2_data.bmc_id);
+ return -1;
+ }
+ if (rsp->ccode > 0) {
+ lprintf(LOG_ERR, "Close Session command failed: %s",
+ val2str(rsp->ccode, completion_code_vals));
+ return -1;
+ }
+
+ lprintf(LOG_DEBUG, "Closed Session %08lx\n",
+ (long)intf->session->v2_data.bmc_id);
+
+ bridgePossible = backupBridgePossible;
+
+ return 0;
+}
+
+
+
+/*
+ * ipmi_lanplus_open_session
+ *
+ * Build and send the open session command. See section 13.17 of the IPMI
+ * v2 specification for details.
+ */
+static int
+ipmi_lanplus_open_session(struct ipmi_intf * intf)
+{
+ struct ipmi_v2_payload v2_payload;
+ struct ipmi_session * session = intf->session;
+ uint8_t * msg;
+ struct ipmi_rs * rsp;
+ int rc = 0;
+
+
+ lprintf(LOG_INFO,"ipmi_lanplus_open_session, verbose=%d\n",
+ verbose);
+ /*
+ * Build an Open Session Request Payload
+ */
+ msg = (uint8_t*)malloc(IPMI_OPEN_SESSION_REQUEST_SIZE);
+ if (msg == NULL) {
+ lprintf(LOG_ERR, "lanplus: malloc failure");
+ return -1;
+ }
+
+ memset(msg, 0, IPMI_OPEN_SESSION_REQUEST_SIZE);
+
+ msg[0] = 0; /* Message tag */
+ if (ipmi_oem_active(intf, "intelplus") || session->privlvl != IPMI_SESSION_PRIV_ADMIN)
+ msg[1] = session->privlvl;
+ else
+ msg[1] = 0; /* Give us highest privlg level based on supported algorithms */
+ msg[2] = 0; /* reserved */
+ msg[3] = 0; /* reserved */
+
+ /* Choose our session ID for easy recognition in the packet dump */
+ session->v2_data.console_id = 0xA0A2A3A4;
+ msg[4] = session->v2_data.console_id & 0xff;
+ msg[5] = (session->v2_data.console_id >> 8) & 0xff;
+ msg[6] = (session->v2_data.console_id >> 16) & 0xff;
+ msg[7] = (session->v2_data.console_id >> 24) & 0xff;
+
+
+ if (lanplus_get_requested_ciphers(session->cipher_suite_id,
+ &(session->v2_data.requested_auth_alg),
+ &(session->v2_data.requested_integrity_alg),
+ &(session->v2_data.requested_crypt_alg)))
+ {
+ lprintf(LOG_WARNING, "Unsupported cipher suite ID : %d\n",
+ session->cipher_suite_id);
+ free(msg);
+ return -1;
+ }
+
+
+ /*
+ * Authentication payload
+ */
+ msg[8] = 0; /* specifies authentication payload */
+ msg[9] = 0; /* reserved */
+ msg[10] = 0; /* reserved */
+ msg[11] = 8; /* payload length */
+ msg[12] = session->v2_data.requested_auth_alg;
+ msg[13] = 0; /* reserved */
+ msg[14] = 0; /* reserved */
+ msg[15] = 0; /* reserved */
+
+ /*
+ * Integrity payload
+ */
+ msg[16] = 1; /* specifies integrity payload */
+ msg[17] = 0; /* reserved */
+ msg[18] = 0; /* reserved */
+ msg[19] = 8; /* payload length */
+ msg[20] = session->v2_data.requested_integrity_alg;
+ msg[21] = 0; /* reserved */
+ msg[22] = 0; /* reserved */
+ msg[23] = 0; /* reserved */
+
+ /*
+ * Confidentiality/Encryption payload
+ */
+ msg[24] = 2; /* specifies confidentiality payload */
+ msg[25] = 0; /* reserved */
+ msg[26] = 0; /* reserved */
+ msg[27] = 8; /* payload length */
+ msg[28] = session->v2_data.requested_crypt_alg;
+ msg[29] = 0; /* reserved */
+ msg[30] = 0; /* reserved */
+ msg[31] = 0; /* reserved */
+
+
+ v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST;
+ v2_payload.payload_length = IPMI_OPEN_SESSION_REQUEST_SIZE;
+ v2_payload.payload.open_session_request.request = msg;
+
+ rsp = ipmi_lanplus_send_payload(intf, &v2_payload);
+
+ free(msg);
+
+ if (rsp == NULL) {
+ /* failsafe check for Dell PE1955 - ARCress 02/28/07 */
+ lprintf(LOG_WARNING, "Error in open session, no response.\n");
+ return -1;
+ }
+ if (verbose)
+ lanplus_dump_open_session_response(rsp);
+
+
+ if (rsp->payload.open_session_response.rakp_return_code !=
+ IPMI_RAKP_STATUS_NO_ERRORS)
+ {
+ lprintf(LOG_WARNING, "Error in open session response message : %s\n",
+ val2str(rsp->payload.open_session_response.rakp_return_code,
+ ipmi_rakp_return_codes));
+ return -1;
+ }
+ else
+ {
+ if (rsp->payload.open_session_response.console_id !=
+ session->v2_data.console_id) {
+ lprintf(LOG_WARNING, "Warning: Console session ID is not "
+ "what we requested");
+ }
+
+ session->v2_data.max_priv_level =
+ rsp->payload.open_session_response.max_priv_level;
+ session->v2_data.bmc_id =
+ rsp->payload.open_session_response.bmc_id;
+ session->v2_data.auth_alg =
+ rsp->payload.open_session_response.auth_alg;
+ session->v2_data.integrity_alg =
+ rsp->payload.open_session_response.integrity_alg;
+ session->v2_data.crypt_alg =
+ rsp->payload.open_session_response.crypt_alg;
+ session->v2_data.session_state =
+ LANPLUS_STATE_OPEN_SESSION_RECEIEVED;
+
+
+ /*
+ * Verify that we have agreed on a cipher suite
+ */
+ if (rsp->payload.open_session_response.auth_alg !=
+ session->v2_data.requested_auth_alg)
+ {
+ lprintf(LOG_WARNING, "Authentication algorithm 0x%02x is "
+ "not what we requested 0x%02x\n",
+ rsp->payload.open_session_response.auth_alg,
+ session->v2_data.requested_auth_alg);
+ rc = -1;
+ }
+ else if (rsp->payload.open_session_response.integrity_alg !=
+ session->v2_data.requested_integrity_alg)
+ {
+ lprintf(LOG_WARNING, "Integrity algorithm 0x%02x is "
+ "not what we requested 0x%02x\n",
+ rsp->payload.open_session_response.integrity_alg,
+ session->v2_data.requested_integrity_alg);
+ rc = -1;
+ }
+ else if (rsp->payload.open_session_response.crypt_alg !=
+ session->v2_data.requested_crypt_alg)
+ {
+ lprintf(LOG_WARNING, "Encryption algorithm 0x%02x is "
+ "not what we requested 0x%02x\n",
+ rsp->payload.open_session_response.crypt_alg,
+ session->v2_data.requested_crypt_alg);
+ rc = -1;
+ }
+
+ }
+
+ return rc;
+}
+
+
+
+/*
+ * ipmi_lanplus_rakp1
+ *
+ * Build and send the RAKP 1 message as part of the IPMI v2 / RMCP+ session
+ * negotiation protocol. We also read and validate the RAKP 2 message received
+ * from the BMC, here. See section 13.20 of the IPMI v2 specification for
+ * details.
+ *
+ * returns 0 on success
+ * 1 on failure
+ *
+ * Note that failure is only indicated if we have an internal error of
+ * some kind. If we actually get a RAKP 2 message in response to our
+ * RAKP 1 message, any errors will be stored in
+ * session->v2_data.rakp2_return_code and sent to the BMC in the RAKP
+ * 3 message.
+ */
+static int
+ipmi_lanplus_rakp1(struct ipmi_intf * intf)
+{
+ struct ipmi_v2_payload v2_payload;
+ struct ipmi_session * session = intf->session;
+ uint8_t * msg;
+ struct ipmi_rs * rsp;
+ int rc = 0;
+
+ /*
+ * Build a RAKP 1 message
+ */
+ msg = (uint8_t*)malloc(IPMI_RAKP1_MESSAGE_SIZE);
+ if (msg == NULL) {
+ lprintf(LOG_ERR, "lanplus: malloc failure");
+ return 1;
+ }
+ memset(msg, 0, IPMI_RAKP1_MESSAGE_SIZE);
+
+
+ msg[0] = 0; /* Message tag */
+
+ msg[1] = 0; /* reserved */
+ msg[2] = 0; /* reserved */
+ msg[3] = 0; /* reserved */
+
+ /* BMC session ID */
+ msg[4] = session->v2_data.bmc_id & 0xff;
+ msg[5] = (session->v2_data.bmc_id >> 8) & 0xff;
+ msg[6] = (session->v2_data.bmc_id >> 16) & 0xff;
+ msg[7] = (session->v2_data.bmc_id >> 24) & 0xff;
+
+
+ /* We need a 16 byte random number */
+ if (lanplus_rand(session->v2_data.console_rand, 16))
+ {
+ // ERROR;
+ lprintf(LOG_ERR, "ERROR generating random number "
+ "in ipmi_lanplus_rakp1");
+ free(msg);
+ return 1;
+ }
+ memcpy(msg + 8, session->v2_data.console_rand, 16);
+ #if WORDS_BIGENDIAN
+ lanplus_swap(msg + 8, 16);
+ #endif
+
+ if (verbose > 1)
+ printbuf(session->v2_data.console_rand, 16,
+ ">> Console generated random number");
+
+
+ /*
+ * Requested maximum privilege level.
+ */
+ msg[24] = 0x10; /* We will specify a name-only lookup */
+ msg[24] |= session->privlvl;
+ // msg[24] = session->privlvl | session->v2_data.lookupbit; *++++*
+ session->v2_data.requested_role = msg[24];
+ msg[25] = 0; /* reserved */
+ msg[26] = 0; /* reserved */
+
+
+ /* Username specification */
+ msg[27] = (uint8_t)strlen((const char *)session->username);
+ if (msg[27] > IPMI_MAX_USER_NAME_LENGTH)
+ {
+ lprintf(LOG_ERR, "ERROR: user name too long. "
+ "(Exceeds %d characters)",
+ IPMI_MAX_USER_NAME_LENGTH);
+ free(msg);
+ return 1;
+ }
+ memcpy(msg + 28, session->username, msg[27]);
+
+ v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RAKP_1;
+ v2_payload.payload_length =
+ IPMI_RAKP1_MESSAGE_SIZE - (16 - msg[27]);
+ v2_payload.payload.rakp_1_message.message = msg;
+
+ rsp = ipmi_lanplus_send_payload(intf, &v2_payload);
+
+ free(msg);
+
+ if (rsp == NULL)
+ {
+ lprintf(LOG_INFO, "> Error: no response from RAKP 1 message");
+ return 1;
+ }
+
+ session->v2_data.session_state = LANPLUS_STATE_RAKP_2_RECEIVED;
+
+ if (verbose)
+ lanplus_dump_rakp2_message(rsp, session->v2_data.auth_alg);
+
+ if (rsp->payload.rakp2_message.rakp_return_code != IPMI_RAKP_STATUS_NO_ERRORS)
+ {
+ lprintf(LOG_INFO, "RAKP 2 message indicates an error : %s",
+ val2str(rsp->payload.rakp2_message.rakp_return_code,
+ ipmi_rakp_return_codes));
+ rc = 1;
+ }
+
+ else
+ {
+ memcpy(session->v2_data.bmc_rand, rsp->payload.rakp2_message.bmc_rand, 16);
+ memcpy(session->v2_data.bmc_guid, rsp->payload.rakp2_message.bmc_guid, 16);
+
+ if (verbose > 2)
+ printbuf(session->v2_data.bmc_rand, 16, "bmc_rand");
+
+ /*
+ * It is at this point that we have to decode the random number and determine
+ * whether the BMC has authenticated.
+ */
+ if (! lanplus_rakp2_hmac_matches(session,
+ rsp->payload.rakp2_message.key_exchange_auth_code,
+ intf))
+ {
+ /* Error */
+ lprintf(LOG_INFO, "> RAKP 2 HMAC is invalid");
+ session->v2_data.rakp2_return_code = IPMI_RAKP_STATUS_INVALID_INTEGRITY_CHECK_VALUE;
+ rc = 1; /*added 03/28/07*/
+ }
+ else
+ {
+ /* Success */
+ session->v2_data.rakp2_return_code = IPMI_RAKP_STATUS_NO_ERRORS;
+ }
+ }
+
+ return rc;
+}
+
+
+
+/*
+ * ipmi_lanplus_rakp3
+ *
+ * Build and send the RAKP 3 message as part of the IPMI v2 / RMCP+ session
+ * negotiation protocol. We also read and validate the RAKP 4 message received
+ * from the BMC, here. See section 13.20 of the IPMI v2 specification for
+ * details.
+ *
+ * If the RAKP 2 return code is not IPMI_RAKP_STATUS_NO_ERRORS, we will
+ * exit with an error code immediately after sendint the RAKP 3 message.
+ *
+ * param intf is the intf that holds all the state we are concerned with
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+static int
+ipmi_lanplus_rakp3(struct ipmi_intf * intf)
+{
+ struct ipmi_v2_payload v2_payload;
+ struct ipmi_session * session = intf->session;
+ uint8_t * msg;
+ struct ipmi_rs * rsp;
+
+ if (session->v2_data.session_state != LANPLUS_STATE_RAKP_2_RECEIVED) {
+ lprintf(LOG_ERR, "lanplus: state %d not RAKP2_RECEIVED",
+ session->v2_data.session_state);
+ return 1; /*was assert*/
+ }
+
+ /*
+ * Build a RAKP 3 message
+ */
+ msg = (uint8_t*)malloc(IPMI_RAKP3_MESSAGE_MAX_SIZE);
+ if (msg == NULL) {
+ lprintf(LOG_ERR, "lanplus: malloc failure");
+ return 1;
+ }
+ memset(msg, 0, IPMI_RAKP3_MESSAGE_MAX_SIZE);
+
+ msg[0] = 0; /* Message tag */
+ msg[1] = session->v2_data.rakp2_return_code;
+
+ msg[2] = 0; /* reserved */
+ msg[3] = 0; /* reserved */
+
+ /* BMC session ID */
+ msg[4] = session->v2_data.bmc_id & 0xff;
+ msg[5] = (session->v2_data.bmc_id >> 8) & 0xff;
+ msg[6] = (session->v2_data.bmc_id >> 16) & 0xff;
+ msg[7] = (session->v2_data.bmc_id >> 24) & 0xff;
+
+ v2_payload.payload_type = IPMI_PAYLOAD_TYPE_RAKP_3;
+ v2_payload.payload_length = 8;
+ v2_payload.payload.rakp_3_message.message = msg;
+
+ /*
+ * If the rakp2 return code indicates and error, we don't have to
+ * generate an authcode or session integrity key. In that case, we
+ * are simply sending a RAKP 3 message to indicate to the BMC that the
+ * RAKP 2 message caused an error.
+ */
+ if (session->v2_data.rakp2_return_code == IPMI_RAKP_STATUS_NO_ERRORS)
+ {
+ uint32_t auth_length;
+
+ if (lanplus_generate_rakp3_authcode(msg + 8, session, &auth_length, intf))
+ {
+ /* Error */
+ lprintf(LOG_INFO, "> Error generating RAKP 3 authcode");
+ free(msg);
+ return 1;
+ }
+ else
+ {
+ /* Success */
+ v2_payload.payload_length += (uint16_t)auth_length;
+ }
+
+ /* Generate our Session Integrity Key, K1, and K2 */
+ if (lanplus_generate_sik(session))
+ {
+ /* Error */
+ lprintf(LOG_INFO, "> Error generating session integrity key");
+ free(msg);
+ return 1;
+ }
+ else if (lanplus_generate_k1(session))
+ {
+ /* Error */
+ lprintf(LOG_INFO, "> Error generating K1 key");
+ free(msg);
+ return 1;
+ }
+ else if (lanplus_generate_k2(session))
+ {
+ /* Error */
+ lprintf(LOG_INFO, "> Error generating K2 key");
+ free(msg);
+ return 1;
+ }
+ }
+
+
+ rsp = ipmi_lanplus_send_payload(intf, &v2_payload);
+
+ free(msg);
+
+ if (session->v2_data.rakp2_return_code != IPMI_RAKP_STATUS_NO_ERRORS)
+ {
+ /*
+ * If the previous RAKP 2 message received was deemed erroneous,
+ * we have nothing else to do here. We only sent the RAKP 3 message
+ * to indicate to the BMC that the RAKP 2 message failed.
+ */
+ lprintf(LOG_INFO, "> Error: RAKP2 return code %d",
+ session->v2_data.rakp2_return_code);
+ return 1;
+ }
+ else if (rsp == NULL)
+ {
+ lprintf(LOG_INFO, "> Error: no response from RAKP 3 message");
+ return 1;
+ }
+
+
+ /*
+ * We have a RAKP 4 message to chew on.
+ */
+ if (verbose)
+ lanplus_dump_rakp4_message(rsp, session->v2_data.auth_alg);
+
+
+ if (rsp->payload.open_session_response.rakp_return_code != IPMI_RAKP_STATUS_NO_ERRORS)
+ {
+ lprintf(LOG_INFO, "RAKP 4 message indicates an error : %s",
+ val2str(rsp->payload.rakp4_message.rakp_return_code,
+ ipmi_rakp_return_codes));
+ return 1;
+ }
+
+ else
+ {
+ /* Validate the authcode */
+ if (lanplus_rakp4_hmac_matches(session,
+ rsp->payload.rakp4_message.integrity_check_value,
+ intf))
+ {
+ /* Success */
+ session->v2_data.session_state = LANPLUS_STATE_ACTIVE;
+ }
+ else
+ {
+ /* Error */
+ lprintf(LOG_INFO, "> RAKP 4 message has invalid integrity check value");
+ return 1;
+ }
+ }
+
+ intf->abort = 0;
+ return 0;
+}
+
+
+
+/**
+ * ipmi_lan_close
+ */
+void
+ipmi_lanplus_close(struct ipmi_intf * intf)
+{
+ if (!intf->abort)
+ ipmi_close_session_cmd(intf);
+
+ if (intf->fd != SockInvalid) {
+#ifdef WIN32
+ closesocket(intf->fd);
+ WSACleanup();
+#else
+ close(intf->fd);
+#endif
+ intf->fd = 0;
+ }
+
+ ipmi_req_clear_entries();
+
+ if (intf->session)
+ free(intf->session);
+
+ intf->session = NULL;
+ intf->opened = 0;
+}
+
+
+
+static int
+ipmi_set_session_privlvl_cmd(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req;
+ uint8_t backupBridgePossible;
+ uint8_t privlvl = intf->session->privlvl;
+
+ if (privlvl <= IPMI_SESSION_PRIV_USER)
+ return 0; /* no need to set higher */
+
+ backupBridgePossible = bridgePossible;
+
+ bridgePossible = 0;
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.cmd = 0x3b;
+ req.msg.data = &privlvl;
+ req.msg.data_len = 1;
+
+ rsp = intf->sendrecv(intf, &req);
+ if (rsp == NULL) {
+ lprintf(LOG_ERR, "Set Session Privilege Level to %s failed",
+ val2str(privlvl, ipmi_privlvl_vals));
+ return -1;
+ }
+ if (verbose > 2)
+ printbuf(rsp->data, rsp->data_len, "set_session_privlvl");
+
+ if (rsp->ccode > 0) {
+ lprintf(LOG_ERR, "Set Session Privilege Level to %s failed: %s",
+ val2str(privlvl, ipmi_privlvl_vals),
+ val2str(rsp->ccode, completion_code_vals));
+ return -1;
+ }
+
+ lprintf(LOG_DEBUG, "Set Session Privilege Level to %s\n",
+ val2str(rsp->data[0], ipmi_privlvl_vals));
+
+ bridgePossible = backupBridgePossible;
+
+ return 0;
+}
+
+/**
+ * ipmi_lanplus_open
+ */
+int
+ipmi_lanplus_open(struct ipmi_intf * intf)
+{
+ int rc;
+ struct get_channel_auth_cap_rsp auth_cap;
+ SOCKADDR_T addr;
+ socklen_t addrlen;
+ struct ipmi_session *session;
+#ifdef HAVE_IPV6
+ struct addrinfo hints;
+ struct addrinfo *result, *rp;
+ char service[NI_MAXSERV];
+#else
+ char *temp;
+#endif
+
+ if (!intf || !intf->session)
+ return -1;
+ session = intf->session;
+
+
+ if (!session->port)
+ session->port = IPMI_LANPLUS_PORT;
+ if (!session->privlvl)
+ session->privlvl = IPMI_SESSION_PRIV_ADMIN;
+ if (!session->timeout)
+ session->timeout = lan2_timeout; /*default timeout*/
+ else lan2_timeout = session->timeout; /*set by caller*/
+ if (!session->retry)
+ session->retry = IPMI_LAN_RETRY;
+
+ if (session->hostname == NULL || strlen((const char *)session->hostname) == 0) {
+ lprintf(LOG_ERR, "No hostname specified!");
+ return -1;
+ }
+
+ intf->abort = 1;
+
+
+ /* Setup our lanplus session state */
+ session->v2_data.session_state = LANPLUS_STATE_PRESESSION;
+ session->v2_data.auth_alg = IPMI_AUTH_RAKP_NONE;
+ session->v2_data.crypt_alg = IPMI_CRYPT_NONE;
+ session->v2_data.console_id = 0x00;
+ session->v2_data.bmc_id = 0x00;
+ session->sol_data.sequence_number = 1;
+ //session->sol_data.last_received_sequence_number = 0;
+ //session->sol_data.last_received_byte_count = 0;
+ memset(session->v2_data.sik, 0, sizeof(session->v2_data.sik));
+ session->v2_data.sik_len = 0;
+
+ /* Kg is set in ipmi_intf */
+ //memset(session->v2_data.kg, 0, IPMI_KG_BUFFER_SIZE);
+
+#ifdef WIN32
+ {
+ DWORD rvl;
+ rvl = WSAStartup(0x0202,&lan2_ws);
+ if (rvl != 0) {
+ lprintf(LOG_ERR, "WSAStartup(2.2) error %ld, try 1.1\n", rvl);
+ rvl = WSAStartup(0x0101,&lan2_ws);
+ if (rvl != 0) {
+ lprintf(LOG_ERR, "WSAStartup(1.1) error %ld\n", rvl);
+ return((int)rvl);
+ }
+ }
+ }
+#endif
+
+#ifdef HAVE_IPV6
+ session->addrlen = 0;
+ memset(&session->addr, 0, sizeof(session->addr));
+ memset(&addr, 0, sizeof(addr));
+ sprintf(service, "%d", session->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; /* */
+
+ rc = getaddrinfo((char *)session->hostname, service, &hints, &result);
+ if (rc != 0) {
+ lprintf(LOG_ERR, "Address lookup for %s failed with %d",
+ session->hostname,rc);
+ return -1;
+ }
+
+ /* getaddrinfo() returns a list of address structures.
+ * Try each address until we successfully connect(2).
+ */
+ for (rp = result; rp != NULL; rp = rp->ai_next) {
+ intf->fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+ if (intf->fd == -1) continue;
+ /* valid protocols are IPPROTO_UDP, IPPROTO_IPV6 */
+ if (rp->ai_protocol == IPPROTO_TCP) continue; /*IPMI != TCP*/
+ lprintf(LOG_DEBUG, "lanplus socket(%d,%d,%d), connect(%d)",
+ rp->ai_family, rp->ai_socktype, rp->ai_protocol,
+ intf->fd );
+ if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
+ lprintf(LOG_DEBUG, "lanplus connect ok, addrlen=%d size=%d",
+ rp->ai_addrlen,sizeof(addr));
+ addrlen = rp->ai_addrlen;
+ memcpy(&addr, rp->ai_addr, addrlen);
+ // memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen);
+ session->addrlen = rp->ai_addrlen;
+ break; /* Success */
+ }
+ close(intf->fd);
+ intf->fd = -1;
+ }
+ freeaddrinfo(result); /* Done with addrinfo */
+ if (intf->fd < 0) {
+ lperror(LOG_ERR, "Connect to %s failed",
+ session->hostname);
+ intf->close(intf);
+ return -1;
+ }
+#else
+ /* open port to BMC via ipv4 */
+ addrlen = sizeof(struct sockaddr_in);
+ memset(&addr, 0, addrlen);
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons((uint16_t)session->port);
+
+#ifdef WIN32
+ rc = -1;
+#else
+ rc = inet_pton(AF_INET, (const char *)session->hostname, &addr.sin_addr);
+#endif
+ if (rc <= 0) {
+ struct hostent *host = gethostbyname((const char *)session->hostname);
+ if (host == NULL) {
+ lprintf(LOG_ERR, "Address lookup for %s failed",
+ session->hostname);
+ return -1;
+ }
+ addr.sin_family = host->h_addrtype;
+ memcpy(&addr.sin_addr, host->h_addr, host->h_length);
+ }
+
+ lprintf(LOG_DEBUG, "IPMI LAN host %s port %d",
+ session->hostname, ntohs(addr.sin_port));
+
+ intf->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (intf->fd == SockInvalid) {
+ lperror(LOG_ERR, "Socket failed");
+ return -1;
+ }
+
+
+ /* connect to UDP socket so we get async errors */
+ rc = connect(intf->fd, (struct sockaddr *)&addr, addrlen);
+ if (rc < 0) {
+ lperror(LOG_ERR, "Connect failed");
+ intf->close(intf);
+ return -1;
+ }
+#endif
+
+ intf->opened = 1;
+
+
+ /*
+ * Make sure the BMC supports IPMI v2 / RMCP+
+ *
+ * I'm not sure why we accept a failure for the first call
+ */
+ if (ipmi_get_auth_capabilities_cmd(intf, &auth_cap)) {
+ lan2_usleep(1,0);
+ if (ipmi_get_auth_capabilities_cmd(intf, &auth_cap))
+ {
+ lprintf(LOG_INFO, "Error issuing Get Channel "
+ "Authentication Capabilies request");
+ goto fail;
+ }
+ }
+
+ if (! auth_cap.v20_data_available)
+ {
+ lprintf(LOG_INFO, "This BMC does not support IPMI v2 / RMCP+");
+ goto fail;
+ }
+
+
+ /*
+ * Open session
+ */
+ if (ipmi_lanplus_open_session(intf)){
+ intf->close(intf);
+ goto fail;
+ }
+
+ /*
+ * RAKP 1
+ */
+ if (ipmi_lanplus_rakp1(intf)){
+ lprintf(LOG_ERROR,"LANPLUS error in RAKP1");
+ intf->close(intf);
+ goto fail;
+ }
+
+
+ /*
+ * RAKP 3
+ */
+ if (ipmi_lanplus_rakp3(intf)){
+ lprintf(LOG_ERROR,"LANPLUS error in RAKP3");
+ intf->close(intf);
+ goto fail;
+ }
+
+
+ lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n");
+
+ bridgePossible = 1;
+
+ rc = ipmi_set_session_privlvl_cmd(intf);
+ if (rc < 0) {
+ lprintf(LOG_ERROR,"LANPLUS error in set_session_privlvl");
+ intf->close(intf);
+ goto fail;
+ }
+
+#ifdef HAVE_IPV6
+ lan2_nodename[0] = 0;
+ lprintf(LOG_ERROR,"Connected to node %s\n", session->hostname);
+#else
+#ifdef WIN32
+ /* check for ws2_32.lib(getnameinfo) resolution */
+ lan2_nodename[0] = 0;
+#else
+ rc = getnameinfo((struct sockaddr *)&addr, sizeof(struct sockaddr_in),
+ lan2_nodename,sizeof(lan2_nodename), NULL,0,0);
+ if (rc != 0) {
+ lprintf(LOG_DEBUG, "LANPLUS: getnameinfo rv = %d\n",rc);
+ lan2_nodename[0] = 0;
+ }
+#endif
+ temp = inet_ntoa(addr.sin_addr);
+ lprintf(LOG_ERROR,"Connected to node %s %s\n",lan2_nodename,temp);
+#endif
+ return (int)(intf->fd);
+
+fail:
+ lprintf(LOG_ERR, "Error: Unable to establish IPMI v2 / RMCP+ session");
+ intf->opened = 0;
+ return -1;
+}
+
+
+
+void test_crypt1(void)
+{
+ uint8_t key[] =
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
+ 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14};
+
+ uint16_t bytes_encrypted;
+ uint16_t bytes_decrypted;
+ uint8_t decrypt_buffer[1000];
+ uint8_t encrypt_buffer[1000];
+
+ uint8_t data[] =
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x11, 0x12};
+
+ printbuf(data, sizeof(data), "original data");
+
+ if (lanplus_encrypt_payload(IPMI_CRYPT_AES_CBC_128,
+ key,
+ data,
+ sizeof(data),
+ encrypt_buffer,
+ &bytes_encrypted))
+ {
+ lprintf(LOG_ERR, "Encrypt test failed");
+ assert(0); /*assert for testing*/
+ }
+ printbuf(encrypt_buffer, bytes_encrypted, "encrypted payload");
+
+
+ if (lanplus_decrypt_payload(IPMI_CRYPT_AES_CBC_128,
+ key,
+ encrypt_buffer,
+ bytes_encrypted,
+ decrypt_buffer,
+ &bytes_decrypted))
+ {
+ lprintf(LOG_ERR, "Decrypt test failed\n");
+ assert(0); /*assert for testing*/
+ }
+ printbuf(decrypt_buffer, bytes_decrypted, "decrypted payload");
+
+ lprintf(LOG_DEBUG, "\nDone testing the encrypt/decyrpt methods!\n");
+ exit(0);
+}
+
+
+
+void test_crypt2(void)
+{
+ uint8_t key[] =
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
+ 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14};
+ uint8_t iv[] =
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
+ 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14};
+ uint8_t data[8] = "12345678";
+
+ uint8_t encrypt_buffer[1000];
+ uint8_t decrypt_buffer[1000];
+ uint32_t bytes_encrypted;
+ uint32_t bytes_decrypted;
+ int len;
+
+ len = (int)strlen((const char *)data),
+ printbuf((const uint8_t *)data, len, "input data");
+
+ lanplus_encrypt_aes_cbc_128(iv, key,
+ data, (uint32_t)len,
+ encrypt_buffer,
+ &bytes_encrypted);
+ printbuf((const uint8_t *)encrypt_buffer, bytes_encrypted, "encrypt_buffer");
+
+ lanplus_decrypt_aes_cbc_128(iv, key,
+ encrypt_buffer,
+ bytes_encrypted,
+ decrypt_buffer,
+ &bytes_decrypted);
+ printbuf((const uint8_t *)decrypt_buffer, bytes_decrypted, "decrypt_buffer");
+
+ lprintf(LOG_INFO, "\nDone testing the encrypt/decyrpt methods!\n");
+ exit(0);
+}
+
+
+/**
+ * send a get device id command to keep session active
+ */
+static int
+ipmi_lanplus_keepalive(struct ipmi_intf * intf)
+{
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req;
+
+ if (!intf->opened)
+ return 0;
+
+ // printf("lanplus_keepalive called\n"); /*++++*/
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.cmd = 0x01; /*GetDeviceID*/
+ req.msg.data_len = 0;
+ rsp = intf->sendrecv(intf, &req);
+ while (rsp != NULL && is_sol_packet(rsp)) {
+ /* rsp was SOL data instead of our answer */
+ /* since it didn't go through the sol recv, do sol recv stuff here */
+ // printf( "lanplus_keepalive got SOL rsp\n"); /*++++*/
+ ack_sol_packet(intf, rsp);
+ check_sol_packet_for_new_data(intf, rsp);
+ // printf( "lanplus_keepalive SOL data len %d\n",rsp->data_len); /*++++*/
+ if (rsp->data_len)
+ intf->session->sol_data.sol_input_handler(rsp);
+ rsp = ipmi_lan_poll_recv(intf);
+ if (rsp == NULL) /* the get device id answer never got back, but retry mechanism was bypassed by SOL data */
+ return 0; /* so get device id command never returned, the connection is still alive */
+ }
+
+ if (rsp == NULL)
+ return -1;
+ if (rsp->ccode > 0)
+ return -1;
+
+ return 0;
+}
+
+
+/**
+ * ipmi_lanplus_setup
+ */
+static int ipmi_lanplus_setup(struct ipmi_intf * intf)
+{
+
+ if (lanplus_seed_prng(16)) {
+ lprintf(LOG_ERR, "lanplus_seed_prng failure");
+ return -1;
+ }
+
+ intf->session = malloc(sizeof(struct ipmi_session));
+ if (intf->session == NULL) {
+ lprintf(LOG_ERR, "lanplus: malloc failure");
+ return -1;
+ }
+ memset(intf->session, 0, sizeof(struct ipmi_session));
+ return 0;
+}
+
+/* end of lanplus.c */
diff --git a/lib/lanplus/lanplus.h b/lib/lanplus/lanplus.h
new file mode 100644
index 0000000..f9ad7dd
--- /dev/null
+++ b/lib/lanplus/lanplus.h
@@ -0,0 +1,135 @@
+/*
+ * 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_LANPLUS_H
+#define IPMI_LANPLUS_H
+
+#include <ipmitool/ipmi.h>
+#include <openssl/sha.h>
+
+#define IPMI_LANPLUS_PORT 0x26f
+
+/*
+ * RAKP return codes. These values come from table 13-15 of the IPMI v2
+ * specification.
+ */
+#define IPMI_RAKP_STATUS_NO_ERRORS 0x00
+#define IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_SESSION 0x01
+#define IPMI_RAKP_STATUS_INVALID_SESSION_ID 0x02
+#define IPMI_RAKP_STATUS_INVALID_PAYLOAD_TYPE 0x03
+#define IPMI_RAKP_STATUS_INVALID_AUTHENTICATION_ALGORITHM 0x04
+#define IPMI_RAKP_STATUS_INVALID_INTEGRITTY_ALGORITHM 0x05
+#define IPMI_RAKP_STATUS_NO_MATCHING_AUTHENTICATION_PAYLOAD 0x06
+#define IPMI_RAKP_STATUS_NO_MATCHING_INTEGRITY_PAYLOAD 0x07
+#define IPMI_RAKP_STATUS_INACTIVE_SESSION_ID 0x08
+#define IPMI_RAKP_STATUS_INVALID_ROLE 0x09
+#define IPMI_RAKP_STATUS_UNAUTHORIZED_ROLE_REQUESTED 0x0A
+#define IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_ROLE 0x0B
+#define IPMI_RAKP_STATUS_INVALID_NAME_LENGTH 0x0C
+#define IPMI_RAKP_STATUS_UNAUTHORIZED_NAME 0x0D
+#define IPMI_RAKP_STATUS_UNAUTHORIZED_GUID 0x0E
+#define IPMI_RAKP_STATUS_INVALID_INTEGRITY_CHECK_VALUE 0x0F
+#define IPMI_RAKP_STATUS_INVALID_CONFIDENTIALITY_ALGORITHM 0x10
+#define IPMI_RAKP_STATUS_NO_CIPHER_SUITE_MATCH 0x11
+#define IPMI_RAKP_STATUS_ILLEGAL_PARAMTER 0x12
+
+
+#define IPMI_LAN_CHANNEL_1 0x07
+#define IPMI_LAN_CHANNEL_2 0x06
+#define IPMI_LAN_CHANNEL_E 0x0e
+
+#define IPMI_LAN_TIMEOUT 1
+#define IPMI_LAN_RETRY 4
+
+#define IPMI_PRIV_CALLBACK 1
+#define IPMI_PRIV_USER 2
+#define IPMI_PRIV_OPERATOR 3
+#define IPMI_PRIV_ADMIN 4
+#define IPMI_PRIV_OEM 5
+
+
+#define IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE 0x10
+
+
+/* Session message offsets, from table 13-8 of the v2 specification */
+#define IPMI_LANPLUS_OFFSET_AUTHTYPE 0x04
+#define IPMI_LANPLUS_OFFSET_PAYLOAD_TYPE 0x05
+#define IPMI_LANPLUS_OFFSET_SESSION_ID 0x06
+#define IPMI_LANPLUS_OFFSET_SEQUENCE_NUM 0x0A
+#define IPMI_LANPLUS_OFFSET_PAYLOAD_SIZE 0x0E
+#define IPMI_LANPLUS_OFFSET_PAYLOAD 0x10
+
+
+#define IPMI_GET_CHANNEL_AUTH_CAP 0x38
+
+/*
+ * Do not change these unless you understand how they interact.
+ * Note:
+ * OpenSSL 0.9.7: #define EVP_MAX_MD_SIZE (16+20) // The SSLv3 md5+sha1 type
+ * OpenSSL 0.9.8: #define EVP_MAX_MD_SIZE 64 // longest known is SHA512
+ */
+#define IPMI_MAX_INTEGRITY_PAD_SIZE EVP_MAX_MD_SIZE
+// HMAC_SHA256_128: 16 HMAC_SHA1_96: 12 HMAC_MD5: 16 MD5: 16
+#define IPMI_MAX_AUTH_CODE_SIZE EVP_MAX_MD_SIZE // must be at least 32.
+#define IPMI_MAX_MAC_SIZE EVP_MAX_MD_SIZE /* The largest mac we ever expect to generate */
+#define IPMI_MAX_CONF_HEADER_SIZE 0x20
+#define IPMI_MAX_PAYLOAD_SIZE 0xFFFF /* Includes confidentiality header/trailer */
+#define IPMI_MAX_CONF_TRAILER_SIZE 0x20
+
+#define IPMI_REQUEST_MESSAGE_SIZE 0x07
+#define IPMI_SHA1_AUTHCODE_SIZE 12
+#define IPMI_HMAC_MD5_AUTHCODE_SIZE 16
+#define IPMI_MD5_AUTHCODE_SIZE 16
+#define IPMI_HMAC_SHA256_AUTHCODE_SIZE 16
+#define SHA256_DIGEST_LENGTH 32 /*may appear in openssl/sha.h later*/
+
+/*
+ *This is accurate, as long as we're only passing 1 auth algorithm,
+ * one integrity algorithm, and 1 encyrption alogrithm
+ */
+#define IPMI_OPEN_SESSION_REQUEST_SIZE 32
+#define IPMI_RAKP1_MESSAGE_SIZE 44
+#define IPMI_RAKP3_MESSAGE_MAX_SIZE (8+EVP_MAX_MD_SIZE)
+
+#define IPMI_MAX_USER_NAME_LENGTH 16
+
+extern const struct valstr ipmi_privlvl_vals[];
+extern const struct valstr ipmi_authtype_vals[];
+
+extern struct ipmi_intf ipmi_lanplus_intf;
+
+struct ipmi_rs * ipmi_lan_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req);
+int ipmi_lanplus_open(struct ipmi_intf * intf);
+void ipmi_lanplus_close(struct ipmi_intf * intf);
+int ipmiv2_lan_ping(struct ipmi_intf * intf);
+
+#endif /*IPMI_LAN_H*/
diff --git a/lib/lanplus/lanplus_crypt.c b/lib/lanplus/lanplus_crypt.c
new file mode 100644
index 0000000..7f3095e
--- /dev/null
+++ b/lib/lanplus/lanplus_crypt.c
@@ -0,0 +1,1038 @@
+/*
+ * 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 <assert.h>
+#include <string.h>
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <ipmitool/bswap.h>
+#include <ipmitool/log.h>
+#include "lanplus.h"
+#include "lanplus_crypt.h"
+#include "lanplus_crypt_impl.h"
+
+/*
+ * lanplus_rakp2_hmac_matches
+ *
+ * param session holds all the state data that we need to generate the hmac
+ * param hmac is the HMAC sent by the BMC in the RAKP 2 message
+ *
+ * The HMAC was generated [per RFC2404] from :
+ *
+ * SIDm - Remote console session ID
+ * SIDc - BMC session ID
+ * Rm - Remote console random number
+ * Rc - BMC random number
+ * GUIDc - BMC guid
+ * ROLEm - Requested privilege level (entire byte)
+ * ULENGTHm - Username length
+ * <UNAMEm> - Username (absent for null user names)
+ *
+ * generated by using Kuid. I am aware that the subscripts on the values
+ * look backwards, but that's the way they are written in the specification.
+ *
+ * If the authentication algorithm is IPMI_AUTH_RAKP_NONE, we return success.
+ *
+ * return 0 on success (the authcode matches)
+ * 1 on failure (the authcode does not match)
+ */
+int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
+ const uint8_t * bmc_mac,
+ struct ipmi_intf * intf)
+{
+ uint8_t * buffer;
+ int bufferLength, i;
+ uint8_t mac[EVP_MAX_MD_SIZE];
+ uint32_t macLength;
+
+ uint32_t SIDm_lsbf, SIDc_lsbf;
+
+ if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
+ return 1;
+
+ /* We don't yet support other algorithms (was assert) */
+ if ((session->v2_data.auth_alg != IPMI_AUTH_RAKP_HMAC_SHA1) &&
+ (session->v2_data.auth_alg != IPMI_AUTH_RAKP_HMAC_MD5) &&
+ (session->v2_data.auth_alg != IPMI_AUTH_RAKP_HMAC_SHA256)) {
+ printf("Error, unsupported rakp2 auth alg %d\n",
+ session->v2_data.auth_alg);
+ return 1;
+ }
+
+ bufferLength =
+ 4 + /* SIDm */
+ 4 + /* SIDc */
+ 16 + /* Rm */
+ 16 + /* Rc */
+ 16 + /* GUIDc */
+ 1 + /* ROLEm */
+ 1 + /* ULENGTHm */
+ (int)strlen((const char *)session->username); /* optional */
+
+ buffer = malloc(bufferLength);
+ if (buffer == NULL) {
+ lprintf(LOG_ERR, "lanplus: malloc failure");
+ return 1;
+ }
+
+ /*
+ * Fill the buffer. I'm assuming that we're using the LSBF representation of the
+ * multibyte numbers in use.
+ */
+
+ /* SIDm */
+ SIDm_lsbf = session->v2_data.console_id;
+ #if WORDS_BIGENDIAN
+ SIDm_lsbf = BSWAP_32(SIDm_lsbf);
+ #endif
+
+ memcpy(buffer, &SIDm_lsbf, 4);
+
+ /* SIDc */
+ SIDc_lsbf = session->v2_data.bmc_id;
+ #if WORDS_BIGENDIAN
+ SIDc_lsbf = BSWAP_32(SIDc_lsbf);
+ #endif
+ memcpy(buffer + 4, &SIDc_lsbf, 4);
+
+ /* Rm */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ buffer[8 + i] = session->v2_data.console_rand[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ buffer[8 + i] = session->v2_data.console_rand[i];
+ #endif
+
+ /* Rc */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ buffer[24 + i] = session->v2_data.bmc_rand[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ buffer[24 + i] = session->v2_data.bmc_rand[i];
+ #endif
+
+ /* GUIDc */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ buffer[40 + i] = session->v2_data.bmc_guid[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ buffer[40 + i] = session->v2_data.bmc_guid[i];
+ #endif
+
+ /* ROLEm */
+ buffer[56] = session->v2_data.requested_role;
+
+ /* ULENGTHm */
+ buffer[57] = (uint8_t)strlen((const char *)session->username);
+
+ /* UserName [optional] */
+ for (i = 0; i < buffer[57]; ++i)
+ buffer[58 + i] = session->username[i];
+
+ if (verbose > 2)
+ {
+ lprintf(LOG_DEBUG,"rakp2 mac input buffer (%d bytes)", bufferLength);
+ }
+
+ /*
+ * The buffer is complete. Let's hash.
+ */
+ lanplus_HMAC(session->v2_data.auth_alg,
+ session->authcode,
+ IPMI_AUTHCODE_BUFFER_SIZE,
+ buffer,
+ bufferLength,
+ mac,
+ &macLength);
+
+ free(buffer);
+
+
+ if (verbose > 2)
+ {
+ printbuf(mac, macLength, ">> rakp2 mac as computed by the remote console");
+ }
+
+ return (memcmp(bmc_mac, mac, macLength) == 0);
+}
+
+
+
+/*
+ * lanplus_rakp4_hmac_matches
+ *
+ * param session holds all the state data that we need to generate the hmac
+ * param hmac is the HMAC sent by the BMC in the RAKP 4 message
+ *
+ * The HMAC was generated [per RFC2404] from :
+ *
+ * Rm - Remote console random number
+ * SIDc - BMC session ID
+ * GUIDc - BMC guid
+ *
+ * generated by using SIK (the session integrity key). I am aware that the
+ * subscripts on the values look backwards, but that's the way they are
+ * written in the specification.
+ *
+ * If the authentication algorithm is IPMI_AUTH_RAKP_NONE, we return success.
+ *
+ * return 1 on success (the authcode matches)
+ * 0 on failure (the authcode does not match)
+ *
+ */
+int lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
+ const uint8_t * bmc_mac,
+ struct ipmi_intf * intf)
+{
+ uint8_t * buffer;
+ int bufferLength, i;
+ uint8_t mac[EVP_MAX_MD_SIZE];
+ uint32_t macLength;
+ uint32_t cmpLength;
+ uint32_t SIDc_lsbf;
+ int unsupported = 0;
+ uint8_t alg;
+
+ if (ipmi_oem_active(intf, "intelplus")){
+ /* Intel BMC responds with the integrity Algorithm in RAKP4 */
+ if (session->v2_data.integrity_alg == IPMI_INTEGRITY_NONE)
+ return 1;
+
+ /* (Old) Intel BMC doesn't support other algorithms */
+ if ((session->v2_data.integrity_alg != IPMI_INTEGRITY_HMAC_SHA1_96) &&
+ (session->v2_data.integrity_alg != IPMI_INTEGRITY_HMAC_MD5_128)) {
+ printf("Error, unsupported rakp4 integrity_alg %d\n",
+ session->v2_data.integrity_alg);
+ return 1;
+ }
+ } else {
+ if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
+ return 1;
+
+ /* We don't yet support other algorithms (was assert) */
+ if ((session->v2_data.auth_alg != IPMI_AUTH_RAKP_HMAC_SHA1) &&
+ (session->v2_data.auth_alg != IPMI_AUTH_RAKP_HMAC_MD5) &&
+ (session->v2_data.auth_alg != IPMI_AUTH_RAKP_HMAC_SHA256)) {
+ printf("Error, unsupported rakp4 auth alg %d\n",
+ session->v2_data.auth_alg);
+ return 1;
+ }
+ }
+
+ bufferLength =
+ 16 + /* Rm */
+ 4 + /* SIDc */
+ 16; /* GUIDc */
+
+ buffer = (uint8_t *)malloc(bufferLength);
+ if (buffer == NULL) {
+ lprintf(LOG_ERR, "lanplus: malloc failure");
+ return 1;
+ }
+
+ /*
+ * Fill the buffer. I'm assuming that we're using the LSBF
+ * representation of the multibyte numbers in use.
+ */
+
+ /* Rm */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ buffer[i] = session->v2_data.console_rand[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ buffer[i] = session->v2_data.console_rand[i];
+ #endif
+
+
+ /* SIDc */
+ SIDc_lsbf = session->v2_data.bmc_id;
+ #if WORDS_BIGENDIAN
+ SIDc_lsbf = BSWAP_32(SIDc_lsbf);
+ #endif
+ memcpy(buffer + 16, &SIDc_lsbf, 4);
+
+
+ /* GUIDc */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ buffer[i + 20] = session->v2_data.bmc_guid[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ buffer[i + 20] = session->v2_data.bmc_guid[i];
+ #endif
+
+
+ if (verbose > 2)
+ {
+ printbuf((const uint8_t *)buffer, bufferLength, ">> rakp4 mac input buffer");
+ printbuf(session->v2_data.sik, session->v2_data.sik_len, ">> rakp4 mac key (sik)");
+ }
+
+
+ /*
+ * The buffer is complete. Let's hash.
+ */
+ alg = ( (ipmi_oem_active(intf, "intelplus"))
+ ? session->v2_data.integrity_alg
+ : session->v2_data.auth_alg );
+ lanplus_HMAC(alg,
+ session->v2_data.sik,
+ session->v2_data.sik_len,
+ buffer,
+ bufferLength,
+ mac,
+ &macLength);
+
+ if (verbose > 2)
+ {
+ printbuf(bmc_mac, macLength, ">> rakp4 mac as computed by the BMC");
+ printbuf(mac, macLength, ">> rakp4 mac as computed by the remote console");
+ }
+
+ if (ipmi_oem_active(intf, "intelplus")){
+ /* Intel BMC responds with the integrity Algorithm in RAKP4 */
+ switch(session->v2_data.integrity_alg)
+ {
+ case IPMI_INTEGRITY_HMAC_SHA1_96:
+ if (macLength != SHA_DIGEST_LENGTH) unsupported = 1;
+ cmpLength = IPMI_SHA1_AUTHCODE_SIZE;
+ break;
+ case IPMI_INTEGRITY_HMAC_MD5_128:
+ if (macLength != MD5_DIGEST_LENGTH) unsupported = 1;
+ cmpLength = IPMI_HMAC_MD5_AUTHCODE_SIZE;
+ break;
+ default:
+ unsupported = 1;
+ break;
+ }
+
+ } else {
+
+ /* We don't yet support other algorithms (was assert) */
+ switch(session->v2_data.auth_alg)
+ {
+ case IPMI_AUTH_RAKP_HMAC_SHA1:
+ if (macLength != SHA_DIGEST_LENGTH) unsupported = 1;
+ cmpLength = IPMI_SHA1_AUTHCODE_SIZE;
+ break;
+ case IPMI_AUTH_RAKP_HMAC_MD5 :
+ if (macLength != MD5_DIGEST_LENGTH) unsupported = 1;
+ cmpLength = IPMI_HMAC_MD5_AUTHCODE_SIZE;
+ break;
+ case IPMI_AUTH_RAKP_HMAC_SHA256:
+ if (macLength != SHA256_DIGEST_LENGTH) unsupported = 1;
+ cmpLength = IPMI_HMAC_SHA256_AUTHCODE_SIZE;
+ break;
+ default:
+ unsupported = 1;
+ break;
+ }
+ }
+ if (unsupported) {
+ printf("Unsupported rakp4 macLength %d for auth %d\n",
+ macLength, session->v2_data.auth_alg);
+ return 1;
+ }
+
+ free(buffer);
+ return (memcmp(bmc_mac, mac, cmpLength) == 0);
+}
+
+
+
+/*
+ * lanplus_generate_rakp3_auth_code
+ *
+ * This auth code is an HMAC generated with :
+ *
+ * Rc - BMC random number
+ * SIDm - Console session ID
+ * ROLEm - Requested privilege level (entire byte)
+ * ULENGTHm - Username length
+ * <USERNAME> - Usename (absent for null usernames)
+ *
+ * The key used to generated the MAC is Kuid
+ *
+ * I am aware that the subscripts look backwards, but that is the way they are
+ * written in the spec.
+ *
+ * param output_buffer [out] will hold the generated MAC
+ * param session [in] holds all the state data we need to generate the auth code
+ * param mac_length [out] will be set to the length of the auth code
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+int lanplus_generate_rakp3_authcode(uint8_t * output_buffer,
+ const struct ipmi_session * session,
+ uint32_t * mac_length,
+ struct ipmi_intf * intf)
+{
+ int ret = 0;
+ int input_buffer_length, i;
+ uint8_t * input_buffer;
+ uint32_t SIDm_lsbf;
+
+
+ if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
+ {
+ *mac_length = 0;
+ return 0;
+ }
+
+ /* We don't yet support other algorithms (was assert) */
+ if ((session->v2_data.auth_alg != IPMI_AUTH_RAKP_HMAC_SHA1) &&
+ (session->v2_data.auth_alg != IPMI_AUTH_RAKP_HMAC_MD5) &&
+ (session->v2_data.auth_alg != IPMI_AUTH_RAKP_HMAC_SHA256)) {
+ printf("Error, unsupported rakp3 auth alg %d\n",
+ session->v2_data.auth_alg);
+ return 1;
+ }
+
+ input_buffer_length =
+ 16 + /* Rc */
+ 4 + /* SIDm */
+ 1 + /* ROLEm */
+ 1 + /* ULENGTHm */
+ (int)strlen((const char *)session->username);
+
+ input_buffer = malloc(input_buffer_length);
+ if (input_buffer == NULL) {
+ lprintf(LOG_ERR, "lanplus: malloc failure");
+ return 1;
+ }
+
+ /*
+ * Fill the buffer. I'm assuming that we're using the LSBF representation of the
+ * multibyte numbers in use.
+ */
+
+ /* Rc */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ input_buffer[i] = session->v2_data.bmc_rand[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ input_buffer[i] = session->v2_data.bmc_rand[i];
+ #endif
+
+ /* SIDm */
+ SIDm_lsbf = session->v2_data.console_id;
+ #if WORDS_BIGENDIAN
+ SIDm_lsbf = BSWAP_32(SIDm_lsbf);
+ #endif
+ memcpy(input_buffer + 16, &SIDm_lsbf, 4);
+
+ /* ROLEm */
+ if (ipmi_oem_active(intf, "intelplus"))
+ input_buffer[20] = session->privlvl;
+ else
+ input_buffer[20] = session->v2_data.requested_role;
+
+ /* ULENGTHm */
+ input_buffer[21] = (uint8_t)strlen((const char *)session->username);
+
+ /* USERNAME */
+ for (i = 0; i < input_buffer[21]; ++i)
+ input_buffer[22 + i] = session->username[i];
+
+ if (verbose > 2)
+ {
+ printbuf((const uint8_t *)input_buffer, input_buffer_length, ">> rakp3 mac input buffer");
+ printbuf((const uint8_t *)session->authcode, IPMI_AUTHCODE_BUFFER_SIZE, ">> rakp3 mac key");
+ }
+
+ lanplus_HMAC(session->v2_data.auth_alg,
+ session->authcode,
+ IPMI_AUTHCODE_BUFFER_SIZE,
+ input_buffer,
+ input_buffer_length,
+ output_buffer,
+ mac_length);
+
+ if (verbose > 2)
+ printbuf((const uint8_t *)output_buffer, *mac_length, "generated rakp3 mac");
+
+
+ free(input_buffer);
+
+ return ret;
+}
+
+
+
+/*
+ * lanplus_generate_sik
+ *
+ * Generate the session integrity key (SIK) used for integrity checking
+ * during the IPMI v2 / RMCP+ session
+ *
+ * This session integrity key is a HMAC generated with :
+ *
+ * Rm - Console generated random number
+ * Rc - BMC generated random number
+ * ROLEm - Requested privilege level (entire byte)
+ * ULENGTHm - Username length
+ * <USERNAME> - Usename (absent for null usernames)
+ *
+ * The key used to generated the SIK is Kg if Kg is not null (two-key logins are
+ * enabled). Otherwise Kuid (the user authcode) is used as the key to genereate
+ * the SIK.
+ *
+ * I am aware that the subscripts look backwards, but that is the way they are
+ * written in the spec.
+ *
+ * param session [in/out] contains our input and output fields.
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+int lanplus_generate_sik(struct ipmi_session * session)
+{
+ uint8_t * input_buffer;
+ int input_buffer_length, i;
+ uint8_t * input_key;
+ uint32_t mac_length;
+ int unsupported = 0;
+
+ memset(session->v2_data.sik, 0, sizeof(session->v2_data.sik));
+ session->v2_data.sik_len = 0;
+
+ if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
+ return 0;
+
+ /* We don't yet support other algorithms (was assert) */
+ if ((session->v2_data.auth_alg != IPMI_AUTH_RAKP_HMAC_SHA1) &&
+ (session->v2_data.auth_alg != IPMI_AUTH_RAKP_HMAC_MD5) &&
+ (session->v2_data.auth_alg != IPMI_AUTH_RAKP_HMAC_SHA256)) {
+ printf("Error, unsupported sik auth alg %d\n",
+ session->v2_data.auth_alg);
+ return 1;
+ }
+
+ input_buffer_length =
+ 16 + /* Rm */
+ 16 + /* Rc */
+ 1 + /* ROLEm */
+ 1 + /* ULENGTHm */
+ (int)strlen((const char *)session->username);
+
+ input_buffer = malloc(input_buffer_length);
+ if (input_buffer == NULL) {
+ lprintf(LOG_ERR, "lanplus: malloc failure");
+ return 1;
+ }
+
+ /*
+ * Fill the buffer. I'm assuming that we're using the LSBF representation of the
+ * multibyte numbers in use.
+ */
+
+ /* Rm */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ input_buffer[i] = session->v2_data.console_rand[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ input_buffer[i] = session->v2_data.console_rand[i];
+ #endif
+
+
+ /* Rc */
+ #if WORDS_BIGENDIAN
+ for (i = 0; i < 16; ++i)
+ input_buffer[16 + i] = session->v2_data.bmc_rand[16 - 1 - i];
+ #else
+ for (i = 0; i < 16; ++i)
+ input_buffer[16 + i] = session->v2_data.bmc_rand[i];
+ #endif
+
+ /* ROLEm */
+ input_buffer[32] = session->v2_data.requested_role;
+
+ /* ULENGTHm */
+ input_buffer[33] = (uint8_t)strlen((const char *)session->username);
+
+ /* USERNAME */
+ for (i = 0; i < input_buffer[33]; ++i)
+ input_buffer[34 + i] = session->username[i];
+
+ if (session->v2_data.kg[0])
+ {
+ /* We will be hashing with Kg */
+ /*
+ * Section 13.31 of the IPMI v2 spec describes the SIK creation
+ * using Kg. It specifies that Kg should not be truncated.
+ * Kg is set in ipmi_intf.
+ */
+ input_key = session->v2_data.kg;
+ }
+ else
+ {
+ /* We will be hashing with Kuid */
+ input_key = session->authcode;
+ }
+
+
+ if (verbose >= 2)
+ printbuf((const uint8_t *)input_buffer, input_buffer_length, "session integrity key input");
+
+ lanplus_HMAC(session->v2_data.auth_alg,
+ input_key,
+ IPMI_AUTHCODE_BUFFER_SIZE,
+ input_buffer,
+ input_buffer_length,
+ session->v2_data.sik,
+ &mac_length);
+
+ free(input_buffer);
+ switch(session->v2_data.auth_alg)
+ {
+ case IPMI_AUTH_RAKP_HMAC_SHA1 :
+ if (mac_length != SHA_DIGEST_LENGTH) unsupported = 1; break;
+ case IPMI_AUTH_RAKP_HMAC_MD5 :
+ if (mac_length != MD5_DIGEST_LENGTH) unsupported = 1; break;
+ case IPMI_AUTH_RAKP_HMAC_SHA256:
+ if (mac_length != SHA256_DIGEST_LENGTH) unsupported = 1; break;
+ default : unsupported = 1; break;
+ }
+ if (unsupported) { /*was assert*/
+ printf("Unsupported sik macLength %d for auth %d\n",
+ mac_length, session->v2_data.auth_alg);
+ return 1;
+ }
+
+ session->v2_data.sik_len = (uint8_t)mac_length;
+
+ /*
+ * The key MAC generated is 20 bytes, but we will only be using the first
+ * 12 for SHA1 96
+ */
+ if (verbose >= 2)
+ printbuf(session->v2_data.sik, session->v2_data.sik_len, "Generated session integrity key");
+
+ return 0;
+}
+
+
+
+/*
+ * lanplus_generate_k1
+ *
+ * Generate K1, the key presumably used to generate integrity authcodes
+ *
+ * We use the authentication algorithm to generated the HMAC, using
+ * the session integrity key (SIK) as our key.
+ *
+ * param session [in/out].
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+int lanplus_generate_k1(struct ipmi_session * session)
+{
+ uint32_t mac_length;
+ int unsupported = 0;
+ uint8_t CONST_1[36] = /*EVP_MAX_MD_SIZE = 36*/
+ {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+
+ if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
+ memcpy(session->v2_data.k1, CONST_1, 20);
+ else
+ {
+ lanplus_HMAC(session->v2_data.auth_alg,
+ session->v2_data.sik,
+ session->v2_data.sik_len,/* SIK length */
+ CONST_1,
+ IPMI_AUTHCODE_BUFFER_SIZE, /*=20*/
+ session->v2_data.k1,
+ &mac_length);
+ switch(session->v2_data.auth_alg)
+ {
+ case IPMI_AUTH_RAKP_HMAC_SHA1 :
+ if (mac_length != SHA_DIGEST_LENGTH) unsupported = 1; break;
+ case IPMI_AUTH_RAKP_HMAC_MD5 :
+ if (mac_length != MD5_DIGEST_LENGTH) unsupported = 1; break;
+ case IPMI_AUTH_RAKP_HMAC_SHA256:
+ if (mac_length != SHA256_DIGEST_LENGTH) unsupported = 1; break;
+ default : unsupported = 1; break;
+ }
+ if (unsupported) { /*was assert*/
+ printf("Unsupported k1 macLength %d for auth %d\n",
+ mac_length, session->v2_data.auth_alg);
+ return 1;
+ }
+ session->v2_data.k1_len = (uint8_t)mac_length;
+ }
+
+ if (verbose >= 2)
+ printbuf(session->v2_data.k1, session->v2_data.k1_len, "Generated K1");
+
+ return 0;
+}
+
+
+
+/*
+ * lanplus_generate_k2
+ *
+ * Generate K2, the key used for RMCP+ AES encryption.
+ *
+ * We use the authentication algorithm to generated the HMAC, using
+ * the session integrity key (SIK) as our key.
+ *
+ * param session [in/out].
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+int lanplus_generate_k2(struct ipmi_session * session)
+{
+ uint32_t mac_length;
+ int unsupported = 0;
+ uint8_t CONST_2[36] = /*EVP_MAX_MD_SIZE = 36*/
+ {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+
+ if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
+ memcpy(session->v2_data.k2, CONST_2, 20);
+ else
+ {
+ lanplus_HMAC(session->v2_data.auth_alg,
+ session->v2_data.sik,
+ session->v2_data.sik_len,/* SIK length */
+ CONST_2,
+ IPMI_AUTHCODE_BUFFER_SIZE, /*=20*/
+ session->v2_data.k2,
+ &mac_length);
+ switch(session->v2_data.auth_alg)
+ {
+ case IPMI_AUTH_RAKP_HMAC_SHA1 :
+ if (mac_length != SHA_DIGEST_LENGTH) unsupported = 1; break;
+ case IPMI_AUTH_RAKP_HMAC_MD5 :
+ if (mac_length != MD5_DIGEST_LENGTH) unsupported = 1; break;
+ case IPMI_AUTH_RAKP_HMAC_SHA256:
+ if (mac_length != SHA256_DIGEST_LENGTH) unsupported = 1; break;
+ default : unsupported = 1; break;
+ }
+ if (unsupported) { /*was assert*/
+ printf("Unsupported k2 macLength %d for auth %d\n",
+ mac_length, session->v2_data.auth_alg);
+ return 1;
+ }
+ session->v2_data.k2_len = (uint8_t)mac_length;
+ }
+
+ if (verbose >= 2)
+ printbuf(session->v2_data.k2, session->v2_data.k2_len, "Generated K2");
+
+ return 0;
+}
+
+
+
+/*
+ * lanplus_encrypt_payload
+ *
+ * Perform the appropriate encryption on the input data. Output the encrypted
+ * data to output, including the required confidentiality header and trailer.
+ * If the crypt_alg is IPMI_CRYPT_NONE, simply copy the input to the output and
+ * set bytes_written to input_length.
+ *
+ * param crypt_alg specifies the encryption algorithm (from table 13-19 of the
+ * IPMI v2 spec)
+ * param key is the used as input to the encryption algorithmf
+ * param input is the input data to be encrypted
+ * param input_length is the length of the input data to be encrypted
+ * param output is the cipher text generated by the encryption process
+ * param bytes_written is the number of bytes written during the encryption
+ * process
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+int lanplus_encrypt_payload(uint8_t crypt_alg,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint16_t * bytes_written)
+{
+ uint8_t * padded_input;
+ uint32_t mod, i, bytes_encrypted;
+ uint8_t pad_length = 0;
+
+ if (crypt_alg == IPMI_CRYPT_NONE)
+ {
+ /* Just copy the input to the output */
+ *bytes_written = (uint16_t)input_length;
+ return 0;
+ }
+
+ /* Currently, we only support AES (was assert) */
+ if ((crypt_alg != IPMI_CRYPT_AES_CBC_128) ||
+ (input_length > IPMI_MAX_PAYLOAD_SIZE)) {
+ lprintf(LOG_ERR,"lanplus crypt: unsupported alg %d or len %d\n",
+ crypt_alg,input_length);
+ return 1;
+ }
+
+ /*
+ * The input to the AES encryption algorithm has to be a multiple of the
+ * block size (16 bytes). The extra byte we are adding is the pad length
+ * byte.
+ */
+ mod = (input_length + 1) % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE;
+ if (mod)
+ pad_length = IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE - mod;
+
+ padded_input = (uint8_t*)malloc(input_length + pad_length + 1);
+ if (padded_input == NULL) {
+ lprintf(LOG_ERR, "lanplus: malloc failure");
+ return 1;
+ }
+ memcpy(padded_input, input, input_length);
+
+ /* add the pad */
+ for (i = 0; i < pad_length; ++i)
+ padded_input[input_length + i] = i + 1;
+
+ /* add the pad length */
+ padded_input[input_length + pad_length] = pad_length;
+
+ /* Generate an initialization vector, IV, for the encryption process */
+ if (lanplus_rand(output, IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE))
+ {
+ lprintf(LOG_ERR, "lanplus_encrypt_payload: Error generating IV");
+ free(padded_input);
+ return 1;
+ }
+
+ if (verbose > 2)
+ printbuf(output, IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, ">> Initialization vector");
+
+
+
+ lanplus_encrypt_aes_cbc_128(output, /* IV */
+ key, /* K2 */
+ padded_input, /* Data to encrypt */
+ input_length + pad_length + 1, /* Input length */
+ output + IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE, /* output */
+ &bytes_encrypted); /* bytes written */
+
+ *bytes_written =
+ IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE + /* IV */
+ bytes_encrypted;
+
+ free(padded_input);
+
+ return 0;
+}
+
+
+
+/*
+ * lanplus_has_valid_auth_code
+ *
+ * Determine whether the packets authcode field is valid for packet.
+ *
+ * We always return success if any of the following are true.
+ * - this is not an IPMIv2 packet
+ * - the session is not yet active
+ * - the packet specifies that it is not authenticated
+ * - the integrity algorithm agreed upon during session creation is "none"
+ *
+ * The authcode is computed using the specified integrity algorithm starting
+ * with the AuthType / Format field, and ending with the field immediately
+ * preceeding the authcode itself.
+ *
+ * The key key used to generate the authcode MAC is K1.
+ *
+ * param rs holds the response structure.
+ * param session holds our session state, including our chosen algorithm, key, etc.
+ *
+ * returns 1 on success (authcode is valid)
+ * 0 on failure (autchode integrity check failed)
+ */
+int lanplus_has_valid_auth_code(struct ipmi_rs * rs,
+ struct ipmi_session * session)
+{
+ uint8_t * bmc_authcode;
+ uint8_t generated_authcode[EVP_MAX_MD_SIZE];
+ uint32_t generated_authcode_length;
+ uint32_t authcode_length;
+
+
+ if ((rs->session.authtype != IPMI_SESSION_AUTHTYPE_RMCP_PLUS) ||
+ (session->v2_data.session_state != LANPLUS_STATE_ACTIVE) ||
+ (! rs->session.bAuthenticated) ||
+ (session->v2_data.integrity_alg == IPMI_INTEGRITY_NONE))
+ return 1;
+
+ switch(session->v2_data.integrity_alg)
+ {
+ case IPMI_INTEGRITY_HMAC_SHA1_96 : authcode_length = IPMI_SHA1_AUTHCODE_SIZE; break;
+ case IPMI_INTEGRITY_HMAC_MD5_128 : authcode_length = IPMI_HMAC_MD5_AUTHCODE_SIZE; break;
+ case IPMI_INTEGRITY_HMAC_SHA256_128: authcode_length = IPMI_HMAC_SHA256_AUTHCODE_SIZE; break;
+ /* Unsupported */
+ default: printf("Unsupported lanplus auth_code %d\n",
+ session->v2_data.auth_alg);
+ return 1; break;
+ }
+
+ /*
+ * For SHA1-96, the authcode will be the last 12 bytes in the packet
+ */
+ bmc_authcode = rs->data + (rs->data_len - authcode_length);
+
+ lanplus_HMAC(session->v2_data.integrity_alg,
+ session->v2_data.k1,
+ session->v2_data.k1_len,
+ rs->data + IPMI_LANPLUS_OFFSET_AUTHTYPE,
+ rs->data_len - IPMI_LANPLUS_OFFSET_AUTHTYPE - authcode_length,
+ generated_authcode,
+ &generated_authcode_length);
+
+ if (verbose > 3)
+ {
+ lprintf(LOG_DEBUG+2, "Validating authcode");
+ printbuf(session->v2_data.k1, session->v2_data.k1_len, "K1");
+ printbuf(rs->data + IPMI_LANPLUS_OFFSET_AUTHTYPE,
+ rs->data_len - IPMI_LANPLUS_OFFSET_AUTHTYPE - authcode_length,
+ "Authcode Input Data");
+ printbuf(generated_authcode, authcode_length, "Generated authcode");
+ printbuf(bmc_authcode, authcode_length, "Expected authcode");
+ }
+
+// assert(generated_authcode_length == 20);
+ return (memcmp(bmc_authcode, generated_authcode, authcode_length) == 0);
+}
+
+
+
+/*
+ * lanplus_decrypt_payload
+ *
+ *
+ * param input points to the beginning of the payload (which will be the IV if
+ * we are using AES)
+ * param payload_size [out] will be set to the size of the payload EXCLUDING
+ * padding
+ *
+ * returns 0 on success (we were able to successfully decrypt the packet)
+ * 1 on failure (we were unable to successfully decrypt the packet)
+ */
+int lanplus_decrypt_payload(uint8_t crypt_alg,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint16_t * payload_size)
+{
+ uint8_t * decrypted_payload;
+ uint32_t bytes_decrypted;
+
+ if (crypt_alg == IPMI_CRYPT_NONE)
+ {
+ /* We are not encrypted. The paylaod size is is everything. */
+ *payload_size = (uint16_t)input_length;
+ memmove(output, input, input_length);
+ return 0;
+ }
+
+ /* We only support AES (was assert) */
+ if (crypt_alg != IPMI_CRYPT_AES_CBC_128) {
+ lprintf(LOG_ERR,"lanplus decrypt: unsupported alg %d\n",
+ crypt_alg);
+ return 1;
+ }
+
+ decrypted_payload = (uint8_t*)malloc(input_length);
+ if (decrypted_payload == NULL) {
+ lprintf(LOG_ERR, "lanplus: malloc failure");
+ return 1;
+ }
+
+ lanplus_decrypt_aes_cbc_128(input, /* IV */
+ key, /* Key */
+ input + /* Data to decrypt */
+ IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE,
+ input_length - /* Input length */
+ IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE,
+ decrypted_payload, /* output */
+ &bytes_decrypted); /* bytes written */
+
+ if (bytes_decrypted != 0)
+ {
+ /* Success */
+ uint8_t conf_pad_length;
+ int i;
+
+ memmove(output,
+ decrypted_payload,
+ bytes_decrypted);
+
+ /*
+ * We have to determine the payload size, by substracting the padding, etc.
+ * The last byte of the decrypted payload is the confidentiality pad length.
+ */
+ conf_pad_length = decrypted_payload[bytes_decrypted - 1];
+ *payload_size = bytes_decrypted - conf_pad_length - 1;
+
+ /*
+ * Extra test to make sure that the padding looks like it should (should start
+ * with 0x01, 0x02, 0x03, etc...
+ */
+ for (i = 0; i < conf_pad_length; ++i)
+ {
+ if (decrypted_payload[*payload_size + i] == i)
+ {
+ lprintf(LOG_ERR, "Malformed payload padding");
+ return 1; /* assert(0); */
+ }
+ }
+ }
+ else
+ {
+ lprintf(LOG_ERR, "ERROR: lanplus_decrypt_aes_cbc_128 decryptd 0 bytes");
+ return 1; /* assert(0); */
+ }
+
+ free(decrypted_payload);
+ return (bytes_decrypted == 0);
+}
diff --git a/lib/lanplus/lanplus_crypt.h b/lib/lanplus/lanplus_crypt.h
new file mode 100644
index 0000000..2756bdd
--- /dev/null
+++ b/lib/lanplus/lanplus_crypt.h
@@ -0,0 +1,79 @@
+/*
+ * 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_LANPLUS_CRYPT_H
+#define IPMI_LANPLUS_CRYPT_H
+
+#include <ipmitool/ipmi_intf.h>
+
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+#include <openssl/md5.h>
+
+/*
+ * See the implementation file for documentation
+ * ipmi_intf can be used for oem specific implementations
+ * e.g. if (ipmi_oem_active(intf, "OEM_XYZ"))
+ */
+
+int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
+ const uint8_t * hmac,
+ struct ipmi_intf * intf);
+int lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
+ const uint8_t * hmac,
+ struct ipmi_intf * intf);
+int lanplus_generate_rakp3_authcode(uint8_t * buffer,
+ const struct ipmi_session * session,
+ uint32_t * auth_length,
+ struct ipmi_intf * intf);
+int lanplus_generate_sik(struct ipmi_session * session);
+int lanplus_generate_k1(struct ipmi_session * session);
+int lanplus_generate_k2(struct ipmi_session * session);
+int lanplus_encrypt_payload(uint8_t crypt_alg,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint16_t * bytesWritten);
+int lanplus_decrypt_payload(uint8_t crypt_alg,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint16_t * payload_size);
+int lanplus_has_valid_auth_code(struct ipmi_rs * rs,
+ struct ipmi_session * session);
+
+
+
+
+#endif /* IPMI_LANPLUS_CRYPT_H */
diff --git a/lib/lanplus/lanplus_crypt_impl.c b/lib/lanplus/lanplus_crypt_impl.c
new file mode 100644
index 0000000..3f9679e
--- /dev/null
+++ b/lib/lanplus/lanplus_crypt_impl.c
@@ -0,0 +1,320 @@
+/*
+ * 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.
+ */
+/* ARCress, TODO: improve error handling and remove all assert() calls here. */
+
+#include "ipmitool/log.h"
+#include "ipmitool/ipmi_constants.h"
+#include "lanplus.h"
+#include "lanplus_crypt_impl.h"
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <assert.h>
+
+
+
+/*
+ * lanplus_seed_prng
+ *
+ * Seed our PRNG with the specified number of bytes from /dev/random
+ *
+ * param bytes specifies the number of bytes to read from /dev/random
+ *
+ * returns 0 on success
+ * 1 on failure
+ */
+int lanplus_seed_prng(uint32_t bytes)
+{
+#ifdef WIN32
+ const char *randfile;
+ char buffer[200];
+ static FILE *fp = NULL;
+ size_t i;
+ randfile = RAND_file_name(buffer, sizeof buffer); /* usu C:\.rnd */
+ if ((randfile != NULL) && (fp == NULL)) {
+ /*first time, so open/create file*/
+ fp = fopen(randfile,"w"); /*create the randfile*/
+ if (fp != NULL) {
+ i = fwrite(" \n",2,1,fp);
+ fclose(fp);
+ }
+ }
+ if (verbose > 0)
+ printf("seed_prng: RAND_file_name = %s, fp=%p\n",randfile,fp);
+#else
+ const char *randfile = "/dev/urandom";
+#endif
+
+ if (RAND_load_file(randfile, bytes) == 0) {
+ printf("seed_prng: RAND_load_file(%s) failed\n",randfile);
+ return 1;
+ } else { /*success*/
+ return 0;
+ }
+}
+
+/*
+ * lanplus_rand
+ *
+ * Generate a random number of the specified size
+ *
+ * param num_bytes [in] is the size of the random number to be
+ * generated
+ * param buffer [out] is where we will place our random number
+ *
+ * return 0 on success
+ * 1 on failure
+ */
+int
+lanplus_rand(uint8_t * buffer, uint32_t num_bytes)
+{
+#undef IPMI_LANPLUS_FAKE_RAND
+#ifdef IPMI_LANPLUS_FAKE_RAND
+ /*
+ * This code exists so that we can easily find the generated random
+ * number in the hex dumps.
+ */
+ int i;
+ for (i = 0; i < num_bytes; ++i)
+ buffer[i] = 0x70 | i;
+ return 0;
+#else
+ return (! RAND_bytes(buffer, num_bytes));
+#endif
+}
+
+/*
+ * lanplus_HMAC
+ *
+ * param mac specifies the algorithm to be used, currently only SHA1 is supported
+ * param key is the key used for HMAC generation
+ * param key_len is the lenght of key
+ * param d is the data to be MAC'd
+ * param n is the length of the data at d
+ * param md is the result of the HMAC algorithm
+ * param md_len is the length of md
+ *
+ * returns a pointer to md
+ */
+uint8_t *
+lanplus_HMAC(uint8_t mac,
+ const void *key,
+ int key_len,
+ const uint8_t *d,
+ int n,
+ uint8_t *md,
+ uint32_t *md_len)
+{
+ const EVP_MD *evp_md = NULL;
+ unsigned int mlen;
+ uint8_t *pnew;
+
+ *md_len = 0; /*if return NULL, also return zero length*/
+ if ((mac == IPMI_AUTH_RAKP_HMAC_SHA1) ||
+ (mac == IPMI_INTEGRITY_HMAC_SHA1_96))
+ evp_md = EVP_sha1();
+ else if ((mac == IPMI_AUTH_RAKP_HMAC_MD5) ||
+ (mac == IPMI_INTEGRITY_HMAC_MD5_128))
+ evp_md = EVP_md5();
+ else if ((mac == IPMI_AUTH_RAKP_HMAC_SHA256) ||
+ (mac == IPMI_INTEGRITY_HMAC_SHA256_128)) {
+#ifdef HAVE_SHA256
+ evp_md = EVP_sha256();
+#else
+ lprintf(LOG_ERR, "Invalid EVP_sha256 in lanplus_HMAC");
+ return NULL; // assert(0);
+#endif
+ } else {
+ lprintf(LOG_ERR,"Invalid mac type 0x%x in lanplus_HMAC",mac);
+ return NULL; // assert(0);
+ }
+ mlen = 20; /* *md_len is usually not initialized */
+ pnew = HMAC(evp_md, key, key_len, d, n, md, &mlen);
+ *md_len = (uint32_t)mlen;
+ return(pnew);
+}
+
+
+/*
+ * lanplus_encrypt_aes_cbc_128
+ *
+ * Encrypt with the AES CBC 128 algorithm
+ *
+ * param iv is the 16 byte initialization vector
+ * param key is the 16 byte key used by the AES algorithm
+ * param input is the data to be encrypted
+ * param input_length is the number of bytes to be encrypted. This MUST
+ * be a multiple of the block size, 16.
+ * param output is the encrypted output
+ * param bytes_written is the number of bytes written. This param is set
+ * to 0 on failure, or if 0 bytes were input.
+ */
+void
+lanplus_encrypt_aes_cbc_128(const uint8_t * iv,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint32_t * bytes_written)
+{
+ int nwritten = 0;
+ int inlen = 0;
+ EVP_CIPHER_CTX ctx;
+ EVP_CIPHER_CTX_init(&ctx);
+ EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+ *bytes_written = 0;
+ if (input_length == 0) return;
+
+ if (verbose >= 5)
+ {
+ printbuf(iv, 16, "encrypting with this IV");
+ printbuf(key, 16, "encrypting with this key");
+ printbuf(input, input_length, "encrypting this data");
+ }
+
+ /*
+ * The default implementation adds a whole block of padding if the input
+ * data is perfectly aligned. We would like to keep that from happening.
+ * We have made a point to have our input perfectly padded.
+ */
+ assert((input_length % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE) == 0);
+ inlen = input_length;
+
+ if(!EVP_EncryptUpdate(&ctx, output, &nwritten, input, inlen))
+ {
+ /* Error */
+ *bytes_written = 0;
+ return;
+ }
+ else
+ {
+ int tmplen;
+
+ if(!EVP_EncryptFinal_ex(&ctx, output + nwritten, &tmplen))
+ {
+ *bytes_written = 0;
+ return; /* Error */
+ }
+ else
+ {
+ /* Success */
+ *bytes_written = nwritten + tmplen;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ }
+ }
+}
+
+
+/*
+ * lanplus_decrypt_aes_cbc_128
+ *
+ * Decrypt with the AES CBC 128 algorithm
+ *
+ * param iv is the 16 byte initialization vector
+ * param key is the 16 byte key used by the AES algorithm
+ * param input is the data to be decrypted
+ * param input_length is the number of bytes to be decrypted. This MUST
+ * be a multiple of the block size, 16.
+ * param output is the decrypted output
+ * param bytes_written is the number of bytes written. This param is set
+ * to 0 on failure, or if 0 bytes were input.
+ */
+void
+lanplus_decrypt_aes_cbc_128(const uint8_t * iv,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint32_t * bytes_written)
+{
+ int nwritten = 0;
+ int inlen = 0;
+ EVP_CIPHER_CTX ctx;
+ EVP_CIPHER_CTX_init(&ctx);
+ EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv);
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+ if (verbose >= 5)
+ {
+ printbuf(iv, 16, "decrypting with this IV");
+ printbuf(key, 16, "decrypting with this key");
+ printbuf(input, input_length, "decrypting this data");
+ }
+
+ *bytes_written = 0;
+ if (input_length == 0) return;
+
+ /*
+ * The default implementation adds a whole block of padding if the input
+ * data is perfectly aligned. We would like to keep that from happening.
+ * We have made a point to have our input perfectly padded.
+ */
+ assert((input_length % IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE) == 0);
+ inlen = input_length;
+
+ if (!EVP_DecryptUpdate(&ctx, output, &nwritten, input, inlen))
+ {
+ /* Error */
+ lprintf(LOG_DEBUG, "ERROR: decrypt update failed");
+ *bytes_written = 0;
+ return;
+ }
+ else
+ {
+ int tmplen;
+
+ if (!EVP_DecryptFinal_ex(&ctx, output + nwritten, &tmplen))
+ {
+ char buffer[1000];
+ ERR_error_string(ERR_get_error(), buffer);
+ lprintf(LOG_DEBUG, "the ERR error %s", buffer);
+ lprintf(LOG_DEBUG, "ERROR: decrypt final failed");
+ *bytes_written = 0;
+ return; /* Error */
+ }
+ else
+ {
+ /* Success */
+ *bytes_written = nwritten + tmplen;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ }
+ }
+
+ if (verbose >= 5)
+ {
+ lprintf(LOG_DEBUG, "Decrypted %d encrypted bytes",input_length);
+ printbuf(output, *bytes_written, "Decrypted this data");
+ }
+}
diff --git a/lib/lanplus/lanplus_crypt_impl.h b/lib/lanplus/lanplus_crypt_impl.h
new file mode 100644
index 0000000..ff534bc
--- /dev/null
+++ b/lib/lanplus/lanplus_crypt_impl.h
@@ -0,0 +1,66 @@
+/*
+ * 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_LANPLUS_CRYPT_IMPL_H
+#define IPMI_LANPLUS_CRYPT_IMPL_H
+
+
+int
+lanplus_seed_prng(uint32_t bytes);
+
+int
+lanplus_rand(uint8_t * buffer, uint32_t num_bytes);
+
+uint8_t *
+lanplus_HMAC(uint8_t mac, const void *key, int key_len,
+ const uint8_t *d, int n, uint8_t *md,
+ uint32_t *md_len);
+
+void
+lanplus_encrypt_aes_cbc_128(const uint8_t * iv,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint32_t * bytes_written);
+
+
+void
+lanplus_decrypt_aes_cbc_128(const uint8_t * iv,
+ const uint8_t * key,
+ const uint8_t * input,
+ uint32_t input_length,
+ uint8_t * output,
+ uint32_t * bytes_written);
+
+
+#endif /* IPMI_LANPLUS_CRYPT_IMPL_H */
diff --git a/lib/lanplus/lanplus_defs.h b/lib/lanplus/lanplus_defs.h
new file mode 100644
index 0000000..dbce90d
--- /dev/null
+++ b/lib/lanplus/lanplus_defs.h
@@ -0,0 +1,376 @@
+/*
+ * lanplus_defs.h: (extracted from 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 LANPLUS_DEFS_H
+#define LANPLUS_DEFS_H
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#else
+#ifndef socklen_t
+typedef unsigned int socklen_t;
+#endif
+#endif
+
+
+#if defined(MACOS)
+#include <stdint.h>
+#endif
+
+#include <openssl/evp.h>
+
+#ifdef WIN32
+#define SockType SOCKET
+#define SockInvalid INVALID_SOCKET /*=0*/
+#else
+#define SockType int
+#define SockInvalid -1
+#endif
+
+#ifndef IPMI_H
+
+#ifndef _IPMI_RQ_
+#define _IPMI_RQ_
+struct ipmi_rq {
+ struct {
+ uint8_t netfn:6;
+ uint8_t lun:2;
+ uint8_t cmd;
+ uint8_t target_cmd;
+ uint16_t data_len;
+ uint8_t *data;
+ } msg;
+};
+#endif
+
+#ifndef _IPMI_RS_
+#define _IPMI_RS_
+struct ipmi_rs {
+ uint8_t ccode;
+ uint8_t data[IPMI_BUF_SIZE];
+
+ /*
+ * Looks like this is the length of the entire packet, including the RMCP
+ * stuff, then modified to be the length of the extra IPMI message data
+ */
+ int data_len;
+
+ struct {
+ uint8_t netfn;
+ uint8_t cmd;
+ uint8_t seq;
+ uint8_t lun;
+ } msg;
+
+ struct {
+ uint8_t authtype;
+ uint32_t seq;
+ uint32_t id;
+ uint8_t bEncrypted; /* IPMI v2 only */
+ uint8_t bAuthenticated; /* IPMI v2 only */
+ uint8_t payloadtype; /* IPMI v2 only */
+ /* This is the total length of the payload or
+ IPMI message. IPMI v2.0 requires this to
+ be 2 bytes. Not really used for much. */
+ uint16_t msglen;
+ } session;
+
+ /*
+ * A union of the different possible payload meta-data
+ */
+ union {
+ struct {
+ uint8_t rq_addr;
+ uint8_t netfn;
+ uint8_t rq_lun;
+ uint8_t rs_addr;
+ uint8_t rq_seq;
+ uint8_t rs_lun;
+ uint8_t cmd;
+ } ipmi_response;
+ struct {
+ uint8_t message_tag;
+ uint8_t rakp_return_code;
+ uint8_t max_priv_level;
+ uint32_t console_id;
+ uint32_t bmc_id;
+ uint8_t auth_alg;
+ uint8_t integrity_alg;
+ uint8_t crypt_alg;
+ } open_session_response;
+ struct {
+ uint8_t message_tag;
+ uint8_t rakp_return_code;
+ uint32_t console_id;
+ uint8_t bmc_rand[16]; /* Random number generated by the BMC */
+ uint8_t bmc_guid[16];
+ uint8_t key_exchange_auth_code[EVP_MAX_MD_SIZE];
+ } rakp2_message;
+ struct {
+ uint8_t message_tag;
+ uint8_t rakp_return_code;
+ uint32_t console_id;
+ uint8_t integrity_check_value[EVP_MAX_MD_SIZE];
+ } rakp4_message;
+ struct {
+ uint8_t packet_sequence_number;
+ uint8_t acked_packet_number;
+ uint8_t accepted_character_count;
+ uint8_t is_nack; /* bool */
+ uint8_t transfer_unavailable; /* bool */
+ uint8_t sol_inactive; /* bool */
+ uint8_t transmit_overrun; /* bool */
+ uint8_t break_detected; /* bool */
+ } sol_packet;
+
+ } payload;
+};
+#endif
+
+struct ipmi_v2_payload {
+ uint16_t payload_length;
+ uint8_t payload_type;
+
+ union {
+
+ struct {
+ uint8_t rq_seq;
+ struct ipmi_rq *request;
+ } ipmi_request;
+
+ struct {
+ uint8_t rs_seq;
+ struct ipmi_rs *response;
+ } ipmi_response;
+
+ /* Only used internally by the lanplus interface */
+ struct {
+ uint8_t *request;
+ } open_session_request;
+
+ /* Only used internally by the lanplus interface */
+ struct {
+ uint8_t *message;
+ } rakp_1_message;
+
+ /* Only used internally by the lanplus interface */
+ struct {
+ uint8_t *message;
+ } rakp_2_message;
+
+ /* Only used internally by the lanplus interface */
+ struct {
+ uint8_t *message;
+ } rakp_3_message;
+
+ /* Only used internally by the lanplus interface */
+ struct {
+ uint8_t *message;
+ } rakp_4_message;
+
+ struct {
+ uint8_t data[IPMI_BUF_SIZE];
+ uint16_t character_count;
+ uint8_t packet_sequence_number;
+ uint8_t acked_packet_number;
+ uint8_t accepted_character_count;
+ uint8_t is_nack; /* bool */
+ uint8_t assert_ring_wor; /* bool */
+ uint8_t generate_break; /* bool */
+ uint8_t deassert_cts; /* bool */
+ uint8_t deassert_dcd_dsr; /* bool */
+ uint8_t flush_inbound; /* bool */
+ uint8_t flush_outbound; /* bool */
+ } sol_packet;
+
+ } payload;
+};
+#endif
+/**************************************/
+
+/* define ipmi_intf locally */
+/*
+ * An enumeration that describes every possible session state for
+ * an IPMIv2 / RMCP+ session.
+ */
+enum LANPLUS_SESSION_STATE {
+ LANPLUS_STATE_PRESESSION = 0,
+ LANPLUS_STATE_OPEN_SESSION_SENT,
+ LANPLUS_STATE_OPEN_SESSION_RECEIEVED,
+ LANPLUS_STATE_RAKP_1_SENT,
+ LANPLUS_STATE_RAKP_2_RECEIVED,
+ LANPLUS_STATE_RAKP_3_SENT,
+ LANPLUS_STATE_ACTIVE,
+ LANPLUS_STATE_CLOSE_SENT,
+};
+
+
+#define IPMI_AUTHCODE_BUFFER_SIZE 20 // KG or KUID
+#define IPMI_SIK_BUFFER_SIZE EVP_MAX_MD_SIZE
+#define IPMI_KG_BUFFER_SIZE 21 /* key plus null byte */
+
+struct ipmi_session {
+ uint8_t hostname[64];
+ uint8_t username[17];
+ uint8_t authcode[IPMI_AUTHCODE_BUFFER_SIZE + 1];
+ uint8_t challenge[16];
+ uint8_t authtype;
+ uint8_t authtype_set;
+#define IPMI_AUTHSTATUS_PER_MSG_DISABLED 0x10
+#define IPMI_AUTHSTATUS_PER_USER_DISABLED 0x08
+#define IPMI_AUTHSTATUS_NONNULL_USERS_ENABLED 0x04
+#define IPMI_AUTHSTATUS_NULL_USERS_ENABLED 0x02
+#define IPMI_AUTHSTATUS_ANONYMOUS_USERS_ENABLED 0x01
+ uint8_t authstatus;
+ uint8_t authextra;
+ uint8_t privlvl;
+ uint8_t cipher_suite_id;
+ char sol_escape_char;
+ int password;
+ int port;
+ int active;
+ int retry;
+
+ uint32_t session_id;
+ uint32_t in_seq;
+ uint32_t out_seq;
+ uint32_t timeout;
+
+#ifdef HAVE_IPV6
+ /* struct sockaddr_storage addr; *causes rest of structure to break */
+ struct sockaddr_in addr;
+#else
+ struct sockaddr_in addr;
+#endif
+ socklen_t addrlen;
+
+ /*
+ * This struct holds state data specific to IMPI v2 / RMCP+ sessions
+ */
+ struct {
+ enum LANPLUS_SESSION_STATE session_state;
+
+ /* These are the algorithms agreed upon for the session */
+ uint8_t requested_auth_alg;
+ uint8_t requested_integrity_alg;
+ uint8_t requested_crypt_alg;
+ uint8_t auth_alg;
+ uint8_t integrity_alg;
+ uint8_t crypt_alg;
+ uint8_t max_priv_level;
+
+ uint32_t console_id;
+ uint32_t bmc_id;
+
+ /*
+ * Values required for RAKP mesages
+ */
+
+ /* Random number generated byt the console */
+ uint8_t console_rand[16];
+ /* Random number generated by the BMC */
+ uint8_t bmc_rand[16];
+
+ uint8_t bmc_guid[16];
+ uint8_t requested_role; /* As sent in the RAKP 1 message */
+ uint8_t rakp2_return_code;
+
+ uint8_t sik[EVP_MAX_MD_SIZE]; /* Session integrity key */
+ uint8_t kg[IPMI_KG_BUFFER_SIZE]; /* BMC key */
+ uint8_t k1[EVP_MAX_MD_SIZE]; /* Used for Integrity checking? */
+ uint8_t k2[EVP_MAX_MD_SIZE]; /* First 16 bytes used for AES */
+ uint8_t sik_len; /* length of sik */
+ uint8_t k1_len; /* length of k1 */
+ uint8_t k2_len; /* length of k2 */
+ } v2_data;
+
+
+ /*
+ * This data is specific to the Serial Over Lan session
+ */
+ struct {
+ uint16_t max_inbound_payload_size;
+ uint16_t max_outbound_payload_size;
+ uint16_t port;
+ uint8_t sequence_number;
+
+ /* This data describes the last SOL packet */
+ uint8_t last_received_sequence_number;
+ uint8_t last_received_byte_count;
+ void (*sol_input_handler)(struct ipmi_rs * rsp);
+ } sol_data;
+};
+
+struct ipmi_intf_support {
+ const char * name;
+ int supported;
+};
+
+struct ipmi_intf {
+ char name[16];
+ char desc[128];
+ SockType fd;
+ int opened;
+ int abort;
+ int noanswer;
+
+ struct ipmi_session * session;
+ struct ipmi_oem_handle * oem;
+ struct ipmi_cmd * cmdlist;
+ uint32_t my_addr;
+ uint32_t target_addr;
+ uint8_t target_lun;
+ uint8_t target_channel;
+ uint32_t transit_addr;
+ uint8_t transit_channel;
+ uint8_t devnum;
+
+ int (*setup)(struct ipmi_intf * intf);
+ int (*open)(struct ipmi_intf * intf);
+ void (*close)(struct ipmi_intf * intf);
+ struct ipmi_rs *(*sendrecv)(struct ipmi_intf * intf, struct ipmi_rq * req);
+ int (*sendrsp)(struct ipmi_intf * intf, struct ipmi_rs * rsp);
+ struct ipmi_rs *(*recv_sol)(struct ipmi_intf * intf);
+ struct ipmi_rs *(*send_sol)(struct ipmi_intf * intf, void *payload);
+ /*struct ipmi_v2_payload * payload);*/
+ int (*keepalive)(struct ipmi_intf * intf);
+};
+
+struct ipmi_cmd {
+ int (*func)(struct ipmi_intf * intf, int argc, char ** argv);
+ const char * name;
+ const char * desc;
+};
+
+#endif /* lanplus_defs.h */
diff --git a/lib/lanplus/lanplus_dump.c b/lib/lanplus/lanplus_dump.c
new file mode 100644
index 0000000..5c86b69
--- /dev/null
+++ b/lib/lanplus/lanplus_dump.c
@@ -0,0 +1,174 @@
+/*
+ * 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 "lanplus.h"
+#include "lanplus_crypt.h"
+#include "lanplus_dump.h"
+
+extern const struct valstr ipmi_rakp_return_codes[];
+extern const struct valstr ipmi_priv_levels[];
+extern const struct valstr ipmi_auth_algorithms[];
+extern const struct valstr ipmi_integrity_algorithms[];
+extern const struct valstr ipmi_encryption_algorithms[];
+
+#define DUMP_PREFIX_INCOMING "<<"
+
+void lanplus_dump_open_session_response(const struct ipmi_rs * rsp)
+{
+ if (verbose < 2)
+ return;
+
+ printf("%sOPEN SESSION RESPONSE\n", DUMP_PREFIX_INCOMING);
+
+ printf("%s Message tag : 0x%02x\n",
+ DUMP_PREFIX_INCOMING,
+ rsp->payload.open_session_response.message_tag);
+ printf("%s RMCP+ status : %s\n",
+ DUMP_PREFIX_INCOMING,
+ val2str(rsp->payload.open_session_response.rakp_return_code,
+ ipmi_rakp_return_codes));
+ printf("%s Maximum privilege level : %s\n",
+ DUMP_PREFIX_INCOMING,
+ val2str(rsp->payload.open_session_response.max_priv_level,
+ ipmi_priv_levels));
+ printf("%s Console Session ID : 0x%08lx\n",
+ DUMP_PREFIX_INCOMING,
+ (long)rsp->payload.open_session_response.console_id);
+
+ /* only tag, status, privlvl, and console id are returned if error */
+ if (rsp->payload.open_session_response.rakp_return_code !=
+ IPMI_RAKP_STATUS_NO_ERRORS)
+ return;
+
+ printf("%s BMC Session ID : 0x%08lx\n",
+ DUMP_PREFIX_INCOMING,
+ (long)rsp->payload.open_session_response.bmc_id);
+ printf("%s Negotiated authenticatin algorithm : %s\n",
+ DUMP_PREFIX_INCOMING,
+ val2str(rsp->payload.open_session_response.auth_alg,
+ ipmi_auth_algorithms));
+ printf("%s Negotiated integrity algorithm : %s\n",
+ DUMP_PREFIX_INCOMING,
+ val2str(rsp->payload.open_session_response.integrity_alg,
+ ipmi_integrity_algorithms));
+ printf("%s Negotiated encryption algorithm : %s\n",
+ DUMP_PREFIX_INCOMING,
+ val2str(rsp->payload.open_session_response.crypt_alg,
+ ipmi_encryption_algorithms));
+ printf("\n");
+}
+
+
+
+void lanplus_dump_rakp2_message(const struct ipmi_rs * rsp, uint8_t auth_alg)
+{
+ int i;
+
+ if (verbose < 2)
+ return;
+
+ printf("%sRAKP 2 MESSAGE\n", DUMP_PREFIX_INCOMING);
+
+ printf("%s Message tag : 0x%02x\n",
+ DUMP_PREFIX_INCOMING,
+ rsp->payload.rakp2_message.message_tag);
+
+ printf("%s RMCP+ status : %s\n",
+ DUMP_PREFIX_INCOMING,
+ val2str(rsp->payload.rakp2_message.rakp_return_code,
+ ipmi_rakp_return_codes));
+
+ printf("%s Console Session ID : 0x%08lx\n",
+ DUMP_PREFIX_INCOMING,
+ (long)rsp->payload.rakp2_message.console_id);
+
+ printf("%s BMC GUID : 0x", DUMP_PREFIX_INCOMING);
+ for (i = 0; i < 16; ++i)
+ printf("%02x", rsp->payload.rakp2_message.bmc_guid[i]);
+ printf("\n");
+
+ switch(auth_alg)
+ {
+ case IPMI_AUTH_RAKP_NONE:
+ printf("%s Key exchange auth code : none\n", DUMP_PREFIX_INCOMING);
+ break;
+ case IPMI_AUTH_RAKP_HMAC_SHA1:
+ case IPMI_AUTH_RAKP_HMAC_MD5:
+ case IPMI_AUTH_RAKP_HMAC_SHA256:
+ printf("%s Key exchange auth code : ok\n", DUMP_PREFIX_INCOMING);
+ break;
+ default:
+ printf("%s Key exchange auth code : invalid", DUMP_PREFIX_INCOMING);
+ }
+ printf("\n");
+}
+
+
+
+void lanplus_dump_rakp4_message(const struct ipmi_rs * rsp, uint8_t auth_alg)
+{
+ //int i;
+
+ if (verbose < 2)
+ return;
+
+ printf("%sRAKP 4 MESSAGE\n", DUMP_PREFIX_INCOMING);
+
+ printf("%s Message tag : 0x%02x\n",
+ DUMP_PREFIX_INCOMING,
+ rsp->payload.rakp4_message.message_tag);
+
+ printf("%s RMCP+ status : %s\n",
+ DUMP_PREFIX_INCOMING,
+ val2str(rsp->payload.rakp4_message.rakp_return_code,
+ ipmi_rakp_return_codes));
+
+ printf("%s Console Session ID : 0x%08lx\n",
+ DUMP_PREFIX_INCOMING,
+ (long)rsp->payload.rakp4_message.console_id);
+
+ switch(auth_alg)
+ {
+ case IPMI_AUTH_RAKP_NONE:
+ printf("%s Key exchange auth code : none\n", DUMP_PREFIX_INCOMING);
+ break;
+ case IPMI_AUTH_RAKP_HMAC_SHA1:
+ case IPMI_AUTH_RAKP_HMAC_MD5:
+ case IPMI_AUTH_RAKP_HMAC_SHA256:
+ printf("%s Key exchange auth code : ok\n", DUMP_PREFIX_INCOMING);
+ break;
+ default:
+ printf("%s Key exchange auth code : invalid", DUMP_PREFIX_INCOMING);
+ }
+ printf("\n");
+}
+
diff --git a/lib/lanplus/lanplus_dump.h b/lib/lanplus/lanplus_dump.h
new file mode 100644
index 0000000..4e29ebb
--- /dev/null
+++ b/lib/lanplus/lanplus_dump.h
@@ -0,0 +1,45 @@
+/*
+ * 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_LANPLUS_DUMP_H
+#define IPMI_LANPLUS_DUMP_H
+
+#include <ipmitool/ipmi_intf.h>
+
+/* See the implementation file for documentation */
+void lanplus_dump_open_session_response(const struct ipmi_rs * rsp);
+void lanplus_dump_rakp2_message(const struct ipmi_rs * rsp, uint8_t auth_alg);
+void lanplus_dump_rakp4_message(const struct ipmi_rs * rsp, uint8_t auth_alg);
+
+
+#endif /* IPMI_LANPLUS_DUMP_H */
diff --git a/lib/lanplus/lanplus_strings.c b/lib/lanplus/lanplus_strings.c
new file mode 100644
index 0000000..f65054f
--- /dev/null
+++ b/lib/lanplus/lanplus_strings.c
@@ -0,0 +1,45 @@
+/*
+ * lanplus_strings.c
+ * extracts all lanplus string messages to one location for potential
+ * customization or translation.
+ *
+ * 01/09/2007 ARCress - created
+ */
+#include "lanplus.h"
+#include "ipmitool/ipmi_constants.h"
+
+const struct valstr ipmi_rakp_return_codes[] = {
+
+ { IPMI_RAKP_STATUS_NO_ERRORS, "no errors" },
+ { IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_SESSION, "insufficient resources for session" },
+ { IPMI_RAKP_STATUS_INVALID_SESSION_ID, "invalid session ID" },
+ { IPMI_RAKP_STATUS_INVALID_PAYLOAD_TYPE, "invalid payload type" },
+ { IPMI_RAKP_STATUS_INVALID_AUTHENTICATION_ALGORITHM, "invalid authentication algorithm" },
+ { IPMI_RAKP_STATUS_INVALID_INTEGRITTY_ALGORITHM, "invalid integrity algorithm" },
+ { IPMI_RAKP_STATUS_NO_MATCHING_AUTHENTICATION_PAYLOAD, "no matching authentication algorithm"},
+ { IPMI_RAKP_STATUS_NO_MATCHING_INTEGRITY_PAYLOAD, "no matching integrity payload" },
+ { IPMI_RAKP_STATUS_INACTIVE_SESSION_ID, "inactive session ID" },
+ { IPMI_RAKP_STATUS_INVALID_ROLE, "invalid role" },
+ { IPMI_RAKP_STATUS_UNAUTHORIZED_ROLE_REQUESTED, "unauthorized role requested" },
+ { IPMI_RAKP_STATUS_INSUFFICIENT_RESOURCES_FOR_ROLE, "insufficient resources for role" },
+ { IPMI_RAKP_STATUS_INVALID_NAME_LENGTH, "invalid name length" },
+ { IPMI_RAKP_STATUS_UNAUTHORIZED_NAME, "unauthorized name" },
+ { IPMI_RAKP_STATUS_UNAUTHORIZED_GUID, "unauthorized GUID" },
+ { IPMI_RAKP_STATUS_INVALID_INTEGRITY_CHECK_VALUE, "invalid integrity check value" },
+ { IPMI_RAKP_STATUS_INVALID_CONFIDENTIALITY_ALGORITHM, "invalid confidentiality algorithm" },
+ { IPMI_RAKP_STATUS_NO_CIPHER_SUITE_MATCH, "no matching cipher suite" },
+ { IPMI_RAKP_STATUS_ILLEGAL_PARAMTER, "illegal parameter" },
+ { 0, 0 },
+};
+
+const struct valstr ipmi_priv_levels[] = {
+ { IPMI_PRIV_CALLBACK, "callback" },
+ { IPMI_PRIV_USER, "user" },
+ { IPMI_PRIV_OPERATOR, "operator" },
+ { IPMI_PRIV_ADMIN, "admin" },
+ { IPMI_PRIV_OEM, "oem" },
+ { 0, 0 },
+};
+
+
+
diff --git a/lib/lanplus/libipmi_lanplus.la b/lib/lanplus/libipmi_lanplus.la
new file mode 100644
index 0000000..870fff8
--- /dev/null
+++ b/lib/lanplus/libipmi_lanplus.la
@@ -0,0 +1,35 @@
+# libipmi_lanplus.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.5.6 (1.1220.2.95 2004/04/11 05:50:42)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='libipmi_lanplus.so.0'
+
+# Names of this library.
+library_names='libipmi_lanplus.so.0.0.0 libipmi_lanplus.so.0 libipmi_lanplus.so'
+
+# The name of the static archive.
+old_library='libipmi_lanplus.a'
+
+# Libraries that this one depends upon.
+dependency_libs=' -lcrypto'
+
+# Version information for libipmi_lanplus.
+current=0
+age=0
+revision=0
+
+# Is this an already installed library?
+installed=no
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=no
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir='/usr/lib'
diff --git a/lib/lanplus/rmcp.h b/lib/lanplus/rmcp.h
new file mode 100644
index 0000000..99b877d
--- /dev/null
+++ b/lib/lanplus/rmcp.h
@@ -0,0 +1,88 @@
+/*
+ * 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_RMCP_H
+#define IPMI_RMCP_H
+
+#include <ipmitool/helper.h>
+#include "lanplus.h"
+
+#define RMCP_VERSION_1 0x06
+
+#define RMCP_UDP_PORT 0x26f /* port 623 */
+#define RMCP_UDP_SECURE_PORT 0x298 /* port 664 */
+
+#define RMCP_TYPE_MASK 0x80
+#define RMCP_TYPE_NORM 0x00
+#define RMCP_TYPE_ACK 0x01
+
+static const struct valstr rmcp_type_vals[] __attribute__((unused)) = {
+ { RMCP_TYPE_NORM, "Normal RMCP" },
+ { RMCP_TYPE_ACK, "RMCP ACK" },
+ { 0, NULL }
+};
+
+#define RMCP_CLASS_MASK 0x1f
+#define RMCP_CLASS_ASF 0x06
+#define RMCP_CLASS_IPMI 0x07
+#define RMCP_CLASS_OEM 0x08
+
+static const struct valstr rmcp_class_vals[] __attribute__((unused)) = {
+ { RMCP_CLASS_ASF, "ASF" },
+ { RMCP_CLASS_IPMI, "IPMI" },
+ { RMCP_CLASS_OEM, "OEM" },
+ { 0, NULL }
+};
+
+/* RMCP message header */
+#ifdef GCC_42
+struct rmcp_hdr {
+ uint8_t ver;
+ uint8_t __rsvd;
+ uint8_t seq;
+ uint8_t class;
+} __attribute__((packed));
+#else
+/* pragma pack works in gcc-4.3 */
+#pragma pack(1)
+struct rmcp_hdr {
+ uint8_t ver;
+ uint8_t __rsvd;
+ uint8_t seq;
+ uint8_t class;
+};
+#pragma pack()
+#endif
+
+int handle_rmcp(struct ipmi_intf * intf, uint8_t * data, int data_len);
+
+#endif /* IPMI_RMCP_H */
diff --git a/lib/libimbapi64.a.redhat b/lib/libimbapi64.a.redhat
new file mode 100644
index 0000000..bd08db1
--- /dev/null
+++ b/lib/libimbapi64.a.redhat
Binary files differ
diff --git a/lib/libimbapi64.a.suse b/lib/libimbapi64.a.suse
new file mode 100644
index 0000000..227ad75
--- /dev/null
+++ b/lib/libimbapi64.a.suse
Binary files differ
diff --git a/ltconfig b/ltconfig
new file mode 100755
index 0000000..c14d83c
--- /dev/null
+++ b/ltconfig
@@ -0,0 +1,3114 @@
+#! /bin/sh
+
+# ltconfig - Create a system-specific libtool.
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This file 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
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A lot of this script is taken from autoconf-2.10.
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+echo=echo
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell.
+ exec "$SHELL" "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit 0
+fi
+
+# Find the correct PATH separator. Usually this is `:', but
+# DJGPP uses `;' like DOS.
+if test "X${PATH_SEPARATOR+set}" != Xset; then
+ UNAME=${UNAME-`uname 2>/dev/null`}
+ case X$UNAME in
+ *-DOS) PATH_SEPARATOR=';' ;;
+ *) PATH_SEPARATOR=':' ;;
+ esac
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+if test "X${echo_test_string+set}" != Xset; then
+ # find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if (echo_test_string="`eval $cmd`") 2>/dev/null &&
+ echo_test_string="`eval $cmd`" &&
+ (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then
+ break
+ fi
+ done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" != 'X\t' ||
+ test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ for dir in $PATH /usr/ucb; do
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+
+ if test "X$echo" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+ test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ echo='print -r'
+ elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running ltconfig again with it.
+ ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}"
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"}
+ else
+ # Try using printf.
+ echo='printf "%s\n"'
+ if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
+ test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+ CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL"
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
+ test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+ if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "$0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ echo=echo
+ fi
+ fi
+ fi
+ fi
+fi
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e s/^X//'
+sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# The name of this program.
+progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'`
+
+# Constants:
+PROGRAM=ltconfig
+PACKAGE=libtool
+VERSION=1.3.5
+TIMESTAMP=" (1.385.2.206 2000/05/27 11:12:27)"
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+rm="rm -f"
+
+help="Try \`$progname --help' for more information."
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+enable_shared=yes
+# All known linkers require a `.a' archive for static linking (except M$VC,
+# which needs '.lib').
+enable_static=yes
+enable_fast_install=yes
+enable_dlopen=unknown
+enable_win32_dll=no
+ltmain=
+silent=
+srcdir=
+ac_config_guess=
+ac_config_sub=
+host=
+nonopt=
+ofile="$default_ofile"
+verify_host=yes
+with_gcc=no
+with_gnu_ld=no
+need_locks=yes
+ac_ext=c
+objext=o
+libext=a
+exeext=
+cache_file=
+
+old_AR="$AR"
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+old_CPPFLAGS="$CPPFLAGS"
+old_LDFLAGS="$LDFLAGS"
+old_LD="$LD"
+old_LN_S="$LN_S"
+old_LIBS="$LIBS"
+old_NM="$NM"
+old_RANLIB="$RANLIB"
+old_DLLTOOL="$DLLTOOL"
+old_OBJDUMP="$OBJDUMP"
+old_AS="$AS"
+
+# Parse the command line options.
+args=
+prev=
+for option
+do
+ case "$option" in
+ -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ eval "$prev=\$option"
+ prev=
+ continue
+ fi
+
+ case "$option" in
+ --help) cat <<EOM
+Usage: $progname [OPTION]... [HOST [LTMAIN]]
+
+Generate a system-specific libtool script.
+
+ --debug enable verbose shell tracing
+ --disable-shared do not build shared libraries
+ --disable-static do not build static libraries
+ --disable-fast-install do not optimize for fast installation
+ --enable-dlopen enable dlopen support
+ --enable-win32-dll enable building dlls on win32 hosts
+ --help display this help and exit
+ --no-verify do not verify that HOST is a valid host type
+-o, --output=FILE specify the output file [default=$default_ofile]
+ --quiet same as \`--silent'
+ --silent do not print informational messages
+ --srcdir=DIR find \`config.guess' in DIR
+ --version output version information and exit
+ --with-gcc assume that the GNU C compiler will be used
+ --with-gnu-ld assume that the C compiler uses the GNU linker
+ --disable-lock disable file locking
+ --cache-file=FILE configure cache file
+
+LTMAIN is the \`ltmain.sh' shell script fragment or \`ltmain.c' program
+that provides basic libtool functionality.
+
+HOST is the canonical host system name [default=guessed].
+EOM
+ exit 0
+ ;;
+
+ --debug)
+ echo "$progname: enabling shell trace mode"
+ set -x
+ ;;
+
+ --disable-shared) enable_shared=no ;;
+
+ --disable-static) enable_static=no ;;
+
+ --disable-fast-install) enable_fast_install=no ;;
+
+ --enable-dlopen) enable_dlopen=yes ;;
+
+ --enable-win32-dll) enable_win32_dll=yes ;;
+
+ --quiet | --silent) silent=yes ;;
+
+ --srcdir) prev=srcdir ;;
+ --srcdir=*) srcdir="$optarg" ;;
+
+ --no-verify) verify_host=no ;;
+
+ --output | -o) prev=ofile ;;
+ --output=*) ofile="$optarg" ;;
+
+ --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"; exit 0 ;;
+
+ --with-gcc) with_gcc=yes ;;
+ --with-gnu-ld) with_gnu_ld=yes ;;
+
+ --disable-lock) need_locks=no ;;
+
+ --cache-file=*) cache_file="$optarg" ;;
+
+ -*)
+ echo "$progname: unrecognized option \`$option'" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *)
+ if test -z "$ltmain"; then
+ ltmain="$option"
+ elif test -z "$host"; then
+# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1
+# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then
+# echo "$progname: warning \`$option' is not a valid host type" 1>&2
+# fi
+ host="$option"
+ else
+ echo "$progname: too many arguments" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi ;;
+ esac
+done
+
+if test -z "$ltmain"; then
+ echo "$progname: you must specify a LTMAIN file" 1>&2
+ echo "$help" 1>&2
+ exit 1
+fi
+
+if test ! -f "$ltmain"; then
+ echo "$progname: \`$ltmain' does not exist" 1>&2
+ echo "$help" 1>&2
+ exit 1
+fi
+
+# Quote any args containing shell metacharacters.
+ltconfig_args=
+for arg
+do
+ case "$arg" in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ltconfig_args="$ltconfig_args '$arg'" ;;
+ *) ltconfig_args="$ltconfig_args $arg" ;;
+ esac
+done
+
+# A relevant subset of AC_INIT.
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 5 compiler messages saved in config.log
+# 6 checking for... messages and results
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>>./config.log
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "X${LC_ALL+set}" = Xset; then LC_ALL=C; export LC_ALL; fi
+if test "X${LANG+set}" = Xset; then LANG=C; export LANG; fi
+
+if test -n "$cache_file" && test -r "$cache_file"; then
+ echo "loading cache $cache_file within ltconfig"
+ . $cache_file
+fi
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+if test -z "$srcdir"; then
+ # Assume the source directory is the same one as the path to LTMAIN.
+ srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'`
+ test "$srcdir" = "$ltmain" && srcdir=.
+fi
+
+trap "$rm conftest*; exit 1" 1 2 15
+if test "$verify_host" = yes; then
+ # Check for config.guess and config.sub.
+ ac_aux_dir=
+ for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/config.guess; then
+ ac_aux_dir=$ac_dir
+ break
+ fi
+ done
+ if test -z "$ac_aux_dir"; then
+ echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi
+ ac_config_guess=$ac_aux_dir/config.guess
+ ac_config_sub=$ac_aux_dir/config.sub
+
+ # Make sure we can run config.sub.
+ if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then :
+ else
+ echo "$progname: cannot run $ac_config_sub" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi
+
+ echo $ac_n "checking host system type""... $ac_c" 1>&6
+
+ host_alias=$host
+ case "$host_alias" in
+ "")
+ if host_alias=`$SHELL $ac_config_guess`; then :
+ else
+ echo "$progname: cannot guess host type; you must specify one" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi ;;
+ esac
+ host=`$SHELL $ac_config_sub $host_alias`
+ echo "$ac_t$host" 1>&6
+
+ # Make sure the host verified.
+ test -z "$host" && exit 1
+
+elif test -z "$host"; then
+ echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2
+ echo "$help" 1>&2
+ exit 1
+else
+ host_alias=$host
+fi
+
+# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+case "$host_os" in
+linux-gnu*) ;;
+linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+esac
+
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+case "$host_os" in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR cru $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+# Set a sane default for `AR'.
+test -z "$AR" && AR=ar
+
+# Set a sane default for `OBJDUMP'.
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+# If RANLIB is not set, then run the test.
+if test "${RANLIB+set}" != "set"; then
+ result=no
+
+ echo $ac_n "checking for ranlib... $ac_c" 1>&6
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then
+ RANLIB="ranlib"
+ result="ranlib"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+
+ echo "$ac_t$result" 1>&6
+fi
+
+if test -n "$RANLIB"; then
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+ old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+fi
+
+# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin.
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$AS" && AS=as
+
+# Check to see if we are using GCC.
+if test "$with_gcc" != yes || test -z "$CC"; then
+ # If CC is not set, then try to find GCC or a usable CC.
+ if test -z "$CC"; then
+ echo $ac_n "checking for gcc... $ac_c" 1>&6
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then
+ CC="gcc"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+
+ if test -n "$CC"; then
+ echo "$ac_t$CC" 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+ fi
+
+ # Not "gcc", so try "cc", rejecting "/usr/ucb/cc".
+ if test -z "$CC"; then
+ echo $ac_n "checking for cc... $ac_c" 1>&6
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ cc_rejected=no
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/cc || test -f $dir/cc$ac_exeext; then
+ if test "$dir/cc" = "/usr/ucb/cc"; then
+ cc_rejected=yes
+ continue
+ fi
+ CC="cc"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+ if test $cc_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same name, so the bogon will be chosen
+ # first if we set CC to just the name; use the full file name.
+ shift
+ set dummy "$dir/cc" "$@"
+ shift
+ CC="$@"
+ fi
+ fi
+
+ if test -n "$CC"; then
+ echo "$ac_t$CC" 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+
+ if test -z "$CC"; then
+ echo "$progname: error: no acceptable cc found in \$PATH" 1>&2
+ exit 1
+ fi
+ fi
+
+ # Now see if the compiler is really GCC.
+ with_gcc=no
+ echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6
+ echo "$progname:581: checking whether we are using GNU C" >&5
+
+ $rm conftest.c
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+ if { ac_try='${CC-cc} -E conftest.c'; { (eval echo $progname:589: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ with_gcc=yes
+ fi
+ $rm conftest.c
+ echo "$ac_t$with_gcc" 1>&6
+fi
+
+# Allow CC to be a program name with arguments.
+set dummy $CC
+compiler="$2"
+
+echo $ac_n "checking for object suffix... $ac_c" 1>&6
+$rm conftest*
+echo 'int i = 1;' > conftest.c
+echo "$progname:603: checking for object suffix" >& 5
+if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then
+ # Append any warnings to the config.log.
+ cat conftest.err 1>&5
+
+ for ac_file in conftest.*; do
+ case $ac_file in
+ *.c) ;;
+ *) objext=`echo $ac_file | sed -e s/conftest.//` ;;
+ esac
+ done
+else
+ cat conftest.err 1>&5
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+fi
+$rm conftest*
+echo "$ac_t$objext" 1>&6
+
+echo $ac_n "checking for executable suffix... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_exeext="no"
+ $rm conftest*
+ echo 'main () { return 0; }' > conftest.c
+ echo "$progname:629: checking for executable suffix" >& 5
+ if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then
+ # Append any warnings to the config.log.
+ cat conftest.err 1>&5
+
+ for ac_file in conftest.*; do
+ case $ac_file in
+ *.c | *.err | *.$objext ) ;;
+ *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;;
+ esac
+ done
+ else
+ cat conftest.err 1>&5
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+ fi
+ $rm conftest*
+fi
+if test "X$ac_cv_exeext" = Xno; then
+ exeext=""
+else
+ exeext="$ac_cv_exeext"
+fi
+echo "$ac_t$ac_cv_exeext" 1>&6
+
+echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6
+pic_flag=
+special_shlib_compile_flags=
+wl=
+link_static_flag=
+no_builtin_flag=
+
+if test "$with_gcc" = yes; then
+ wl='-Wl,'
+ link_static_flag='-static'
+
+ case "$host_os" in
+ beos* | irix5* | irix6* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ aix*)
+ # Below there is a dirty hack to force normal static linking with -ldl
+ # The problem is because libdl dynamically linked with both libc and
+ # libC (AIX C++ library), which obviously doesn't included in libraries
+ # list by gcc. This cause undefined symbols with -static flags.
+ # This hack allows C programs to be linked with "-static -ldl", but
+ # we not sure about C++ programs.
+ link_static_flag="$link_static_flag ${wl}-lC"
+ ;;
+ cygwin* | mingw* | os2*)
+ # We can build DLLs from non-PIC.
+ ;;
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ pic_flag='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ pic_flag=-Kconform_pic
+ fi
+ ;;
+ *)
+ pic_flag='-fPIC'
+ ;;
+ esac
+else
+ # PORTME Check for PIC flags for the system compiler.
+ case "$host_os" in
+ aix3* | aix4*)
+ # All AIX code is PIC.
+ link_static_flag='-bnso -bI:/lib/syscalls.exp'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ # Is there a better link_static_flag that works with the bundled CC?
+ wl='-Wl,'
+ link_static_flag="${wl}-a ${wl}archive"
+ pic_flag='+Z'
+ ;;
+
+ irix5* | irix6*)
+ wl='-Wl,'
+ link_static_flag='-non_shared'
+ # PIC (with -KPIC) is the default.
+ ;;
+
+ cygwin* | mingw* | os2*)
+ # We can build DLLs from non-PIC.
+ ;;
+
+ osf3* | osf4* | osf5*)
+ # All OSF/1 code is PIC.
+ wl='-Wl,'
+ link_static_flag='-non_shared'
+ ;;
+
+ sco3.2v5*)
+ pic_flag='-Kpic'
+ link_static_flag='-dn'
+ special_shlib_compile_flags='-belf'
+ ;;
+
+ solaris*)
+ pic_flag='-KPIC'
+ link_static_flag='-Bstatic'
+ wl='-Wl,'
+ ;;
+
+ sunos4*)
+ pic_flag='-PIC'
+ link_static_flag='-Bstatic'
+ wl='-Qoption ld '
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ pic_flag='-KPIC'
+ link_static_flag='-Bstatic'
+ wl='-Wl,'
+ ;;
+
+ uts4*)
+ pic_flag='-pic'
+ link_static_flag='-Bstatic'
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ pic_flag='-Kconform_pic'
+ link_static_flag='-Bstatic'
+ fi
+ ;;
+ *)
+ can_build_shared=no
+ ;;
+ esac
+fi
+
+if test -n "$pic_flag"; then
+ echo "$ac_t$pic_flag" 1>&6
+
+ # Check to make sure the pic_flag actually works.
+ echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6
+ $rm conftest*
+ echo "int some_variable = 0;" > conftest.c
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $pic_flag -DPIC"
+ echo "$progname:776: checking if $compiler PIC flag $pic_flag works" >&5
+ if { (eval echo $progname:777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then
+ # Append any warnings to the config.log.
+ cat conftest.err 1>&5
+
+ case "$host_os" in
+ hpux9* | hpux10* | hpux11*)
+ # On HP-UX, both CC and GCC only warn that PIC is supported... then they
+ # create non-PIC objects. So, if there were any warnings, we assume that
+ # PIC is not supported.
+ if test -s conftest.err; then
+ echo "$ac_t"no 1>&6
+ can_build_shared=no
+ pic_flag=
+ else
+ echo "$ac_t"yes 1>&6
+ pic_flag=" $pic_flag"
+ fi
+ ;;
+ *)
+ echo "$ac_t"yes 1>&6
+ pic_flag=" $pic_flag"
+ ;;
+ esac
+ else
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ can_build_shared=no
+ pic_flag=
+ echo "$ac_t"no 1>&6
+ fi
+ CFLAGS="$save_CFLAGS"
+ $rm conftest*
+else
+ echo "$ac_t"none 1>&6
+fi
+
+# Check to see if options -o and -c are simultaneously supported by compiler
+echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6
+$rm -r conftest 2>/dev/null
+mkdir conftest
+cd conftest
+$rm conftest*
+echo "int some_variable = 0;" > conftest.c
+mkdir out
+# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
+# that will create temporary files in the current directory regardless of
+# the output directory. Thus, making CWD read-only will cause this test
+# to fail, enabling locking or at least warning the user not to do parallel
+# builds.
+chmod -w .
+save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -o out/conftest2.o"
+echo "$progname:829: checking if $compiler supports -c -o file.o" >&5
+if { (eval echo $progname:830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then
+
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s out/conftest.err; then
+ echo "$ac_t"no 1>&6
+ compiler_c_o=no
+ else
+ echo "$ac_t"yes 1>&6
+ compiler_c_o=yes
+ fi
+else
+ # Append any errors to the config.log.
+ cat out/conftest.err 1>&5
+ compiler_c_o=no
+ echo "$ac_t"no 1>&6
+fi
+CFLAGS="$save_CFLAGS"
+chmod u+w .
+$rm conftest* out/*
+rmdir out
+cd ..
+rmdir conftest
+$rm -r conftest 2>/dev/null
+
+if test x"$compiler_c_o" = x"yes"; then
+ # Check to see if we can write to a .lo
+ echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6
+ $rm conftest*
+ echo "int some_variable = 0;" > conftest.c
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -c -o conftest.lo"
+ echo "$progname:862: checking if $compiler supports -c -o file.lo" >&5
+if { (eval echo $progname:863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then
+
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ echo "$ac_t"no 1>&6
+ compiler_o_lo=no
+ else
+ echo "$ac_t"yes 1>&6
+ compiler_o_lo=yes
+ fi
+ else
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ compiler_o_lo=no
+ echo "$ac_t"no 1>&6
+ fi
+ CFLAGS="$save_CFLAGS"
+ $rm conftest*
+else
+ compiler_o_lo=no
+fi
+
+# Check to see if we can do hard links to lock some files if needed
+hard_links="nottested"
+if test "$compiler_c_o" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ echo "$ac_t$hard_links" 1>&6
+ $rm conftest*
+ if test "$hard_links" = no; then
+ echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+if test "$with_gcc" = yes; then
+ # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
+ echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6
+ $rm conftest*
+ echo "int some_variable = 0;" > conftest.c
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c"
+ echo "$progname:914: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+ if { (eval echo $progname:915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then
+
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ echo "$ac_t"no 1>&6
+ compiler_rtti_exceptions=no
+ else
+ echo "$ac_t"yes 1>&6
+ compiler_rtti_exceptions=yes
+ fi
+ else
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ compiler_rtti_exceptions=no
+ echo "$ac_t"no 1>&6
+ fi
+ CFLAGS="$save_CFLAGS"
+ $rm conftest*
+
+ if test "$compiler_rtti_exceptions" = "yes"; then
+ no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
+ else
+ no_builtin_flag=' -fno-builtin'
+ fi
+
+fi
+
+# Check for any special shared library compilation flags.
+if test -n "$special_shlib_compile_flags"; then
+ echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2
+ if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then :
+ else
+ echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2
+ can_build_shared=no
+ fi
+fi
+
+echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6
+$rm conftest*
+echo 'main(){return(0);}' > conftest.c
+save_LDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS $link_static_flag"
+echo "$progname:958: checking if $compiler static flag $link_static_flag works" >&5
+if { (eval echo $progname:959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ echo "$ac_t$link_static_flag" 1>&6
+else
+ echo "$ac_t"none 1>&6
+ link_static_flag=
+fi
+LDFLAGS="$save_LDFLAGS"
+$rm conftest*
+
+if test -z "$LN_S"; then
+ # Check to see if we can use ln -s, or we need hard links.
+ echo $ac_n "checking whether ln -s works... $ac_c" 1>&6
+ $rm conftest.dat
+ if ln -s X conftest.dat 2>/dev/null; then
+ $rm conftest.dat
+ LN_S="ln -s"
+ else
+ LN_S=ln
+ fi
+ if test "$LN_S" = "ln -s"; then
+ echo "$ac_t"yes 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+fi
+
+# Make sure LD is an absolute path.
+if test -z "$LD"; then
+ ac_prog=ld
+ if test "$with_gcc" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6
+ echo "$progname:991: checking for ld used by GCC" >&5
+ ac_prog=`($CC -print-prog-name=ld) 2>&5`
+ case "$ac_prog" in
+ # Accept absolute paths.
+ [\\/]* | [A-Za-z]:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we are not using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+ elif test "$with_gnu_ld" = yes; then
+ echo $ac_n "checking for GNU ld... $ac_c" 1>&6
+ echo "$progname:1015: checking for GNU ld" >&5
+ else
+ echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+ echo "$progname:1018: checking for non-GNU ld" >&5
+ fi
+
+ if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ fi
+
+ if test -n "$LD"; then
+ echo "$ac_t$LD" 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+
+ if test -z "$LD"; then
+ echo "$progname: error: no acceptable ld found in \$PATH" 1>&2
+ exit 1
+ fi
+fi
+
+# Check to see if it really is or is not GNU ld.
+echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6
+# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+echo "$ac_t$with_gnu_ld" 1>&6
+
+# See if the linker supports building shared libraries.
+echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6
+
+allow_undefined_flag=
+no_undefined_flag=
+need_lib_prefix=unknown
+need_version=unknown
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+archive_cmds=
+archive_expsym_cmds=
+old_archive_from_new_cmds=
+export_dynamic_flag_spec=
+whole_archive_flag_spec=
+thread_safe_flag_spec=
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+hardcode_shlibpath_var=unsupported
+runpath_var=
+always_export_symbols=no
+export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
+# include_expsyms should be a list of space-separated symbols to be *always*
+# included in the symbol list
+include_expsyms=
+# exclude_expsyms can be an egrep regular expression of symbols to exclude
+# it will be wrapped by ` (' and `)$', so one must not match beginning or
+# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+# as well as any symbol that contains `d'.
+exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+# platforms (ab)use it in PIC code, but their linkers get confused if
+# the symbol is explicitly referenced. Since portable code cannot
+# rely on this symbol name, it's probably fine to never include it in
+# preloaded symbol tables.
+
+case "$host_os" in
+cygwin* | mingw*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$with_gcc" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # See if GNU ld supports shared libraries.
+ case "$host_os" in
+ aix3* | aix4*)
+ # On AIX, the GNU linker is very broken
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can use
+ # them.
+ ld_shlibs=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ cygwin* | mingw*)
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+
+ # Extract the symbol export list from an `--export-all' def file,
+ # then regenerate the def file from the symbol export list, so that
+ # the compiled dll only exports the symbol export list.
+ # Be careful not to strip the DATA tag left by newer dlltools.
+ export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
+ test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
+ $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def $objdir/$soname-ltdll.$objext $libobjs $convenience~
+ sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < $objdir/$soname-def > $export_symbols'
+
+ # If DATA tags from a recent dlltool are present, honour them!
+ archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~
+ _lt_hint=1;
+ cat $export_symbols | while read symbol; do
+ set dummy \$symbol;
+ case \$# in
+ 2) echo " \$2 @ \$_lt_hint ; " >> $objdir/$soname-def;;
+ *) echo " \$2 @ \$_lt_hint \$3 ; " >> $objdir/$soname-def;;
+ esac;
+ _lt_hint=`expr 1 + \$_lt_hint`;
+ done~
+ test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
+ test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
+ $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
+ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
+ $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
+ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
+ $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts'
+
+ old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a'
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib'
+ # can we support soname and/or expsyms with a.out? -oliva
+ fi
+ ;;
+
+ solaris* | sysv5*)
+ if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts'
+ wlarc=
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs" = yes; then
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec='${wl}--export-dynamic'
+ case $host_os in
+ cygwin* | mingw*)
+ # dlltool doesn't understand --whole-archive et. al.
+ whole_archive_flag_spec=
+ ;;
+ *)
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec=
+ fi
+ ;;
+ esac
+ fi
+else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case "$host_os" in
+ aix3*)
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$with_gcc" = yes && test -z "$link_static_flag"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix4*)
+ hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib'
+ hardcode_libdir_separator=':'
+ if test "$with_gcc" = yes; then
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct=yes
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ shared_flag='-shared'
+ else
+ shared_flag='${wl}-bM:SRE'
+ hardcode_direct=yes
+ fi
+ allow_undefined_flag=' ${wl}-berok'
+ archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}'
+ archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}'
+ case "$host_os" in aix4.[01]|aix4.[01].*)
+ # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on
+ always_export_symbols=yes ;;
+ esac
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs=no
+ ;;
+
+ cygwin* | mingw*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_from_new_cmds='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds='lib /OUT:$oldlib$oldobjs'
+ fix_srcfile_path='`cygpath -w $srcfile`'
+ ;;
+
+ freebsd1*)
+ ld_shlibs=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd*)
+ archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ case "$host_os" in
+ hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;;
+ *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;;
+ esac
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ hardcode_minus_L=yes # Not in the search PATH, but as the default
+ # location of the library.
+ export_dynamic_flag_spec='${wl}-E'
+ ;;
+
+ irix5* | irix6*)
+ if test "$with_gcc" = yes; then
+ archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+ else
+ archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' # a.out
+ else
+ archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts' # ELF
+ fi
+ hardcode_libdir_flag_spec='${wl}-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ openbsd*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def'
+ old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$with_gcc" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ osf4* | osf5*) # As osf3* with the addition of the -msym flag
+ if test "$with_gcc" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ rhapsody*)
+ archive_cmds='$CC -bundle -undefined suppress -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flags_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sco3.2v5*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ;;
+
+ solaris*)
+ no_undefined_flag=' -z text'
+ # $CC -shared without GNU ld will not create a library from C++
+ # object files and a static libstdc++, better avoid it by now
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ case "$host_os" in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+ whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $linkopts'
+ else
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ fi
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+
+ sysv4.3*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ hardcode_shlibpath_var=no
+ export_dynamic_flag_spec='-Bexport'
+ ;;
+
+ sysv5*)
+ no_undefined_flag=' -z text'
+ # $CC -shared without GNU ld will not create a library from C++
+ # object files and a static libstdc++, better avoid it by now
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
+ hardcode_libdir_flag_spec=
+ hardcode_shlibpath_var=no
+ runpath_var='LD_RUN_PATH'
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ dgux*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ fi
+ ;;
+
+ sysv4.2uw2*)
+ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linkopts'
+ hardcode_direct=yes
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=no
+ hardcode_runpath_var=yes
+ runpath_var=LD_RUN_PATH
+ ;;
+
+ unixware7*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+fi
+echo "$ac_t$ld_shlibs" 1>&6
+test "$ld_shlibs" = no && can_build_shared=no
+
+if test -z "$NM"; then
+ echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6
+ case "$NM" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path.
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+ NM="$ac_dir/nm -B"
+ break
+ elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+ NM="$ac_dir/nm -p"
+ break
+ else
+ NM=${NM="$ac_dir/nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$NM" && NM=nm
+ ;;
+ esac
+ echo "$ac_t$NM" 1>&6
+fi
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
+# Define system-specific variables.
+case "$host_os" in
+aix*)
+ symcode='[BCDT]'
+ ;;
+cygwin* | mingw*)
+ symcode='[ABCDGISTW]'
+ ;;
+hpux*) # Its linker distinguishes data from code symbols
+ global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'"
+ ;;
+irix*)
+ symcode='[BCDEGRST]'
+ ;;
+solaris*)
+ symcode='[BDT]'
+ ;;
+sysv4)
+ symcode='[DFNSTU]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+ symcode='[ABCDGISTW]'
+fi
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Write the raw and C identifiers.
+ global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode\)[ ][ ]*\($ac_symprfx\)$sympat$/$symxfrm/p'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+ $rm conftest*
+ cat > conftest.c <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+ echo "$progname:1653: checking if global_symbol_pipe works" >&5
+ if { (eval echo $progname:1654: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if { echo "$progname:1657: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then
+
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if egrep ' nm_test_var$' "$nlist" >/dev/null; then
+ if egrep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.c
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c'
+
+ cat <<EOF >> conftest.c
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+ sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c
+ cat <<\EOF >> conftest.c
+ {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.$objext conftstm.$objext
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$objext"
+ CFLAGS="$CFLAGS$no_builtin_flag"
+ if { (eval echo $progname:1709: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ pipe_works=yes
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+ fi
+ LIBS="$save_LIBS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&5
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&5
+ fi
+ else
+ echo "cannot run $global_symbol_pipe" >&5
+ fi
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+ fi
+ $rm conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ global_symbol_pipe=
+ fi
+done
+if test "$pipe_works" = yes; then
+ echo "${ac_t}ok" 1>&6
+else
+ echo "${ac_t}failed" 1>&6
+fi
+
+if test -z "$global_symbol_pipe"; then
+ global_symbol_to_cdecl=
+fi
+
+# Check hardcoding attributes.
+echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+ test -n "$runpath_var"; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$hardcode_shlibpath_var" != no &&
+ test "$hardcode_minus_L" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action=unsupported
+fi
+echo "$ac_t$hardcode_action" 1>&6
+
+
+reload_flag=
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6
+# PORTME Some linkers may need a different reload flag.
+reload_flag='-r'
+echo "$ac_t$reload_flag" 1>&6
+test -n "$reload_flag" && reload_flag=" $reload_flag"
+
+# PORTME Fill in your ld.so characteristics
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+file_magic_cmd=
+file_magic_test_file=
+deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [regex]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given egrep regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6
+case "$host_os" in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}.so$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}.so$major'
+ ;;
+
+aix4*)
+ version_type=linux
+ # AIX has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ # We preserve .a as extension for shared libraries though AIX4.2
+ # and later linker supports .so
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a'
+ shlibpath_var=LIBPATH
+ deplibs_check_method=pass_all
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}.so'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ deplibs_check_method=pass_all
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+bsdi4*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=/shlib/libc.so
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ export_dynamic_flag_spec=-rdynamic
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw*)
+ version_type=windows
+ need_version=no
+ need_lib_prefix=no
+ if test "$with_gcc" = yes; then
+ library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a'
+ else
+ library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib'
+ fi
+ dynamic_linker='Win32 ld.exe'
+ deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ file_magic_cmd='${OBJDUMP} -f'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+freebsd*)
+ objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+ version_type=freebsd-$objformat
+ case "$version_type" in
+ freebsd-elf*)
+ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object'
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=`echo /usr/lib/libc.so*`
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ deplibs_check_method=unknown
+ library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case "$host_os" in
+ freebsd2* | freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ *) # from 3.2 on
+ shlibpath_overrides_runpath=no
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ dynamic_linker="$host_os dld.sl"
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
+ soname_spec='${libname}${release}.sl$major'
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ case "$host_os" in
+ hpux10.20*)
+ # TODO: Does this work for hpux-11 too?
+ deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+irix5* | irix6*)
+ version_type=irix
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}.so.$major'
+ library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so'
+ case "$host_os" in
+ irix5*)
+ libsuff= shlibsuff=
+ # this will be overridden with pass_all, but let us keep it just in case
+ deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
+ ;;
+ *)
+ case "$LD" in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=`echo /lib${libsuff}/libc.so*`
+ deplibs_check_method='pass_all'
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ deplibs_check_method=pass_all
+
+ if test -f /lib/ld.so.1; then
+ dynamic_linker='GNU ld.so'
+ else
+ # Only the GNU ld.so supports shared libraries on MkLinux.
+ case "$host_cpu" in
+ powerpc*) dynamic_linker=no ;;
+ *) dynamic_linker='Linux ld.so' ;;
+ esac
+ fi
+ ;;
+
+netbsd*)
+ version_type=sunos
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
+ soname_spec='${libname}${release}.so$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+openbsd*)
+ version_type=sunos
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ need_version=no
+ fi
+ library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+os2*)
+ libname_spec='$name'
+ need_lib_prefix=no
+ library_names_spec='$libname.dll $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_version=no
+ soname_spec='${libname}${release}.so'
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ # this will be overridden with pass_all, but let us keep it just in case
+ deplibs_check_method='file_magic COFF format alpha shared library'
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=/shlib/libc.so
+ deplibs_check_method='pass_all'
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+rhapsody*)
+ version_type=sunos
+ library_names_spec='${libname}.so'
+ soname_spec='${libname}.so'
+ shlibpath_var=DYLD_LIBRARY_PATH
+ deplibs_check_method=pass_all
+ ;;
+
+sco3.2v5*)
+ version_type=osf
+ soname_spec='${libname}${release}.so$major'
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib"
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=/lib/libc.so
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ version_type=linux
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case "$host_vendor" in
+ sequent)
+ file_magic_cmd='/bin/file'
+ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+ ;;
+ ncr)
+ deplibs_check_method='pass_all'
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ esac
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+ soname_spec='$libname.so.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$ac_t$dynamic_linker" 1>&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+# Report the final consequences.
+echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6
+
+# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in
+# configure.in, otherwise build static only libraries.
+case "$host_os" in
+cygwin* | mingw* | os2*)
+ if test x$can_build_shared = xyes; then
+ test x$enable_win32_dll = xno && can_build_shared=no
+ echo "checking if package supports dlls... $can_build_shared" 1>&6
+ fi
+;;
+esac
+
+if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then
+ case "$deplibs_check_method" in
+ "file_magic "*)
+ file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ egrep "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+fi
+
+echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+aix4*)
+ test "$enable_shared" = yes && enable_static=no
+ ;;
+esac
+
+echo "$ac_t$enable_shared" 1>&6
+
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+
+echo "checking whether to build static libraries... $enable_static" 1>&6
+
+if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+echo $ac_n "checking for objdir... $ac_c" 1>&6
+rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+echo "$ac_t$objdir" 1>&6
+
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then
+ lt_cv_dlopen=no lt_cv_dlopen_libs=
+echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
+echo "$progname:2248: checking for dlopen in -ldl" >&5
+ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2256 "ltconfig"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen();
+
+int main() {
+dlopen()
+; return 0; }
+EOF
+if { (eval echo $progname:2269: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for dlopen""... $ac_c" 1>&6
+echo "$progname:2288: checking for dlopen" >&5
+if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2293 "ltconfig"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char dlopen(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_dlopen) || defined (__stub___dlopen)
+choke me
+#else
+dlopen();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo $progname:2318: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_dlopen=yes"
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_dlopen=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ lt_cv_dlopen="dlopen"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6
+echo "$progname:2335: checking for dld_link in -ldld" >&5
+ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldld $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2343 "ltconfig"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link();
+
+int main() {
+dld_link()
+; return 0; }
+EOF
+if { (eval echo $progname:2356: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for shl_load""... $ac_c" 1>&6
+echo "$progname:2375: checking for shl_load" >&5
+if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2380 "ltconfig"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shl_load(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_shl_load) || defined (__stub___shl_load)
+choke me
+#else
+shl_load();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo $progname:2405: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_shl_load=yes"
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_shl_load=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ lt_cv_dlopen="shl_load"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
+echo "$progname:2423: checking for shl_load in -ldld" >&5
+ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldld $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2431 "ltconfig"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load();
+
+int main() {
+shl_load()
+; return 0; }
+EOF
+if { (eval echo $progname:2445: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+fi
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ fi
+
+ case "$lt_cv_dlopen" in
+ dlopen)
+for ac_hdr in dlfcn.h; do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "$progname:2488: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2493 "ltconfig"
+#include <$ac_hdr>
+int fnord = 0;
+EOF
+ac_try="$ac_compile >/dev/null 2>conftest.out"
+{ (eval echo $progname:2498: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ if test "x$ac_cv_header_dlfcn_h" = xyes; then
+ CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+ fi
+ eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6
+echo "$progname:2526: checking whether a program can dlopen itself" >&5
+if test "${lt_cv_dlopen_self+set}" = set; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ lt_cv_dlopen_self=cross
+ else
+ cat > conftest.c <<EOF
+#line 2534 "ltconfig"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LTDL_GLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LTDL_GLOBAL DL_GLOBAL
+# else
+# define LTDL_GLOBAL 0
+# endif
+#endif
+
+/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LTDL_LAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LTDL_LAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LTDL_LAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LTDL_LAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LTDL_LAZY_OR_NOW DL_NOW
+# else
+# define LTDL_LAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+fnord() { int i=42;}
+main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
+ if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
+ if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); }
+
+EOF
+if { (eval echo $progname:2580: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ lt_cv_dlopen_self=yes
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ lt_cv_dlopen_self=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$lt_cv_dlopen_self" 1>&6
+
+ if test "$lt_cv_dlopen_self" = yes; then
+ LDFLAGS="$LDFLAGS $link_static_flag"
+ echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6
+echo "$progname:2599: checking whether a statically linked program can dlopen itself" >&5
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ lt_cv_dlopen_self_static=cross
+ else
+ cat > conftest.c <<EOF
+#line 2607 "ltconfig"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LTDL_GLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LTDL_GLOBAL DL_GLOBAL
+# else
+# define LTDL_GLOBAL 0
+# endif
+#endif
+
+/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LTDL_LAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LTDL_LAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LTDL_LAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LTDL_LAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LTDL_LAZY_OR_NOW DL_NOW
+# else
+# define LTDL_LAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+fnord() { int i=42;}
+main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
+ if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
+ if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); }
+
+EOF
+if { (eval echo $progname:2653: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ lt_cv_dlopen_self_static=yes
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ lt_cv_dlopen_self_static=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6
+fi
+ ;;
+ esac
+
+ case "$lt_cv_dlopen_self" in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case "$lt_cv_dlopen_self_static" in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+
+# Copy echo and quote the copy, instead of the original, because it is
+# used later.
+ltecho="$echo"
+if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+ ltecho="$CONFIG_SHELL \$0 --fallback-echo"
+fi
+LTSHELL="$SHELL"
+
+LTCONFIG_VERSION="$VERSION"
+
+# Only quote variables if we're using ltmain.sh.
+case "$ltmain" in
+*.sh)
+ # Now quote all the things that may contain metacharacters.
+ for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \
+ old_LD old_LDFLAGS old_LIBS \
+ old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \
+ AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \
+ reload_flag reload_cmds wl \
+ pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
+ thread_safe_flag_spec whole_archive_flag_spec libname_spec \
+ library_names_spec soname_spec \
+ RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
+ old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \
+ file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \
+ finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
+ hardcode_libdir_flag_spec hardcode_libdir_separator \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
+
+ case "$var" in
+ reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case "$ltecho" in
+ *'\$0 --fallback-echo"')
+ ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+ trap "$rm \"$ofile\"; exit 1" 1 2 15
+ echo "creating $ofile"
+ $rm "$ofile"
+ cat <<EOF > "$ofile"
+#! $SHELL
+
+# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh.
+#
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# 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
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="sed -e s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+### BEGIN LIBTOOL CONFIG
+EOF
+ cfgfile="$ofile"
+ ;;
+
+*)
+ # Double-quote the variables that need it (for aesthetics).
+ for var in old_CC old_CFLAGS old_CPPFLAGS \
+ old_LD old_LDFLAGS old_LIBS \
+ old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do
+ eval "$var=\\\"\$var\\\""
+ done
+
+ # Just create a config file.
+ cfgfile="$ofile.cfg"
+ trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+ echo "creating $cfgfile"
+ $rm "$cfgfile"
+ cat <<EOF > "$cfgfile"
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+EOF
+ ;;
+esac
+
+cat <<EOF >> "$cfgfile"
+# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\
+# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\
+# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\
+# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\
+# $0$ltconfig_args
+#
+# Compiler and other test output produced by $progname, useful for
+# debugging $progname, is in ./config.log if it exists.
+
+# The version of $progname that generated this script.
+LTCONFIG_VERSION=$LTCONFIG_VERSION
+
+# Shell to use when invoking shell scripts.
+SHELL=$LTSHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$ltecho
+
+# The archiver.
+AR=$AR
+
+# The default C compiler.
+CC=$CC
+
+# The linker used to build libraries.
+LD=$LD
+
+# Whether we need hard or soft links.
+LN_S=$LN_S
+
+# A BSD-compatible nm program.
+NM=$NM
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$reload_flag
+reload_cmds=$reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$wl
+
+# Object file suffix (normally "o").
+objext="$objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$pic_flag
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$compiler_c_o
+
+# Can we write directly to a .lo ?
+compiler_o_lo=$compiler_o_lo
+
+# Must we lock files when doing compilation ?
+need_locks=$need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$link_static_flag
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$RANLIB
+old_archive_cmds=$old_archive_cmds
+old_postinstall_cmds=$old_postinstall_cmds
+old_postuninstall_cmds=$old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$old_archive_from_new_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$archive_cmds
+archive_expsym_cmds=$archive_expsym_cmds
+postinstall_cmds=$postinstall_cmds
+postuninstall_cmds=$postuninstall_cmds
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$global_symbol_to_cdecl
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$include_expsyms
+
+EOF
+
+case "$ltmain" in
+*.sh)
+ echo '### END LIBTOOL CONFIG' >> "$ofile"
+ echo >> "$ofile"
+ case "$host_os" in
+ aix3*)
+ cat <<\EOF >> "$ofile"
+
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+EOF
+ ;;
+ esac
+
+ # Append the ltmain.sh script.
+ sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1)
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+
+ chmod +x "$ofile"
+ ;;
+
+*)
+ # Compile the libtool program.
+ echo "FIXME: would compile $ltmain"
+ ;;
+esac
+
+test -n "$cache_file" || exit 0
+
+# AC_CACHE_SAVE
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/ltmain.sh b/ltmain.sh
new file mode 100644
index 0000000..0223495
--- /dev/null
+++ b/ltmain.sh
@@ -0,0 +1,6911 @@
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun configure.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# 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
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+basename="s,^.*/,,g"
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+# The name of this program:
+progname=`echo "$progpath" | $SED $basename`
+modename="$progname"
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.5.22
+TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)"
+
+# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell, and then maybe $echo will work.
+ exec $SHELL "$progpath" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit $EXIT_SUCCESS
+fi
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ SP2NL='tr \040 \012'
+ NL2SP='tr \015\012 \040\040'
+ ;;
+ *) # EBCDIC based system
+ SP2NL='tr \100 \n'
+ NL2SP='tr \r\n \100\100'
+ ;;
+esac
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+ eval "if test \"\${$lt_var+set}\" = set; then
+ save_$lt_var=\$$lt_var
+ $lt_var=C
+ export $lt_var
+ fi"
+done
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS=" $lt_nl"
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ $echo "$modename: not configured to build any kind of library" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit $EXIT_FAILURE
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+duplicate_deps=no
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+#####################################
+# Shell function definitions:
+# This seems to be the best place for them
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible. If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+ my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+ if test "$run" = ":"; then
+ # Return a directory name, but don't create it in dry-run mode
+ my_tmpdir="${my_template}-$$"
+ else
+
+ # If mktemp works, use that first and foremost
+ my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+ if test ! -d "$my_tmpdir"; then
+ # Failing that, at least try and use $RANDOM to avoid a race
+ my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+ save_mktempdir_umask=`umask`
+ umask 0077
+ $mkdir "$my_tmpdir"
+ umask $save_mktempdir_umask
+ fi
+
+ # If we're not in dry-run mode, bomb out on failure
+ test -d "$my_tmpdir" || {
+ $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2
+ exit $EXIT_FAILURE
+ }
+ fi
+
+ $echo "X$my_tmpdir" | $Xsed
+}
+
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+func_win32_libid ()
+{
+ win32_libid_type="unknown"
+ win32_fileres=`file -L $1 2>/dev/null`
+ case $win32_fileres in
+ *ar\ archive\ import\ library*) # definitely import
+ win32_libid_type="x86 archive import"
+ ;;
+ *ar\ archive*) # could be an import, or static
+ if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
+ $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+ win32_nmres=`eval $NM -f posix -A $1 | \
+ $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'`
+ case $win32_nmres in
+ import*) win32_libid_type="x86 archive import";;
+ *) win32_libid_type="x86 archive static";;
+ esac
+ fi
+ ;;
+ *DLL*)
+ win32_libid_type="x86 DLL"
+ ;;
+ *executable*) # but shell scripts are "executable" too...
+ case $win32_fileres in
+ *MS\ Windows\ PE\ Intel*)
+ win32_libid_type="x86 DLL"
+ ;;
+ esac
+ ;;
+ esac
+ $echo $win32_libid_type
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+ if test -n "$available_tags" && test -z "$tagname"; then
+ CC_quoted=
+ for arg in $CC; do
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ CC_quoted="$CC_quoted $arg"
+ done
+ case $@ in
+ # Blanks in the command may have been stripped by the calling shell,
+ # but not from the CC environment variable when configure was run.
+ " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;;
+ # Blanks at the start of $base_compile will cause this to fail
+ # if we don't check for them as well.
+ *)
+ for z in $available_tags; do
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+ CC_quoted=
+ for arg in $CC; do
+ # Double-quote args containing other shell metacharacters.
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ CC_quoted="$CC_quoted $arg"
+ done
+ case "$@ " in
+ " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*)
+ # The compiler in the base compile command matches
+ # the one in the tagged configuration.
+ # Assume this is the tagged configuration we want.
+ tagname=$z
+ break
+ ;;
+ esac
+ fi
+ done
+ # If $tagname still isn't set, then no tagged configuration
+ # was found and let the user know that the "--tag" command
+ # line option must be used.
+ if test -z "$tagname"; then
+ $echo "$modename: unable to infer tagged configuration"
+ $echo "$modename: specify a tag with \`--tag'" 1>&2
+ exit $EXIT_FAILURE
+# else
+# $echo "$modename: using $tagname tagged configuration"
+ fi
+ ;;
+ esac
+ fi
+}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+ f_ex_an_ar_dir="$1"; shift
+ f_ex_an_ar_oldlib="$1"
+
+ $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
+ $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
+ if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
+ exit $EXIT_FAILURE
+ fi
+}
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+ my_gentop="$1"; shift
+ my_oldlibs=${1+"$@"}
+ my_oldobjs=""
+ my_xlib=""
+ my_xabs=""
+ my_xdir=""
+ my_status=""
+
+ $show "${rm}r $my_gentop"
+ $run ${rm}r "$my_gentop"
+ $show "$mkdir $my_gentop"
+ $run $mkdir "$my_gentop"
+ my_status=$?
+ if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
+ exit $my_status
+ fi
+
+ for my_xlib in $my_oldlibs; do
+ # Extract the objects.
+ case $my_xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+ *) my_xabs=`pwd`"/$my_xlib" ;;
+ esac
+ my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
+ my_xlib_u=$my_xlib
+ while :; do
+ case " $extracted_archives " in
+ *" $my_xlib_u "*)
+ extracted_serial=`expr $extracted_serial + 1`
+ my_xlib_u=lt$extracted_serial-$my_xlib ;;
+ *) break ;;
+ esac
+ done
+ extracted_archives="$extracted_archives $my_xlib_u"
+ my_xdir="$my_gentop/$my_xlib_u"
+
+ $show "${rm}r $my_xdir"
+ $run ${rm}r "$my_xdir"
+ $show "$mkdir $my_xdir"
+ $run $mkdir "$my_xdir"
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then
+ exit $exit_status
+ fi
+ case $host in
+ *-darwin*)
+ $show "Extracting $my_xabs"
+ # Do not bother doing anything if just a dry run
+ if test -z "$run"; then
+ darwin_orig_dir=`pwd`
+ cd $my_xdir || exit $?
+ darwin_archive=$my_xabs
+ darwin_curdir=`pwd`
+ darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'`
+ darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
+ if test -n "$darwin_arches"; then
+ darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
+ darwin_arch=
+ $show "$darwin_base_archive has multiple architectures $darwin_arches"
+ for darwin_arch in $darwin_arches ; do
+ mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+ cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+ cd "$darwin_curdir"
+ $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+ done # $darwin_arches
+ ## Okay now we have a bunch of thin objects, gotta fatten them up :)
+ darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP`
+ darwin_file=
+ darwin_files=
+ for darwin_file in $darwin_filelist; do
+ darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+ lipo -create -output "$darwin_file" $darwin_files
+ done # $darwin_filelist
+ ${rm}r unfat-$$
+ cd "$darwin_orig_dir"
+ else
+ cd "$darwin_orig_dir"
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ fi # $darwin_arches
+ fi # $run
+ ;;
+ *)
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ ;;
+ esac
+ my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+ done
+ func_extract_archives_result="$my_oldobjs"
+}
+# End of Shell function definitions
+#####################################
+
+# Darwin sucks
+eval std_shrext=\"$shrext_cmds\"
+
+disable_libs=no
+
+# Parse our command line options once, thoroughly.
+while test "$#" -gt 0
+do
+ arg="$1"
+ shift
+
+ case $arg in
+ -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ execute_dlfiles)
+ execute_dlfiles="$execute_dlfiles $arg"
+ ;;
+ tag)
+ tagname="$arg"
+ preserve_args="${preserve_args}=$arg"
+
+ # Check whether tagname contains only valid characters
+ case $tagname in
+ *[!-_A-Za-z0-9,/]*)
+ $echo "$progname: invalid tag name: $tagname" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $tagname in
+ CC)
+ # Don't test for the "default" C tag, as we know, it's there, but
+ # not specially marked.
+ ;;
+ *)
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then
+ taglist="$taglist $tagname"
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`"
+ else
+ $echo "$progname: ignoring unknown tag $tagname" 1>&2
+ fi
+ ;;
+ esac
+ ;;
+ *)
+ eval "$prev=\$arg"
+ ;;
+ esac
+
+ prev=
+ prevopt=
+ continue
+ fi
+
+ # Have we seen a non-optional argument yet?
+ case $arg in
+ --help)
+ show_help=yes
+ ;;
+
+ --version)
+ $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
+ $echo
+ $echo "Copyright (C) 2005 Free Software Foundation, Inc."
+ $echo "This is free software; see the source for copying conditions. There is NO"
+ $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+ exit $?
+ ;;
+
+ --config)
+ ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath
+ # Now print the configurations for the tags.
+ for tagname in $taglist; do
+ ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
+ done
+ exit $?
+ ;;
+
+ --debug)
+ $echo "$progname: enabling shell trace mode"
+ set -x
+ preserve_args="$preserve_args $arg"
+ ;;
+
+ --dry-run | -n)
+ run=:
+ ;;
+
+ --features)
+ $echo "host: $host"
+ if test "$build_libtool_libs" = yes; then
+ $echo "enable shared libraries"
+ else
+ $echo "disable shared libraries"
+ fi
+ if test "$build_old_libs" = yes; then
+ $echo "enable static libraries"
+ else
+ $echo "disable static libraries"
+ fi
+ exit $?
+ ;;
+
+ --finish) mode="finish" ;;
+
+ --mode) prevopt="--mode" prev=mode ;;
+ --mode=*) mode="$optarg" ;;
+
+ --preserve-dup-deps) duplicate_deps="yes" ;;
+
+ --quiet | --silent)
+ show=:
+ preserve_args="$preserve_args $arg"
+ ;;
+
+ --tag)
+ prevopt="--tag"
+ prev=tag
+ preserve_args="$preserve_args --tag"
+ ;;
+ --tag=*)
+ set tag "$optarg" ${1+"$@"}
+ shift
+ prev=tag
+ preserve_args="$preserve_args --tag"
+ ;;
+
+ -dlopen)
+ prevopt="-dlopen"
+ prev=execute_dlfiles
+ ;;
+
+ -*)
+ $echo "$modename: unrecognized option \`$arg'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+
+ *)
+ nonopt="$arg"
+ break
+ ;;
+ esac
+done
+
+if test -n "$prevopt"; then
+ $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+fi
+
+case $disable_libs in
+no)
+ ;;
+shared)
+ build_libtool_libs=no
+ build_old_libs=yes
+ ;;
+static)
+ build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+ ;;
+esac
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end. This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+if test -z "$show_help"; then
+
+ # Infer the operation mode.
+ if test -z "$mode"; then
+ $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
+ $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2
+ case $nonopt in
+ *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
+ mode=link
+ for arg
+ do
+ case $arg in
+ -c)
+ mode=compile
+ break
+ ;;
+ esac
+ done
+ ;;
+ *db | *dbx | *strace | *truss)
+ mode=execute
+ ;;
+ *install*|cp|mv)
+ mode=install
+ ;;
+ *rm)
+ mode=uninstall
+ ;;
+ *)
+ # If we have no mode, but dlfiles were specified, then do execute mode.
+ test -n "$execute_dlfiles" && mode=execute
+
+ # Just use the default operation mode.
+ if test -z "$mode"; then
+ if test -n "$nonopt"; then
+ $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+ else
+ $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+ fi
+ fi
+ ;;
+ esac
+ fi
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$execute_dlfiles" && test "$mode" != execute; then
+ $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help="$help"
+ help="Try \`$modename --help --mode=$mode' for more information."
+
+ # These modes are in order of execution frequency so that they run quickly.
+ case $mode in
+ # libtool compile mode
+ compile)
+ modename="$modename: compile"
+ # Get the compilation command and the source file.
+ base_compile=
+ srcfile="$nonopt" # always keep a non-empty value in "srcfile"
+ suppress_opt=yes
+ suppress_output=
+ arg_mode=normal
+ libobj=
+ later=
+
+ for arg
+ do
+ case $arg_mode in
+ arg )
+ # do not "continue". Instead, add this to base_compile
+ lastarg="$arg"
+ arg_mode=normal
+ ;;
+
+ target )
+ libobj="$arg"
+ arg_mode=normal
+ continue
+ ;;
+
+ normal )
+ # Accept any command-line options.
+ case $arg in
+ -o)
+ if test -n "$libobj" ; then
+ $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ arg_mode=target
+ continue
+ ;;
+
+ -static | -prefer-pic | -prefer-non-pic)
+ later="$later $arg"
+ continue
+ ;;
+
+ -no-suppress)
+ suppress_opt=no
+ continue
+ ;;
+
+ -Xcompiler)
+ arg_mode=arg # the next one goes into the "base_compile" arg list
+ continue # The current "srcfile" will either be retained or
+ ;; # replaced later. I would guess that would be a bug.
+
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
+ lastarg=
+ save_ifs="$IFS"; IFS=','
+ for arg in $args; do
+ IFS="$save_ifs"
+
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ lastarg="$lastarg $arg"
+ done
+ IFS="$save_ifs"
+ lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
+
+ # Add the arguments to base_compile.
+ base_compile="$base_compile $lastarg"
+ continue
+ ;;
+
+ * )
+ # Accept the current argument as the source file.
+ # The previous "srcfile" becomes the current argument.
+ #
+ lastarg="$srcfile"
+ srcfile="$arg"
+ ;;
+ esac # case $arg
+ ;;
+ esac # case $arg_mode
+
+ # Aesthetically quote the previous argument.
+ lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+ case $lastarg in
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, and some SunOS ksh mistreat backslash-escaping
+ # in scan sets (worked around with variable expansion),
+ # and furthermore cannot handle '|' '&' '(' ')' in scan sets
+ # at all, so we specify them separately.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ lastarg="\"$lastarg\""
+ ;;
+ esac
+
+ base_compile="$base_compile $lastarg"
+ done # for arg
+
+ case $arg_mode in
+ arg)
+ $echo "$modename: you must specify an argument for -Xcompile"
+ exit $EXIT_FAILURE
+ ;;
+ target)
+ $echo "$modename: you must specify a target with \`-o'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ *)
+ # Get the name of the library object.
+ [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+ ;;
+ esac
+
+ # Recognize several different file suffixes.
+ # If the user specifies -o file.o, it is replaced with file.lo
+ xform='[cCFSifmso]'
+ case $libobj in
+ *.ada) xform=ada ;;
+ *.adb) xform=adb ;;
+ *.ads) xform=ads ;;
+ *.asm) xform=asm ;;
+ *.c++) xform=c++ ;;
+ *.cc) xform=cc ;;
+ *.ii) xform=ii ;;
+ *.class) xform=class ;;
+ *.cpp) xform=cpp ;;
+ *.cxx) xform=cxx ;;
+ *.f90) xform=f90 ;;
+ *.for) xform=for ;;
+ *.java) xform=java ;;
+ *.obj) xform=obj ;;
+ esac
+
+ libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+ case $libobj in
+ *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+ *)
+ $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ func_infer_tag $base_compile
+
+ for arg in $later; do
+ case $arg in
+ -static)
+ build_old_libs=yes
+ continue
+ ;;
+
+ -prefer-pic)
+ pic_mode=yes
+ continue
+ ;;
+
+ -prefer-non-pic)
+ pic_mode=no
+ continue
+ ;;
+ esac
+ done
+
+ qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
+ case $qlibobj in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qlibobj="\"$qlibobj\"" ;;
+ esac
+ test "X$libobj" != "X$qlibobj" \
+ && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \
+ && $echo "$modename: libobj name \`$libobj' may not contain shell special characters."
+ objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+ xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$obj"; then
+ xdir=
+ else
+ xdir=$xdir/
+ fi
+ lobj=${xdir}$objdir/$objname
+
+ if test -z "$base_compile"; then
+ $echo "$modename: you must specify a compilation command" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Delete any leftover library objects.
+ if test "$build_old_libs" = yes; then
+ removelist="$obj $lobj $libobj ${libobj}T"
+ else
+ removelist="$lobj $libobj ${libobj}T"
+ fi
+
+ $run $rm $removelist
+ trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+
+ # On Cygwin there's no "real" PIC flag so we must build both object types
+ case $host_os in
+ cygwin* | mingw* | pw32* | os2*)
+ pic_mode=default
+ ;;
+ esac
+ if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+ # non-PIC code in shared libraries is not supported
+ pic_mode=default
+ fi
+
+ # Calculate the filename of the output object if compiler does
+ # not support -o with -c
+ if test "$compiler_c_o" = no; then
+ output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+ lockfile="$output_obj.lock"
+ removelist="$removelist $output_obj $lockfile"
+ trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+ else
+ output_obj=
+ need_locks=no
+ lockfile=
+ fi
+
+ # Lock this critical section if it is needed
+ # We use this script file to make the link, it avoids creating a new file
+ if test "$need_locks" = yes; then
+ until $run ln "$progpath" "$lockfile" 2>/dev/null; do
+ $show "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ elif test "$need_locks" = warn; then
+ if test -f "$lockfile"; then
+ $echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+ $echo "$srcfile" > "$lockfile"
+ fi
+
+ if test -n "$fix_srcfile_path"; then
+ eval srcfile=\"$fix_srcfile_path\"
+ fi
+ qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
+ case $qsrcfile in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qsrcfile="\"$qsrcfile\"" ;;
+ esac
+
+ $run $rm "$libobj" "${libobj}T"
+
+ # Create a libtool object file (analogous to a ".la" file),
+ # but don't create it if we're doing a dry run.
+ test -z "$run" && cat > ${libobj}T <<EOF
+# $libobj - a libtool object file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+EOF
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test "$build_libtool_libs" = yes; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ if test "$pic_mode" != no; then
+ command="$base_compile $qsrcfile $pic_flag"
+ else
+ # Don't build PIC code
+ command="$base_compile $qsrcfile"
+ fi
+
+ if test ! -d "${xdir}$objdir"; then
+ $show "$mkdir ${xdir}$objdir"
+ $run $mkdir ${xdir}$objdir
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "${xdir}$objdir"; then
+ exit $exit_status
+ fi
+ fi
+
+ if test -z "$output_obj"; then
+ # Place PIC objects in $objdir
+ command="$command -o $lobj"
+ fi
+
+ $run $rm "$lobj" "$output_obj"
+
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ test -n "$output_obj" && $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$need_locks" = warn &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed, then go on to compile the next one
+ if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+ $show "$mv $output_obj $lobj"
+ if $run $mv $output_obj $lobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Append the name of the PIC object to the libtool object file.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object='$objdir/$objname'
+
+EOF
+
+ # Allow error messages only from the first compilation.
+ if test "$suppress_opt" = yes; then
+ suppress_output=' >/dev/null 2>&1'
+ fi
+ else
+ # No PIC object so indicate it doesn't exist in the libtool
+ # object file.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object=none
+
+EOF
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test "$build_old_libs" = yes; then
+ if test "$pic_mode" != yes; then
+ # Don't build PIC code
+ command="$base_compile $qsrcfile"
+ else
+ command="$base_compile $qsrcfile $pic_flag"
+ fi
+ if test "$compiler_c_o" = yes; then
+ command="$command -o $obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ command="$command$suppress_output"
+ $run $rm "$obj" "$output_obj"
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$need_locks" = warn &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed
+ if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+ $show "$mv $output_obj $obj"
+ if $run $mv $output_obj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Append the name of the non-PIC object the libtool object file.
+ # Only append if the libtool object file exists.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object='$objname'
+
+EOF
+ else
+ # Append the name of the non-PIC object the libtool object file.
+ # Only append if the libtool object file exists.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object=none
+
+EOF
+ fi
+
+ $run $mv "${libobj}T" "${libobj}"
+
+ # Unlock the critical section if it was locked
+ if test "$need_locks" != no; then
+ $run $rm "$lockfile"
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool link mode
+ link | relink)
+ modename="$modename: link"
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ # It is impossible to link a dll without this setting, and
+ # we shouldn't force the makefile maintainer to figure out
+ # which system we are compiling for in order to pass an extra
+ # flag for every libtool invocation.
+ # allow_undefined=no
+
+ # FIXME: Unfortunately, there are problems with the above when trying
+ # to make a dll which has undefined symbols, in which case not
+ # even a static library is built. For now, we need to specify
+ # -no-undefined on the libtool link line when we can be certain
+ # that all symbols are satisfied, otherwise we get a static library.
+ allow_undefined=yes
+ ;;
+ *)
+ allow_undefined=yes
+ ;;
+ esac
+ libtool_args="$nonopt"
+ base_compile="$nonopt $@"
+ compile_command="$nonopt"
+ finalize_command="$nonopt"
+
+ compile_rpath=
+ finalize_rpath=
+ compile_shlibpath=
+ finalize_shlibpath=
+ convenience=
+ old_convenience=
+ deplibs=
+ old_deplibs=
+ compiler_flags=
+ linker_flags=
+ dllsearchpath=
+ lib_search_path=`pwd`
+ inst_prefix_dir=
+
+ avoid_version=no
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ ltlibs=
+ module=no
+ no_install=no
+ objs=
+ non_pic_objects=
+ notinst_path= # paths that contain not-installed libtool libraries
+ precious_files_regex=
+ prefer_static_libs=no
+ preload=no
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+ vinfo_number=no
+
+ func_infer_tag $base_compile
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case $arg in
+ -all-static | -static | -static-libtool-libs)
+ case $arg in
+ -all-static)
+ if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+ $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=yes
+ ;;
+ -static)
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=built
+ ;;
+ -static-libtool-libs)
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=yes
+ ;;
+ esac
+ build_libtool_libs=no
+ build_old_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ while test "$#" -gt 0; do
+ arg="$1"
+ shift
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
+ ;;
+ *) qarg=$arg ;;
+ esac
+ libtool_args="$libtool_args $qarg"
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ output)
+ compile_command="$compile_command @OUTPUT@"
+ finalize_command="$finalize_command @OUTPUT@"
+ ;;
+ esac
+
+ case $prev in
+ dlfiles|dlprefiles)
+ if test "$preload" = no; then
+ # Add the symbol object into the linking commands.
+ compile_command="$compile_command @SYMFILE@"
+ finalize_command="$finalize_command @SYMFILE@"
+ preload=yes
+ fi
+ case $arg in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test "$dlself" = no; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test "$prev" = dlprefiles; then
+ dlself=yes
+ elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ else
+ dlprefiles="$dlprefiles $arg"
+ fi
+ prev=
+ continue
+ ;;
+ esac
+ ;;
+ expsyms)
+ export_symbols="$arg"
+ if test ! -f "$arg"; then
+ $echo "$modename: symbol file \`$arg' does not exist"
+ exit $EXIT_FAILURE
+ fi
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex="$arg"
+ prev=
+ continue
+ ;;
+ inst_prefix)
+ inst_prefix_dir="$arg"
+ prev=
+ continue
+ ;;
+ precious_regex)
+ precious_files_regex="$arg"
+ prev=
+ continue
+ ;;
+ release)
+ release="-$arg"
+ prev=
+ continue
+ ;;
+ objectlist)
+ if test -f "$arg"; then
+ save_arg=$arg
+ moreargs=
+ for fil in `cat $save_arg`
+ do
+# moreargs="$moreargs $fil"
+ arg=$fil
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ # If there is no directory component, then add one.
+ case $arg in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ if test -z "$pic_object" || \
+ test -z "$non_pic_object" ||
+ test "$pic_object" = none && \
+ test "$non_pic_object" = none; then
+ $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ if test "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ libobjs="$libobjs $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object="$xdir$non_pic_object"
+
+ # A standard non-PIC object
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ if test -z "$pic_object" || test "$pic_object" = none ; then
+ arg="$non_pic_object"
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object="$pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if test -z "$run"; then
+ $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+ exit $EXIT_FAILURE
+ else
+ # Dry-run case.
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+ non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+ libobjs="$libobjs $pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ fi
+ done
+ else
+ $echo "$modename: link input file \`$save_arg' does not exist"
+ exit $EXIT_FAILURE
+ fi
+ arg=$save_arg
+ prev=
+ continue
+ ;;
+ rpath | xrpath)
+ # We need an absolute path.
+ case $arg in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ if test "$prev" = rpath; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) rpath="$rpath $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) xrpath="$xrpath $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ xcompiler)
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ compile_command="$compile_command $qarg"
+ finalize_command="$finalize_command $qarg"
+ continue
+ ;;
+ xlinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $wl$qarg"
+ prev=
+ compile_command="$compile_command $wl$qarg"
+ finalize_command="$finalize_command $wl$qarg"
+ continue
+ ;;
+ xcclinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ compile_command="$compile_command $qarg"
+ finalize_command="$finalize_command $qarg"
+ continue
+ ;;
+ shrext)
+ shrext_cmds="$arg"
+ prev=
+ continue
+ ;;
+ darwin_framework|darwin_framework_skip)
+ test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ prev=
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi # test -n "$prev"
+
+ prevarg="$arg"
+
+ case $arg in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ # FIXME: remove this flag sometime in the future.
+ $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+ continue
+ ;;
+
+ -avoid-version)
+ avoid_version=yes
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ export_dynamic=yes
+ continue
+ ;;
+
+ -export-symbols | -export-symbols-regex)
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: more than one -exported-symbols argument is not allowed"
+ exit $EXIT_FAILURE
+ fi
+ if test "X$arg" = "X-export-symbols"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ continue
+ ;;
+
+ -framework|-arch|-isysroot)
+ case " $CC " in
+ *" ${arg} ${1} "* | *" ${arg} ${1} "*)
+ prev=darwin_framework_skip ;;
+ *) compiler_flags="$compiler_flags $arg"
+ prev=darwin_framework ;;
+ esac
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ continue
+ ;;
+
+ -inst-prefix-dir)
+ prev=inst_prefix
+ continue
+ ;;
+
+ # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+ # so, if we see these flags be careful not to treat them like -L
+ -L[A-Z][A-Z]*:*)
+ case $with_gcc/$host in
+ no/*-*-irix* | /*-*-irix*)
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ ;;
+ esac
+ continue
+ ;;
+
+ -L*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
+ absdir="$dir"
+ notinst_path="$notinst_path $dir"
+ fi
+ dir="$absdir"
+ ;;
+ esac
+ case "$deplibs " in
+ *" -L$dir "*) ;;
+ *)
+ deplibs="$deplibs -L$dir"
+ lib_search_path="$lib_search_path $dir"
+ ;;
+ esac
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$dir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$dir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$testbindir";;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+
+ -l*)
+ if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*)
+ # These systems don't actually have a C or math library (as such)
+ continue
+ ;;
+ *-*-os2*)
+ # These systems don't actually have a C library (as such)
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc due to us having libc/libc_r.
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C and math libraries are in the System framework
+ deplibs="$deplibs -framework System"
+ continue
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ test "X$arg" = "X-lc" && continue
+ ;;
+ esac
+ elif test "X$arg" = "X-lc_r"; then
+ case $host in
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc_r directly, use -pthread flag.
+ continue
+ ;;
+ esac
+ fi
+ deplibs="$deplibs $arg"
+ continue
+ ;;
+
+ # Tru64 UNIX uses -model [arg] to determine the layout of C++
+ # classes, name mangling, and exception handling.
+ -model)
+ compile_command="$compile_command $arg"
+ compiler_flags="$compiler_flags $arg"
+ finalize_command="$finalize_command $arg"
+ prev=xcompiler
+ continue
+ ;;
+
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
+ compiler_flags="$compiler_flags $arg"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ continue
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+ # -r[0-9][0-9]* specifies the processor on the SGI compiler
+ # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+ # +DA*, +DD* enable 64-bit mode on the HP compiler
+ # -q* pass through compiler args for the IBM compiler
+ # -m* pass through architecture-specific compiler args for GCC
+ # -m*, -t[45]*, -txscale* pass through architecture-specific
+ # compiler args for GCC
+ # -pg pass through profiling flag for GCC
+ # @file GCC response files
+ -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \
+ -t[45]*|-txscale*|@*)
+
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ compiler_flags="$compiler_flags $arg"
+ continue
+ ;;
+
+ -shrext)
+ prev=shrext
+ continue
+ ;;
+
+ -no-fast-install)
+ fast_install=no
+ continue
+ ;;
+
+ -no-install)
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ # The PATH hackery in wrapper scripts is required on Windows
+ # in order for the loader to find any dlls it needs.
+ $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
+ $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
+ fast_install=no
+ ;;
+ *) no_install=yes ;;
+ esac
+ continue
+ ;;
+
+ -no-undefined)
+ allow_undefined=no
+ continue
+ ;;
+
+ -objectlist)
+ prev=objectlist
+ continue
+ ;;
+
+ -o) prev=output ;;
+
+ -precious-files-regex)
+ prev=precious_regex
+ continue
+ ;;
+
+ -release)
+ prev=release
+ continue
+ ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -R)
+ prev=xrpath
+ continue
+ ;;
+
+ -R*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ continue
+ ;;
+
+ -static | -static-libtool-libs)
+ # The effects of -static are defined in a previous loop.
+ # We used to do the same as -all-static on platforms that
+ # didn't have a PIC flag, but the assumption that the effects
+ # would be equivalent was wrong. It would break on at least
+ # Digital Unix and AIX.
+ continue
+ ;;
+
+ -thread-safe)
+ thread_safe=yes
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+ -version-number)
+ prev=vinfo
+ vinfo_number=yes
+ continue
+ ;;
+
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Wl,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $wl$flag"
+ linker_flags="$linker_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Xcompiler)
+ prev=xcompiler
+ continue
+ ;;
+
+ -Xlinker)
+ prev=xlinker
+ continue
+ ;;
+
+ -XCClinker)
+ prev=xcclinker
+ continue
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+
+ *.$objext)
+ # A standard object.
+ objs="$objs $arg"
+ ;;
+
+ *.lo)
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ # If there is no directory component, then add one.
+ case $arg in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ if test -z "$pic_object" || \
+ test -z "$non_pic_object" ||
+ test "$pic_object" = none && \
+ test "$non_pic_object" = none; then
+ $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ if test "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ libobjs="$libobjs $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object="$xdir$non_pic_object"
+
+ # A standard non-PIC object
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ if test -z "$pic_object" || test "$pic_object" = none ; then
+ arg="$non_pic_object"
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object="$pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if test -z "$run"; then
+ $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+ exit $EXIT_FAILURE
+ else
+ # Dry-run case.
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+ non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+ libobjs="$libobjs $pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ fi
+ ;;
+
+ *.$libext)
+ # An archive.
+ deplibs="$deplibs $arg"
+ old_deplibs="$old_deplibs $arg"
+ continue
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ if test "$prev" = dlfiles; then
+ # This library was specified with -dlopen.
+ dlfiles="$dlfiles $arg"
+ prev=
+ elif test "$prev" = dlprefiles; then
+ # The library was specified with -dlpreopen.
+ dlprefiles="$dlprefiles $arg"
+ prev=
+ else
+ deplibs="$deplibs $arg"
+ fi
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+ esac # arg
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+ done # argument parsing loop
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+
+ oldlibs=
+ # calculate the name of the file, without its directory
+ outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+ libobjs_save="$libobjs"
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+ else
+ shlib_search_path=
+ fi
+ eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+ # Create the object directory.
+ if test ! -d "$output_objdir"; then
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then
+ exit $exit_status
+ fi
+ fi
+
+ # Determine the type of output
+ case $output in
+ "")
+ $echo "$modename: you must specify an output file" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ *.$libext) linkmode=oldlib ;;
+ *.lo | *.$objext) linkmode=obj ;;
+ *.la) linkmode=lib ;;
+ *) linkmode=prog ;; # Anything else should be a program.
+ esac
+
+ case $host in
+ *cygwin* | *mingw* | *pw32*)
+ # don't eliminate duplications in $postdeps and $predeps
+ duplicate_compiler_generated_deps=yes
+ ;;
+ *)
+ duplicate_compiler_generated_deps=$duplicate_deps
+ ;;
+ esac
+ specialdeplibs=
+
+ libs=
+ # Find all interdependent deplibs by searching for libraries
+ # that are linked more than once (e.g. -la -lb -la)
+ for deplib in $deplibs; do
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ libs="$libs $deplib"
+ done
+
+ if test "$linkmode" = lib; then
+ libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+ # Compute libraries that are listed more than once in $predeps
+ # $postdeps and mark them as special (i.e., whose duplicates are
+ # not to be eliminated).
+ pre_post_deps=
+ if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then
+ for pre_post_dep in $predeps $postdeps; do
+ case "$pre_post_deps " in
+ *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+ esac
+ pre_post_deps="$pre_post_deps $pre_post_dep"
+ done
+ fi
+ pre_post_deps=
+ fi
+
+ deplibs=
+ newdependency_libs=
+ newlib_search_path=
+ need_relink=no # whether we're linking any uninstalled libtool libraries
+ notinst_deplibs= # not-installed libtool libraries
+ case $linkmode in
+ lib)
+ passes="conv link"
+ for file in $dlfiles $dlprefiles; do
+ case $file in
+ *.la) ;;
+ *)
+ $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ done
+ ;;
+ prog)
+ compile_deplibs=
+ finalize_deplibs=
+ alldeplibs=no
+ newdlfiles=
+ newdlprefiles=
+ passes="conv scan dlopen dlpreopen link"
+ ;;
+ *) passes="conv"
+ ;;
+ esac
+ for pass in $passes; do
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan"; then
+ libs="$deplibs"
+ deplibs=
+ fi
+ if test "$linkmode" = prog; then
+ case $pass in
+ dlopen) libs="$dlfiles" ;;
+ dlpreopen) libs="$dlprefiles" ;;
+ link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+ esac
+ fi
+ if test "$pass" = dlopen; then
+ # Collect dlpreopened libraries
+ save_deplibs="$deplibs"
+ deplibs=
+ fi
+ for deplib in $libs; do
+ lib=
+ found=no
+ case $deplib in
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ compiler_flags="$compiler_flags $deplib"
+ fi
+ continue
+ ;;
+ -l*)
+ if test "$linkmode" != lib && test "$linkmode" != prog; then
+ $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
+ continue
+ fi
+ name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
+ for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ for search_ext in .la $std_shrext .so .a; do
+ # Search the libtool library
+ lib="$searchdir/lib${name}${search_ext}"
+ if test -f "$lib"; then
+ if test "$search_ext" = ".la"; then
+ found=yes
+ else
+ found=no
+ fi
+ break 2
+ fi
+ done
+ done
+ if test "$found" != yes; then
+ # deplib doesn't seem to be a libtool library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ else # deplib is a libtool library
+ # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+ # We need to do some special things here, and not later.
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $deplib "*)
+ if (${SED} -e '2q' $lib |
+ grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ library_names=
+ old_library=
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ for l in $old_library $library_names; do
+ ll="$l"
+ done
+ if test "X$ll" = "X$old_library" ; then # only static version available
+ found=no
+ ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$ladir" = "X$lib" && ladir="."
+ lib=$ladir/$old_library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+ fi
+ fi
+ ;; # -l
+ -L*)
+ case $linkmode in
+ lib)
+ deplibs="$deplib $deplibs"
+ test "$pass" = conv && continue
+ newdependency_libs="$deplib $newdependency_libs"
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ ;;
+ prog)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ if test "$pass" = scan; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ ;;
+ *)
+ $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2
+ ;;
+ esac # linkmode
+ continue
+ ;; # -L
+ -R*)
+ if test "$pass" = link; then
+ dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+ # Make sure the xrpath contains only unique directories.
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ fi
+ deplibs="$deplib $deplibs"
+ continue
+ ;;
+ *.la) lib="$deplib" ;;
+ *.$libext)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ case $linkmode in
+ lib)
+ valid_a_lib=no
+ case $deplibs_check_method in
+ match_pattern*)
+ set dummy $deplibs_check_method
+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ if eval $echo \"$deplib\" 2>/dev/null \
+ | $SED 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ valid_a_lib=yes
+ fi
+ ;;
+ pass_all)
+ valid_a_lib=yes
+ ;;
+ esac
+ if test "$valid_a_lib" != yes; then
+ $echo
+ $echo "*** Warning: Trying to link with static lib archive $deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because the file extensions .$libext of this argument makes me believe"
+ $echo "*** that it is just a static archive that I should not used here."
+ else
+ $echo
+ $echo "*** Warning: Linking the shared library $output against the"
+ $echo "*** static library $deplib is not portable!"
+ deplibs="$deplib $deplibs"
+ fi
+ continue
+ ;;
+ prog)
+ if test "$pass" != link; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ continue
+ ;;
+ esac # linkmode
+ ;; # *.$libext
+ *.lo | *.$objext)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ elif test "$linkmode" = prog; then
+ if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlopen support or we're linking statically,
+ # we need to preload.
+ newdlprefiles="$newdlprefiles $deplib"
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ newdlfiles="$newdlfiles $deplib"
+ fi
+ fi
+ continue
+ ;;
+ %DEPLIBS%)
+ alldeplibs=yes
+ continue
+ ;;
+ esac # case $deplib
+ if test "$found" = yes || test -f "$lib"; then :
+ else
+ $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$ladir" = "X$lib" && ladir="."
+
+ dlname=
+ dlopen=
+ dlpreopen=
+ libdir=
+ library_names=
+ old_library=
+ # If the library was installed with an old release of libtool,
+ # it will not redefine variables installed, or shouldnotlink
+ installed=yes
+ shouldnotlink=no
+ avoidtemprpath=
+
+
+ # Read the .la file
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan" ||
+ { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+ test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+ test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+ fi
+
+ if test "$pass" = conv; then
+ # Only check for convenience libraries
+ deplibs="$lib $deplibs"
+ if test -z "$libdir"; then
+ if test -z "$old_library"; then
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ # It is a libtool convenience library, so add in its objects.
+ convenience="$convenience $ladir/$objdir/$old_library"
+ old_convenience="$old_convenience $ladir/$objdir/$old_library"
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+ elif test "$linkmode" != prog && test "$linkmode" != lib; then
+ $echo "$modename: \`$lib' is not a convenience library" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ continue
+ fi # $pass = conv
+
+
+ # Get the name of the library we link against.
+ linklib=
+ for l in $old_library $library_names; do
+ linklib="$l"
+ done
+ if test -z "$linklib"; then
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # This library was specified with -dlopen.
+ if test "$pass" = dlopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test -z "$dlname" ||
+ test "$dlopen_support" != yes ||
+ test "$build_libtool_libs" = no; then
+ # If there is no dlname, no dlopen support or we're linking
+ # statically, we need to preload. We also need to preload any
+ # dependent libraries so libltdl's deplib preloader doesn't
+ # bomb out in the load deplibs phase.
+ dlprefiles="$dlprefiles $lib $dependency_libs"
+ else
+ newdlfiles="$newdlfiles $lib"
+ fi
+ continue
+ fi # $pass = dlopen
+
+ # We need an absolute path.
+ case $ladir in
+ [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+ *)
+ abs_ladir=`cd "$ladir" && pwd`
+ if test -z "$abs_ladir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
+ $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+ abs_ladir="$ladir"
+ fi
+ ;;
+ esac
+ laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+
+ # Find the relevant object directory and library name.
+ if test "X$installed" = Xyes; then
+ if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ $echo "$modename: warning: library \`$lib' was moved." 1>&2
+ dir="$ladir"
+ absdir="$abs_ladir"
+ libdir="$abs_ladir"
+ else
+ dir="$libdir"
+ absdir="$libdir"
+ fi
+ test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+ else
+ if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ dir="$ladir"
+ absdir="$abs_ladir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ else
+ dir="$ladir/$objdir"
+ absdir="$abs_ladir/$objdir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ fi
+ fi # $installed = yes
+ name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+
+ # This library was specified with -dlpreopen.
+ if test "$pass" = dlpreopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ newdlprefiles="$newdlprefiles $dir/$old_library"
+ # Otherwise, use the dlname, so that lt_dlopen finds it.
+ elif test -n "$dlname"; then
+ newdlprefiles="$newdlprefiles $dir/$dlname"
+ else
+ newdlprefiles="$newdlprefiles $dir/$linklib"
+ fi
+ fi # $pass = dlpreopen
+
+ if test -z "$libdir"; then
+ # Link the convenience library
+ if test "$linkmode" = lib; then
+ deplibs="$dir/$old_library $deplibs"
+ elif test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$dir/$old_library $compile_deplibs"
+ finalize_deplibs="$dir/$old_library $finalize_deplibs"
+ else
+ deplibs="$lib $deplibs" # used for prog,scan pass
+ fi
+ continue
+ fi
+
+
+ if test "$linkmode" = prog && test "$pass" != link; then
+ newlib_search_path="$newlib_search_path $ladir"
+ deplibs="$lib $deplibs"
+
+ linkalldeplibs=no
+ if test "$link_all_deplibs" != no || test -z "$library_names" ||
+ test "$build_libtool_libs" = no; then
+ linkalldeplibs=yes
+ fi
+
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
+ esac
+ # Need to link against all dependency_libs?
+ if test "$linkalldeplibs" = yes; then
+ deplibs="$deplib $deplibs"
+ else
+ # Need to hardcode shared library paths
+ # or/and link against static libraries
+ newdependency_libs="$deplib $newdependency_libs"
+ fi
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done # for deplib
+ continue
+ fi # $linkmode = prog...
+
+ if test "$linkmode,$pass" = "prog,link"; then
+ if test -n "$library_names" &&
+ { { test "$prefer_static_libs" = no ||
+ test "$prefer_static_libs,$installed" = "built,yes"; } ||
+ test -z "$old_library"; }; then
+ # We need to hardcode the library path
+ if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath " in
+ *" $dir "*) ;;
+ *" $absdir "*) ;;
+ *) temp_rpath="$temp_rpath $absdir" ;;
+ esac
+ fi
+
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ fi # $linkmode,$pass = prog,link...
+
+ if test "$alldeplibs" = yes &&
+ { test "$deplibs_check_method" = pass_all ||
+ { test "$build_libtool_libs" = yes &&
+ test -n "$library_names"; }; }; then
+ # We only need to search for static libraries
+ continue
+ fi
+ fi
+
+ link_static=no # Whether the deplib will be linked statically
+ use_static_libs=$prefer_static_libs
+ if test "$use_static_libs" = built && test "$installed" = yes ; then
+ use_static_libs=no
+ fi
+ if test -n "$library_names" &&
+ { test "$use_static_libs" = no || test -z "$old_library"; }; then
+ if test "$installed" = no; then
+ notinst_deplibs="$notinst_deplibs $lib"
+ need_relink=yes
+ fi
+ # This is a shared library
+
+ # Warn about portability, can't link against -module's on
+ # some systems (darwin)
+ if test "$shouldnotlink" = yes && test "$pass" = link ; then
+ $echo
+ if test "$linkmode" = prog; then
+ $echo "*** Warning: Linking the executable $output against the loadable module"
+ else
+ $echo "*** Warning: Linking the shared library $output against the loadable module"
+ fi
+ $echo "*** $linklib is not portable!"
+ fi
+ if test "$linkmode" = lib &&
+ test "$hardcode_into_libs" = yes; then
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ fi
+
+ if test -n "$old_archive_from_expsyms_cmds"; then
+ # figure out the soname
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+ libname=`eval \\$echo \"$libname_spec\"`
+ # use dlname if we got it. it's perfectly good, no?
+ if test -n "$dlname"; then
+ soname="$dlname"
+ elif test -n "$soname_spec"; then
+ # bleh windows
+ case $host in
+ *cygwin* | mingw*)
+ major=`expr $current - $age`
+ versuffix="-$major"
+ ;;
+ esac
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+
+ # Make a new name for the extract_expsyms_cmds to use
+ soroot="$soname"
+ soname=`$echo $soroot | ${SED} -e 's/^.*\///'`
+ newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
+
+ # If the library has no export list, then create one now
+ if test -f "$output_objdir/$soname-def"; then :
+ else
+ $show "extracting exported symbol list from \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ cmds=$extract_expsyms_cmds
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Create $newlib
+ if test -f "$output_objdir/$newlib"; then :; else
+ $show "generating import library for \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ cmds=$old_archive_from_expsyms_cmds
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+ # make sure the library variables are pointing to the new library
+ dir=$output_objdir
+ linklib=$newlib
+ fi # test -n "$old_archive_from_expsyms_cmds"
+
+ if test "$linkmode" = prog || test "$mode" != relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ lib_linked=yes
+ case $hardcode_action in
+ immediate | unsupported)
+ if test "$hardcode_direct" = no; then
+ add="$dir/$linklib"
+ case $host in
+ *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+ *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+ *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+ *-*-unixware7*) add_dir="-L$dir" ;;
+ *-*-darwin* )
+ # if the lib is a module then we can not link against
+ # it, someone is ignoring the new warnings I added
+ if /usr/bin/file -L $add 2> /dev/null |
+ $EGREP ": [^:]* bundle" >/dev/null ; then
+ $echo "** Warning, lib $linklib is a module, not a shared library"
+ if test -z "$old_library" ; then
+ $echo
+ $echo "** And there doesn't seem to be a static archive available"
+ $echo "** The link will probably fail, sorry"
+ else
+ add="$dir/$old_library"
+ fi
+ fi
+ esac
+ elif test "$hardcode_minus_L" = no; then
+ case $host in
+ *-*-sunos*) add_shlibpath="$dir" ;;
+ esac
+ add_dir="-L$dir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ relink)
+ if test "$hardcode_direct" = yes; then
+ add="$dir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$dir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ *) lib_linked=no ;;
+ esac
+
+ if test "$lib_linked" != yes; then
+ $echo "$modename: configuration error: unsupported hardcode properties"
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$add_shlibpath"; then
+ case :$compile_shlibpath: in
+ *":$add_shlibpath:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+ esac
+ fi
+ if test "$linkmode" = prog; then
+ test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+ test -n "$add" && compile_deplibs="$add $compile_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ if test "$hardcode_direct" != yes && \
+ test "$hardcode_minus_L" != yes && \
+ test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ fi
+ fi
+ fi
+
+ if test "$linkmode" = prog || test "$mode" = relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ # Finalize command for both is simple: just hardcode it.
+ if test "$hardcode_direct" = yes; then
+ add="$libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$libdir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ add="-l$name"
+ elif test "$hardcode_automatic" = yes; then
+ if test -n "$inst_prefix_dir" &&
+ test -f "$inst_prefix_dir$libdir/$linklib" ; then
+ add="$inst_prefix_dir$libdir/$linklib"
+ else
+ add="$libdir/$linklib"
+ fi
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ add_dir="-L$libdir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ fi
+
+ if test "$linkmode" = prog; then
+ test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+ test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ fi
+ fi
+ elif test "$linkmode" = prog; then
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test "$hardcode_direct" != unsupported; then
+ test -n "$old_library" && linklib="$old_library"
+ compile_deplibs="$dir/$linklib $compile_deplibs"
+ finalize_deplibs="$dir/$linklib $finalize_deplibs"
+ else
+ compile_deplibs="-l$name -L$dir $compile_deplibs"
+ finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+ fi
+ elif test "$build_libtool_libs" = yes; then
+ # Not a shared library
+ if test "$deplibs_check_method" != pass_all; then
+ # We're trying link a shared library against a static one
+ # but the system doesn't support it.
+
+ # Just print a warning and add the library to dependency_libs so
+ # that the program can be linked against the static library.
+ $echo
+ $echo "*** Warning: This system can not link to static lib archive $lib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have."
+ if test "$module" = yes; then
+ $echo "*** But as you try to build a module library, libtool will still create "
+ $echo "*** a static module, that should work as long as the dlopening application"
+ $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+ if test -z "$global_symbol_pipe"; then
+ $echo
+ $echo "*** However, this would only work if libtool was able to extract symbol"
+ $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ $echo "*** not find such a program. So, this module is probably useless."
+ $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ else
+ deplibs="$dir/$old_library $deplibs"
+ link_static=yes
+ fi
+ fi # link shared/static library?
+
+ if test "$linkmode" = lib; then
+ if test -n "$dependency_libs" &&
+ { test "$hardcode_into_libs" != yes ||
+ test "$build_old_libs" = yes ||
+ test "$link_static" = yes; }; then
+ # Extract -R from dependency_libs
+ temp_deplibs=
+ for libdir in $dependency_libs; do
+ case $libdir in
+ -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
+ case " $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) xrpath="$xrpath $temp_xrpath";;
+ esac;;
+ *) temp_deplibs="$temp_deplibs $libdir";;
+ esac
+ done
+ dependency_libs="$temp_deplibs"
+ fi
+
+ newlib_search_path="$newlib_search_path $absdir"
+ # Link against this library
+ test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+ # ... and its dependency_libs
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ newdependency_libs="$deplib $newdependency_libs"
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+
+ if test "$link_all_deplibs" != no; then
+ # Add the search paths of all dependency libraries
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) path="$deplib" ;;
+ *.la)
+ dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$deplib" && dir="."
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+ absdir="$dir"
+ fi
+ ;;
+ esac
+ if grep "^installed=no" $deplib > /dev/null; then
+ path="$absdir/$objdir"
+ else
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test "$absdir" != "$libdir"; then
+ $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
+ fi
+ path="$absdir"
+ fi
+ depdepl=
+ case $host in
+ *-*-darwin*)
+ # we do not want to link against static libs,
+ # but need to link against shared
+ eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+ if test -n "$deplibrary_names" ; then
+ for tmp in $deplibrary_names ; do
+ depdepl=$tmp
+ done
+ if test -f "$path/$depdepl" ; then
+ depdepl="$path/$depdepl"
+ fi
+ # do not add paths which are already there
+ case " $newlib_search_path " in
+ *" $path "*) ;;
+ *) newlib_search_path="$newlib_search_path $path";;
+ esac
+ fi
+ path=""
+ ;;
+ *)
+ path="-L$path"
+ ;;
+ esac
+ ;;
+ -l*)
+ case $host in
+ *-*-darwin*)
+ # Again, we only want to link against shared libraries
+ eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
+ for tmp in $newlib_search_path ; do
+ if test -f "$tmp/lib$tmp_libs.dylib" ; then
+ eval depdepl="$tmp/lib$tmp_libs.dylib"
+ break
+ fi
+ done
+ path=""
+ ;;
+ *) continue ;;
+ esac
+ ;;
+ *) continue ;;
+ esac
+ case " $deplibs " in
+ *" $path "*) ;;
+ *) deplibs="$path $deplibs" ;;
+ esac
+ case " $deplibs " in
+ *" $depdepl "*) ;;
+ *) deplibs="$depdepl $deplibs" ;;
+ esac
+ done
+ fi # link_all_deplibs != no
+ fi # linkmode = lib
+ done # for deplib in $libs
+ dependency_libs="$newdependency_libs"
+ if test "$pass" = dlpreopen; then
+ # Link the dlpreopened libraries before other libraries
+ for deplib in $save_deplibs; do
+ deplibs="$deplib $deplibs"
+ done
+ fi
+ if test "$pass" != dlopen; then
+ if test "$pass" != conv; then
+ # Make sure lib_search_path contains only unique directories.
+ lib_search_path=
+ for dir in $newlib_search_path; do
+ case "$lib_search_path " in
+ *" $dir "*) ;;
+ *) lib_search_path="$lib_search_path $dir" ;;
+ esac
+ done
+ newlib_search_path=
+ fi
+
+ if test "$linkmode,$pass" != "prog,link"; then
+ vars="deplibs"
+ else
+ vars="compile_deplibs finalize_deplibs"
+ fi
+ for var in $vars dependency_libs; do
+ # Add libraries to $var in reverse order
+ eval tmp_libs=\"\$$var\"
+ new_libs=
+ for deplib in $tmp_libs; do
+ # FIXME: Pedantically, this is the right thing to do, so
+ # that some nasty dependency loop isn't accidentally
+ # broken:
+ #new_libs="$deplib $new_libs"
+ # Pragmatically, this seems to cause very few problems in
+ # practice:
+ case $deplib in
+ -L*) new_libs="$deplib $new_libs" ;;
+ -R*) ;;
+ *)
+ # And here is the reason: when a library appears more
+ # than once as an explicit dependence of a library, or
+ # is implicitly linked in more than once by the
+ # compiler, it is considered special, and multiple
+ # occurrences thereof are not removed. Compare this
+ # with having the same library being listed as a
+ # dependency of multiple other libraries: in this case,
+ # we know (pedantically, we assume) the library does not
+ # need to be listed more than once, so we keep only the
+ # last copy. This is not always right, but it is rare
+ # enough that we require users that really mean to play
+ # such unportable linking tricks to link the library
+ # using -Wl,-lname, so that libtool does not consider it
+ # for duplicate removal.
+ case " $specialdeplibs " in
+ *" $deplib "*) new_libs="$deplib $new_libs" ;;
+ *)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$deplib $new_libs" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ tmp_libs=
+ for deplib in $new_libs; do
+ case $deplib in
+ -L*)
+ case " $tmp_libs " in
+ *" $deplib "*) ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ done
+ eval $var=\"$tmp_libs\"
+ done # for var
+ fi
+ # Last step: remove runtime libs from dependency_libs
+ # (they stay in deplibs)
+ tmp_libs=
+ for i in $dependency_libs ; do
+ case " $predeps $postdeps $compiler_lib_search_path " in
+ *" $i "*)
+ i=""
+ ;;
+ esac
+ if test -n "$i" ; then
+ tmp_libs="$tmp_libs $i"
+ fi
+ done
+ dependency_libs=$tmp_libs
+ done # for pass
+ if test "$linkmode" = prog; then
+ dlfiles="$newdlfiles"
+ dlprefiles="$newdlprefiles"
+ fi
+
+ case $linkmode in
+ oldlib)
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+ fi
+
+ # Now set the variables for building old libraries.
+ build_libtool_libs=no
+ oldlibs="$output"
+ objs="$objs$old_deplibs"
+ ;;
+
+ lib)
+ # Make sure we only generate libraries of the form `libNAME.la'.
+ case $outputname in
+ lib*)
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ ;;
+ *)
+ if test "$module" = no; then
+ $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test "$need_lib_prefix" != no; then
+ # Add the "lib" prefix for modules if required
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ else
+ libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ fi
+ ;;
+ esac
+
+ if test -n "$objs"; then
+ if test "$deplibs_check_method" != pass_all; then
+ $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
+ exit $EXIT_FAILURE
+ else
+ $echo
+ $echo "*** Warning: Linking the shared library $output against the non-libtool"
+ $echo "*** objects $objs is not portable!"
+ libobjs="$libobjs $objs"
+ fi
+ fi
+
+ if test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
+ fi
+
+ set dummy $rpath
+ if test "$#" -gt 2; then
+ $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+ fi
+ install_libdir="$2"
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test "$build_libtool_libs" = yes; then
+ # Building a libtool convenience library.
+ # Some compilers have problems with a `.al' extension so
+ # convenience libraries should have the same extension an
+ # archive normally would.
+ oldlibs="$output_objdir/$libname.$libext $oldlibs"
+ build_libtool_libs=convenience
+ build_old_libs=yes
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+ fi
+ else
+
+ # Parse the version information argument.
+ save_ifs="$IFS"; IFS=':'
+ set dummy $vinfo 0 0 0
+ IFS="$save_ifs"
+
+ if test -n "$8"; then
+ $echo "$modename: too many parameters to \`-version-info'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # convert absolute version numbers to libtool ages
+ # this retains compatibility with .la files and attempts
+ # to make the code below a bit more comprehensible
+
+ case $vinfo_number in
+ yes)
+ number_major="$2"
+ number_minor="$3"
+ number_revision="$4"
+ #
+ # There are really only two kinds -- those that
+ # use the current revision as the major version
+ # and those that subtract age and use age as
+ # a minor version. But, then there is irix
+ # which has an extra 1 added just for fun
+ #
+ case $version_type in
+ darwin|linux|osf|windows|none)
+ current=`expr $number_major + $number_minor`
+ age="$number_minor"
+ revision="$number_revision"
+ ;;
+ freebsd-aout|freebsd-elf|sunos)
+ current="$number_major"
+ revision="$number_minor"
+ age="0"
+ ;;
+ irix|nonstopux)
+ current=`expr $number_major + $number_minor - 1`
+ age="$number_minor"
+ revision="$number_minor"
+ ;;
+ esac
+ ;;
+ no)
+ current="$2"
+ revision="$3"
+ age="$4"
+ ;;
+ esac
+
+ # Check that each of the things are valid numbers.
+ case $current in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $revision in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $age in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ if test "$age" -gt "$current"; then
+ $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Calculate the version variables.
+ major=
+ versuffix=
+ verstring=
+ case $version_type in
+ none) ;;
+
+ darwin)
+ # Like Linux, but with the current version available in
+ # verstring for coding it into the library header
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ # Darwin ld doesn't like 0 for these options...
+ minor_current=`expr $current + 1`
+ verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+ ;;
+
+ freebsd-aout)
+ major=".$current"
+ versuffix=".$current.$revision";
+ ;;
+
+ freebsd-elf)
+ major=".$current"
+ versuffix=".$current";
+ ;;
+
+ irix | nonstopux)
+ major=`expr $current - $age + 1`
+
+ case $version_type in
+ nonstopux) verstring_prefix=nonstopux ;;
+ *) verstring_prefix=sgi ;;
+ esac
+ verstring="$verstring_prefix$major.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test "$loop" -ne 0; do
+ iface=`expr $revision - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring_prefix$major.$iface:$verstring"
+ done
+
+ # Before this point, $major must not contain `.'.
+ major=.$major
+ versuffix="$major.$revision"
+ ;;
+
+ linux)
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ ;;
+
+ osf)
+ major=.`expr $current - $age`
+ versuffix=".$current.$age.$revision"
+ verstring="$current.$age.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test "$loop" -ne 0; do
+ iface=`expr $current - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring:${iface}.0"
+ done
+
+ # Make executables depend on our current version.
+ verstring="$verstring:${current}.0"
+ ;;
+
+ sunos)
+ major=".$current"
+ versuffix=".$current.$revision"
+ ;;
+
+ windows)
+ # Use '-' rather than '.', since we only want one
+ # extension on DOS 8.3 filesystems.
+ major=`expr $current - $age`
+ versuffix="-$major"
+ ;;
+
+ *)
+ $echo "$modename: unknown library version type \`$version_type'" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ # Clear the version info if we defaulted, and they specified a release.
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ case $version_type in
+ darwin)
+ # we can't check for "0.0" in archive_cmds due to quoting
+ # problems, so we reset it completely
+ verstring=
+ ;;
+ *)
+ verstring="0.0"
+ ;;
+ esac
+ if test "$need_version" = no; then
+ versuffix=
+ else
+ versuffix=".0.0"
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test "$avoid_version" = yes && test "$need_version" = no; then
+ major=
+ versuffix=
+ verstring=""
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test "$allow_undefined" = yes; then
+ if test "$allow_undefined_flag" = unsupported; then
+ $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+ build_libtool_libs=no
+ build_old_libs=yes
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag="$no_undefined_flag"
+ fi
+ fi
+
+ if test "$mode" != relink; then
+ # Remove our outputs, but don't remove object files since they
+ # may have been created when compiling PIC objects.
+ removelist=
+ tempremovelist=`$echo "$output_objdir/*"`
+ for p in $tempremovelist; do
+ case $p in
+ *.$objext)
+ ;;
+ $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+ if test "X$precious_files_regex" != "X"; then
+ if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+ then
+ continue
+ fi
+ fi
+ removelist="$removelist $p"
+ ;;
+ *) ;;
+ esac
+ done
+ if test -n "$removelist"; then
+ $show "${rm}r $removelist"
+ $run ${rm}r $removelist
+ fi
+ fi
+
+ # Now set the variables for building old libraries.
+ if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+ oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+ fi
+
+ # Eliminate all temporary directories.
+# for path in $notinst_path; do
+# lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"`
+# deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"`
+# dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"`
+# done
+
+ if test -n "$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ temp_xrpath=
+ for libdir in $xrpath; do
+ temp_xrpath="$temp_xrpath -R$libdir"
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+ fi
+
+ # Make sure dlfiles contains only unique files that won't be dlpreopened
+ old_dlfiles="$dlfiles"
+ dlfiles=
+ for lib in $old_dlfiles; do
+ case " $dlprefiles $dlfiles " in
+ *" $lib "*) ;;
+ *) dlfiles="$dlfiles $lib" ;;
+ esac
+ done
+
+ # Make sure dlprefiles contains only unique files
+ old_dlprefiles="$dlprefiles"
+ dlprefiles=
+ for lib in $old_dlprefiles; do
+ case "$dlprefiles " in
+ *" $lib "*) ;;
+ *) dlprefiles="$dlprefiles $lib" ;;
+ esac
+ done
+
+ if test "$build_libtool_libs" = yes; then
+ if test -n "$rpath"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C library is in the System framework
+ deplibs="$deplibs -framework System"
+ ;;
+ *-*-netbsd*)
+ # Don't link with libc until the a.out ld.so is fixed.
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc due to us having libc/libc_r.
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ ;;
+ *)
+ # Add libc to deplibs on all other systems if necessary.
+ if test "$build_libtool_need_lc" = "yes"; then
+ deplibs="$deplibs -lc"
+ fi
+ ;;
+ esac
+ fi
+
+ # Transform deplibs into only deplibs that can be linked in shared.
+ name_save=$name
+ libname_save=$libname
+ release_save=$release
+ versuffix_save=$versuffix
+ major_save=$major
+ # I'm not sure if I'm treating the release correctly. I think
+ # release should show up in the -l (ie -lgmp5) so we don't want to
+ # add it in twice. Is that correct?
+ release=""
+ versuffix=""
+ major=""
+ newdeplibs=
+ droppeddeps=no
+ case $deplibs_check_method in
+ pass_all)
+ # Don't check for shared/static. Everything works.
+ # This might be a little naive. We might want to check
+ # whether the library exists or not. But this is on
+ # osf3 & osf4 and I'm not really sure... Just
+ # implementing what was already the behavior.
+ newdeplibs=$deplibs
+ ;;
+ test_compile)
+ # This code stresses the "libraries are programs" paradigm to its
+ # limits. Maybe even breaks it. We compile a program, linking it
+ # against the deplibs as a proxy for the library. Then we can check
+ # whether they linked in statically or dynamically with ldd.
+ $rm conftest.c
+ cat > conftest.c <<EOF
+ int main() { return 0; }
+EOF
+ $rm conftest
+ if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ name=`expr $i : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" != "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: dynamic linker does not accept needed library $i."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which I believe you do not have"
+ $echo "*** because a test_compile did reveal that the linker did not use it for"
+ $echo "*** its dynamic dependency list that programs get resolved with at runtime."
+ fi
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ else
+ # Error occurred in the first compile. Let's try to salvage
+ # the situation: Compile a separate program for each library.
+ for i in $deplibs; do
+ name=`expr $i : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" != "0"; then
+ $rm conftest
+ if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+ ldd_output=`ldd conftest`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: dynamic linker does not accept needed library $i."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because a test_compile did reveal that the linker did not use this one"
+ $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+ fi
+ fi
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning! Library $i is needed by this library but I was not able to"
+ $echo "*** make it link in! You will probably need to install it or some"
+ $echo "*** library that it depends on before this library will be fully"
+ $echo "*** functional. Installing it before continuing would be even better."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method
+ file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ for a_deplib in $deplibs; do
+ name=`expr $a_deplib : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" != "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ # Follow soft links.
+ if ls -lLd "$potent_lib" 2>/dev/null \
+ | grep " -> " >/dev/null; then
+ continue
+ fi
+ # The statement above tries to avoid entering an
+ # endless loop below, in case of cyclic links.
+ # We might still enter an endless loop, since a link
+ # loop can be closed while we follow links,
+ # but so what?
+ potlib="$potent_lib"
+ while test -h "$potlib" 2>/dev/null; do
+ potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+ case $potliblink in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+ *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+ | ${SED} 10q \
+ | $EGREP "$file_magic_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: linker path does not have real file for library $a_deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ $echo "*** with $libname but no candidates were found. (...for file magic test)"
+ else
+ $echo "*** with $libname and none of the candidates passed a file format test"
+ $echo "*** using a file magic. Last file checked: $potlib"
+ fi
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ match_pattern*)
+ set dummy $deplibs_check_method
+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ for a_deplib in $deplibs; do
+ name=`expr $a_deplib : '-l\(.*\)'`
+ # If $name is empty we are operating on a -L argument.
+ if test -n "$name" && test "$name" != "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ potlib="$potent_lib" # see symlink-check above in file_magic test
+ if eval $echo \"$potent_lib\" 2>/dev/null \
+ | ${SED} 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: linker path does not have real file for library $a_deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
+ else
+ $echo "*** with $libname and none of the candidates passed a file format test"
+ $echo "*** using a regex pattern. Last file checked: $potlib"
+ fi
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=""
+ tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+ -e 's/ -[LR][^ ]*//g'`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ for i in $predeps $postdeps ; do
+ # can't use Xsed below, because $i might contain '/'
+ tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
+ done
+ fi
+ if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \
+ | grep . >/dev/null; then
+ $echo
+ if test "X$deplibs_check_method" = "Xnone"; then
+ $echo "*** Warning: inter-library dependencies are not supported in this platform."
+ else
+ $echo "*** Warning: inter-library dependencies are not known to be supported."
+ fi
+ $echo "*** All declared inter-library dependencies are being dropped."
+ droppeddeps=yes
+ fi
+ ;;
+ esac
+ versuffix=$versuffix_save
+ major=$major_save
+ release=$release_save
+ libname=$libname_save
+ name=$name_save
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ ;;
+ esac
+
+ if test "$droppeddeps" = yes; then
+ if test "$module" = yes; then
+ $echo
+ $echo "*** Warning: libtool could not satisfy all declared inter-library"
+ $echo "*** dependencies of module $libname. Therefore, libtool will create"
+ $echo "*** a static module, that should work as long as the dlopening"
+ $echo "*** application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ $echo
+ $echo "*** However, this would only work if libtool was able to extract symbol"
+ $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ $echo "*** not find such a program. So, this module is probably useless."
+ $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ else
+ $echo "*** The inter-library dependencies that have been dropped here will be"
+ $echo "*** automatically added whenever a program is linked with this library"
+ $echo "*** or is declared to -dlopen it."
+
+ if test "$allow_undefined" = no; then
+ $echo
+ $echo "*** Since this library must not contain undefined symbols,"
+ $echo "*** because either the platform does not support them or"
+ $echo "*** it was explicitly requested with -no-undefined,"
+ $echo "*** libtool will only create a static version of it."
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ fi
+ fi
+ # Done checking deplibs!
+ deplibs=$newdeplibs
+ fi
+
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $deplibs " in
+ *" -L$path/$objdir "*)
+ new_libs="$new_libs -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ done
+ deplibs="$new_libs"
+
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+
+ # Test again, we may have decided not to build it any more
+ if test "$build_libtool_libs" = yes; then
+ if test "$hardcode_into_libs" = yes; then
+ # Hardcode the library paths
+ hardcode_libdirs=
+ dep_rpath=
+ rpath="$finalize_rpath"
+ test "$mode" != relink && rpath="$compile_rpath$rpath"
+ for libdir in $rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ dep_rpath="$dep_rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ if test -n "$hardcode_libdir_flag_spec_ld"; then
+ eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
+ else
+ eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+ fi
+ fi
+ if test -n "$runpath_var" && test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+ fi
+ test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+ fi
+
+ shlibpath="$finalize_shlibpath"
+ test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+ if test -n "$shlibpath"; then
+ eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+ fi
+
+ # Get the real and link names of the library.
+ eval shared_ext=\"$shrext_cmds\"
+ eval library_names=\"$library_names_spec\"
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+
+ if test -n "$soname_spec"; then
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+ if test -z "$dlname"; then
+ dlname=$soname
+ fi
+
+ lib="$output_objdir/$realname"
+ linknames=
+ for link
+ do
+ linknames="$linknames $link"
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ cmds=$export_symbols_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ if len=`expr "X$cmd" : ".*"` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ skipped_export=false
+ else
+ # The command line is too long to execute in one step.
+ $show "using reloadable object file for export list..."
+ skipped_export=:
+ # Break out early, otherwise skipped_export may be
+ # set to false by a later but shorter cmd.
+ break
+ fi
+ done
+ IFS="$save_ifs"
+ if test -n "$export_symbols_regex"; then
+ $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+ $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+ $run eval '$mv "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+ fi
+
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+ fi
+
+ tmp_deplibs=
+ for test_deplib in $deplibs; do
+ case " $convenience " in
+ *" $test_deplib "*) ;;
+ *)
+ tmp_deplibs="$tmp_deplibs $test_deplib"
+ ;;
+ esac
+ done
+ deplibs="$tmp_deplibs"
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ libobjs="$libobjs $func_extract_archives_result"
+ fi
+ fi
+
+ if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ linker_flags="$linker_flags $flag"
+ fi
+
+ # Make a backup of the uninstalled library when relinking
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
+ fi
+
+ # Do each of the archive commands.
+ if test "$module" = yes && test -n "$module_cmds" ; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ eval test_cmds=\"$module_expsym_cmds\"
+ cmds=$module_expsym_cmds
+ else
+ eval test_cmds=\"$module_cmds\"
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval test_cmds=\"$archive_expsym_cmds\"
+ cmds=$archive_expsym_cmds
+ else
+ eval test_cmds=\"$archive_cmds\"
+ cmds=$archive_cmds
+ fi
+ fi
+
+ if test "X$skipped_export" != "X:" &&
+ len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ :
+ else
+ # The command line is too long to link in one step, link piecewise.
+ $echo "creating reloadable object files..."
+
+ # Save the value of $output and $libobjs because we want to
+ # use them later. If we have whole_archive_flag_spec, we
+ # want to use save_libobjs as it was before
+ # whole_archive_flag_spec was expanded, because we can't
+ # assume the linker understands whole_archive_flag_spec.
+ # This may have to be revisited, in case too many
+ # convenience libraries get linked in and end up exceeding
+ # the spec.
+ if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ fi
+ save_output=$output
+ output_la=`$echo "X$output" | $Xsed -e "$basename"`
+
+ # Clear the reloadable object creation command queue and
+ # initialize k to one.
+ test_cmds=
+ concat_cmds=
+ objlist=
+ delfiles=
+ last_robj=
+ k=1
+ output=$output_objdir/$output_la-${k}.$objext
+ # Loop over the list of objects to be linked.
+ for obj in $save_libobjs
+ do
+ eval test_cmds=\"$reload_cmds $objlist $last_robj\"
+ if test "X$objlist" = X ||
+ { len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+ test "$len" -le "$max_cmd_len"; }; then
+ objlist="$objlist $obj"
+ else
+ # The command $test_cmds is almost too long, add a
+ # command to the queue.
+ if test "$k" -eq 1 ; then
+ # The first file doesn't have a previous command to add.
+ eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+ else
+ # All subsequent reloadable object files will link in
+ # the last one created.
+ eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
+ fi
+ last_robj=$output_objdir/$output_la-${k}.$objext
+ k=`expr $k + 1`
+ output=$output_objdir/$output_la-${k}.$objext
+ objlist=$obj
+ len=1
+ fi
+ done
+ # Handle the remaining objects by creating one last
+ # reloadable object file. All subsequent reloadable object
+ # files will link in the last one created.
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+
+ if ${skipped_export-false}; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ libobjs=$output
+ # Append the command to create the export file.
+ eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
+ fi
+
+ # Set up a command to remove the reloadable object files
+ # after they are used.
+ i=0
+ while test "$i" -lt "$k"
+ do
+ i=`expr $i + 1`
+ delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
+ done
+
+ $echo "creating a temporary reloadable object file: $output"
+
+ # Loop through the commands generated above and execute them.
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $concat_cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ libobjs=$output
+ # Restore the value of output.
+ output=$save_output
+
+ if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ fi
+ # Expand the library linking commands again to reset the
+ # value of $libobjs for piecewise linking.
+
+ # Do each of the archive commands.
+ if test "$module" = yes && test -n "$module_cmds" ; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ cmds=$module_expsym_cmds
+ else
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ cmds=$archive_expsym_cmds
+ else
+ cmds=$archive_cmds
+ fi
+ fi
+
+ # Append the command to remove the reloadable object files
+ # to the just-reset $cmds.
+ eval cmds=\"\$cmds~\$rm $delfiles\"
+ fi
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS="$save_ifs"
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+
+ if test -n "$convenience"; then
+ if test -z "$whole_archive_flag_spec"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ fi
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ # Create links to the real library.
+ for linkname in $linknames; do
+ if test "$realname" != "$linkname"; then
+ $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+ fi
+ done
+
+ # If -module or -export-dynamic was specified, set the dlname.
+ if test "$module" = yes || test "$export_dynamic" = yes; then
+ # On all known operating systems, these are identical.
+ dlname="$soname"
+ fi
+ fi
+ ;;
+
+ obj)
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+ fi
+
+ case $output in
+ *.lo)
+ if test -n "$objs$old_deplibs"; then
+ $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ libobj="$output"
+ obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+ ;;
+ *)
+ libobj=
+ obj="$output"
+ ;;
+ esac
+
+ # Delete the old objects.
+ $run $rm $obj $libobj
+
+ # Objects from convenience libraries. This assumes
+ # single-version convenience libraries. Whenever we create
+ # different ones for PIC/non-PIC, this we'll have to duplicate
+ # the extraction.
+ reload_conv_objs=
+ gentop=
+ # reload_cmds runs $LD directly, so let us get rid of
+ # -Wl from whole_archive_flag_spec and hope we can get by with
+ # turning comma into space..
+ wl=
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+ reload_conv_objs=$reload_objs\ `$echo "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'`
+ else
+ gentop="$output_objdir/${obj}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ reload_conv_objs="$reload_objs $func_extract_archives_result"
+ fi
+ fi
+
+ # Create the old-style object.
+ reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+ output="$obj"
+ cmds=$reload_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Exit if we aren't doing a library object file.
+ if test -z "$libobj"; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ if test "$build_libtool_libs" != yes; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ # $show "echo timestamp > $libobj"
+ # $run eval "echo timestamp > $libobj" || exit $?
+ exit $EXIT_SUCCESS
+ fi
+
+ if test -n "$pic_flag" || test "$pic_mode" != default; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs $reload_conv_objs"
+ output="$libobj"
+ cmds=$reload_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ prog)
+ case $host in
+ *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
+ esac
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+ fi
+
+ if test "$preload" = yes; then
+ if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
+ test "$dlopen_self_static" = unknown; then
+ $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+ fi
+ fi
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ ;;
+ esac
+
+ case $host in
+ *darwin*)
+ # Don't allow lazy linking, it breaks C++ global constructors
+ if test "$tagname" = CXX ; then
+ compile_command="$compile_command ${wl}-bind_at_load"
+ finalize_command="$finalize_command ${wl}-bind_at_load"
+ fi
+ ;;
+ esac
+
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $compile_deplibs " in
+ *" -L$path/$objdir "*)
+ new_libs="$new_libs -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $compile_deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ done
+ compile_deplibs="$new_libs"
+
+
+ compile_command="$compile_command $compile_deplibs"
+ finalize_command="$finalize_command $finalize_deplibs"
+
+ if test -n "$rpath$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath $xrpath; do
+ # This is the magic to use -rpath.
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ fi
+
+ # Now hardcode the library paths
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$libdir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$libdir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$testbindir";;
+ esac
+ ;;
+ esac
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ compile_rpath="$rpath"
+
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ finalize_rpath="$rpath"
+
+ if test -n "$libobjs" && test "$build_old_libs" = yes; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ fi
+
+ dlsyms=
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ if test -n "$NM" && test -n "$global_symbol_pipe"; then
+ dlsyms="${outputname}S.c"
+ else
+ $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+ fi
+ fi
+
+ if test -n "$dlsyms"; then
+ case $dlsyms in
+ "") ;;
+ *.c)
+ # Discover the nlist of each of the dlfiles.
+ nlist="$output_objdir/${outputname}.nm"
+
+ $show "$rm $nlist ${nlist}S ${nlist}T"
+ $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+ # Parse the name list into a source file.
+ $show "creating $output_objdir/$dlsyms"
+
+ test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test "$dlself" = yes; then
+ $show "generating symbol list for \`$output'"
+
+ test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+ # Add our own program objects to the symbol list.
+ progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ for arg in $progfiles; do
+ $show "extracting global C symbols from \`$arg'"
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -n "$exclude_expsyms"; then
+ $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ if test -n "$export_symbols_regex"; then
+ $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ export_symbols="$output_objdir/$outputname.exp"
+ $run $rm $export_symbols
+ $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ case $host in
+ *cygwin* | *mingw* )
+ $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ else
+ $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+ $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+ $run eval 'mv "$nlist"T "$nlist"'
+ case $host in
+ *cygwin* | *mingw* )
+ $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ fi
+ fi
+
+ for arg in $dlprefiles; do
+ $show "extracting global C symbols from \`$arg'"
+ name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
+ $run eval '$echo ": $name " >> "$nlist"'
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -z "$run"; then
+ # Make sure we have at least an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ if test -n "$exclude_expsyms"; then
+ $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+ $mv "$nlist"T "$nlist"
+ fi
+
+ # Try sorting and uniquifying the output.
+ if grep -v "^: " < "$nlist" |
+ if sort -k 3 </dev/null >/dev/null 2>&1; then
+ sort -k 3
+ else
+ sort +2
+ fi |
+ uniq > "$nlist"S; then
+ :
+ else
+ grep -v "^: " < "$nlist" > "$nlist"S
+ fi
+
+ if test -f "$nlist"S; then
+ eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+ else
+ $echo '/* NONE */' >> "$output_objdir/$dlsyms"
+ fi
+
+ $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+"
+
+ case $host in
+ *cygwin* | *mingw* )
+ $echo >> "$output_objdir/$dlsyms" "\
+/* DATA imports from DLLs on WIN32 can't be const, because
+ runtime relocations are performed -- see ld's documentation
+ on pseudo-relocs */
+struct {
+"
+ ;;
+ * )
+ $echo >> "$output_objdir/$dlsyms" "\
+const struct {
+"
+ ;;
+ esac
+
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ const char *name;
+ lt_ptr address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+ eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ {0, (lt_ptr) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+ fi
+
+ pic_flag_for_symtable=
+ case $host in
+ # compiling the symbol table file with pic_flag works around
+ # a FreeBSD bug that causes programs to crash when -lm is
+ # linked before any other PIC object. But we must not use
+ # pic_flag when linking with -static. The problem exists in
+ # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+ *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
+ esac;;
+ *-*-hpux*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag";;
+ esac
+ esac
+
+ # Now compile the dynamic symbol file.
+ $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+ $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+ # Clean up the generated files.
+ $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+ $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+ # Transform the symbol file into the correct name.
+ case $host in
+ *cygwin* | *mingw* )
+ if test -f "$output_objdir/${outputname}.def" ; then
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ else
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ fi
+ ;;
+ * )
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+ ;;
+ esac
+ ;;
+ *)
+ $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ else
+ # We keep going just in case the user didn't refer to
+ # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+
+ # Nullify the symbol file.
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP`
+ fi
+
+ if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+ # Replace the output file specification.
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$output"'%g' | $NL2SP`
+ link_command="$compile_command$compile_rpath"
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ $show "$link_command"
+ $run eval "$link_command"
+ exit_status=$?
+
+ # Delete the generated files.
+ if test -n "$dlsyms"; then
+ $show "$rm $output_objdir/${outputname}S.${objext}"
+ $run $rm "$output_objdir/${outputname}S.${objext}"
+ fi
+
+ exit $exit_status
+ fi
+
+ if test -n "$shlibpath_var"; then
+ # We should set the shlibpath_var
+ rpath=
+ for dir in $temp_rpath; do
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*)
+ # Absolute path.
+ rpath="$rpath$dir:"
+ ;;
+ *)
+ # Relative path: add a thisdir entry.
+ rpath="$rpath\$thisdir/$dir:"
+ ;;
+ esac
+ done
+ temp_rpath="$rpath"
+ fi
+
+ if test -n "$compile_shlibpath$finalize_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ compile_var=
+ finalize_var=
+ if test -n "$runpath_var"; then
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ if test -n "$finalize_perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $finalize_perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test "$no_install" = yes; then
+ # We don't need to create a wrapper script.
+ link_command="$compile_var$compile_command$compile_rpath"
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ # Delete the old output file.
+ $run $rm $output
+ # Link the executable and exit
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+ exit $EXIT_SUCCESS
+ fi
+
+ if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+ $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+ $echo "$modename: \`$output' will be relinked during installation" 1>&2
+ else
+ if test "$fast_install" != no; then
+ link_command="$finalize_var$compile_command$finalize_rpath"
+ if test "$fast_install" = yes; then
+ relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $SP2NL | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g' | $NL2SP`
+ else
+ # fast_install is set to needless
+ relink_command=
+ fi
+ else
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+ fi
+ fi
+
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+ # Delete the old output files.
+ $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+
+ # Now create the wrapper script.
+ $show "creating $output"
+
+ # Quote the relink command for shipping.
+ if test -n "$relink_command"; then
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ relink_command="(cd `pwd`; $relink_command)"
+ relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP`
+ fi
+
+ # Quote $echo for shipping.
+ if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then
+ case $progpath in
+ [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
+ *) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
+ esac
+ qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+ else
+ qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Only actually do things if our run command is non-null.
+ if test -z "$run"; then
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+ *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
+ esac
+ # test for cygwin because mv fails w/o .exe extensions
+ case $host in
+ *cygwin*)
+ exeext=.exe
+ outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
+ *) exeext= ;;
+ esac
+ case $host in
+ *cygwin* | *mingw* )
+ output_name=`basename $output`
+ output_path=`dirname $output`
+ cwrappersource="$output_path/$objdir/lt-$output_name.c"
+ cwrapper="$output_path/$output_name.exe"
+ $rm $cwrappersource $cwrapper
+ trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+ cat > $cwrappersource <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+ Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+
+ The $output program cannot be directly executed until all the libtool
+ libraries that it depends on are installed.
+
+ This wrapper executable should never be moved out of the build directory.
+ If it is, it will not operate correctly.
+
+ Currently, it simply execs the wrapper *script* "/bin/sh $output",
+ but could eventually absorb all of the scripts functionality and
+ exec $objdir/$outputname directly.
+*/
+EOF
+ cat >> $cwrappersource<<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+ defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# ifndef DIR_SEPARATOR_2
+# define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+# define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+ if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+/* -DDEBUG is fairly common in CFLAGS. */
+#undef DEBUG
+#if defined DEBUGWRAPPER
+# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__)
+#else
+# define DEBUG(format, ...)
+#endif
+
+const char *program_name = NULL;
+
+void * xmalloc (size_t num);
+char * xstrdup (const char *string);
+const char * base_name (const char *name);
+char * find_executable(const char *wrapper);
+int check_executable(const char *path);
+char * strendzap(char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+
+int
+main (int argc, char *argv[])
+{
+ char **newargz;
+ int i;
+
+ program_name = (char *) xstrdup (base_name (argv[0]));
+ DEBUG("(main) argv[0] : %s\n",argv[0]);
+ DEBUG("(main) program_name : %s\n",program_name);
+ newargz = XMALLOC(char *, argc+2);
+EOF
+
+ cat >> $cwrappersource <<EOF
+ newargz[0] = (char *) xstrdup("$SHELL");
+EOF
+
+ cat >> $cwrappersource <<"EOF"
+ newargz[1] = find_executable(argv[0]);
+ if (newargz[1] == NULL)
+ lt_fatal("Couldn't find %s", argv[0]);
+ DEBUG("(main) found exe at : %s\n",newargz[1]);
+ /* we know the script has the same name, without the .exe */
+ /* so make sure newargz[1] doesn't end in .exe */
+ strendzap(newargz[1],".exe");
+ for (i = 1; i < argc; i++)
+ newargz[i+1] = xstrdup(argv[i]);
+ newargz[argc+1] = NULL;
+
+ for (i=0; i<argc+1; i++)
+ {
+ DEBUG("(main) newargz[%d] : %s\n",i,newargz[i]);
+ ;
+ }
+
+EOF
+
+ case $host_os in
+ mingw*)
+ cat >> $cwrappersource <<EOF
+ execv("$SHELL",(char const **)newargz);
+EOF
+ ;;
+ *)
+ cat >> $cwrappersource <<EOF
+ execv("$SHELL",newargz);
+EOF
+ ;;
+ esac
+
+ cat >> $cwrappersource <<"EOF"
+ return 127;
+}
+
+void *
+xmalloc (size_t num)
+{
+ void * p = (void *) malloc (num);
+ if (!p)
+ lt_fatal ("Memory exhausted");
+
+ return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+ return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
+;
+}
+
+const char *
+base_name (const char *name)
+{
+ const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ /* Skip over the disk name in MSDOS pathnames. */
+ if (isalpha ((unsigned char)name[0]) && name[1] == ':')
+ name += 2;
+#endif
+
+ for (base = name; *name; name++)
+ if (IS_DIR_SEPARATOR (*name))
+ base = name + 1;
+ return base;
+}
+
+int
+check_executable(const char * path)
+{
+ struct stat st;
+
+ DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
+ if ((!path) || (!*path))
+ return 0;
+
+ if ((stat (path, &st) >= 0) &&
+ (
+ /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */
+#if defined (S_IXOTH)
+ ((st.st_mode & S_IXOTH) == S_IXOTH) ||
+#endif
+#if defined (S_IXGRP)
+ ((st.st_mode & S_IXGRP) == S_IXGRP) ||
+#endif
+ ((st.st_mode & S_IXUSR) == S_IXUSR))
+ )
+ return 1;
+ else
+ return 0;
+}
+
+/* Searches for the full path of the wrapper. Returns
+ newly allocated full path name if found, NULL otherwise */
+char *
+find_executable (const char* wrapper)
+{
+ int has_slash = 0;
+ const char* p;
+ const char* p_next;
+ /* static buffer for getcwd */
+ char tmp[LT_PATHMAX + 1];
+ int tmp_len;
+ char* concat_name;
+
+ DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!");
+
+ if ((wrapper == NULL) || (*wrapper == '\0'))
+ return NULL;
+
+ /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':')
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ }
+ else
+ {
+#endif
+ if (IS_DIR_SEPARATOR (wrapper[0]))
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ }
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ }
+#endif
+
+ for (p = wrapper; *p; p++)
+ if (*p == '/')
+ {
+ has_slash = 1;
+ break;
+ }
+ if (!has_slash)
+ {
+ /* no slashes; search PATH */
+ const char* path = getenv ("PATH");
+ if (path != NULL)
+ {
+ for (p = path; *p; p = p_next)
+ {
+ const char* q;
+ size_t p_len;
+ for (q = p; *q; q++)
+ if (IS_PATH_SEPARATOR(*q))
+ break;
+ p_len = q - p;
+ p_next = (*q == '\0' ? q : q + 1);
+ if (p_len == 0)
+ {
+ /* empty path: current directory */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal ("getcwd failed");
+ tmp_len = strlen(tmp);
+ concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+ }
+ else
+ {
+ concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1);
+ memcpy (concat_name, p, p_len);
+ concat_name[p_len] = '/';
+ strcpy (concat_name + p_len + 1, wrapper);
+ }
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ }
+ }
+ /* not found in PATH; assume curdir */
+ }
+ /* Relative path | not found in path: prepend cwd */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal ("getcwd failed");
+ tmp_len = strlen(tmp);
+ concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+
+ if (check_executable(concat_name))
+ return concat_name;
+ XFREE(concat_name);
+ return NULL;
+}
+
+char *
+strendzap(char *str, const char *pat)
+{
+ size_t len, patlen;
+
+ assert(str != NULL);
+ assert(pat != NULL);
+
+ len = strlen(str);
+ patlen = strlen(pat);
+
+ if (patlen <= len)
+ {
+ str += len - patlen;
+ if (strcmp(str, pat) == 0)
+ *str = '\0';
+ }
+ return str;
+}
+
+static void
+lt_error_core (int exit_status, const char * mode,
+ const char * message, va_list ap)
+{
+ fprintf (stderr, "%s: %s: ", program_name, mode);
+ vfprintf (stderr, message, ap);
+ fprintf (stderr, ".\n");
+
+ if (exit_status >= 0)
+ exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+ va_list ap;
+ va_start (ap, message);
+ lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+ va_end (ap);
+}
+EOF
+ # we should really use a build-platform specific compiler
+ # here, but OTOH, the wrappers (shell script and this C one)
+ # are only useful if you want to execute the "real" binary.
+ # Since the "real" binary is built for $host, then this
+ # wrapper might as well be built for $host, too.
+ $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource
+ ;;
+ esac
+ $rm $output
+ trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
+
+ $echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='${SED} -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+ # install mode needs the following variable:
+ notinst_deplibs='$notinst_deplibs'
+else
+ # When we are sourced in execute mode, \$file and \$echo are already set.
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ echo=\"$qecho\"
+ file=\"\$0\"
+ # Make sure echo works.
+ if test \"X\$1\" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+ elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+ # Yippee, \$echo works!
+ :
+ else
+ # Restart under the correct shell, and then maybe \$echo will work.
+ exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+ fi
+ fi\
+"
+ $echo >> $output "\
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test \"x\$destdir\" != \"x\$file\"; then
+ case \"\$destdir\" in
+ [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+ *) thisdir=\"\$thisdir/\$destdir\" ;;
+ esac
+ fi
+
+ file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+ done
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test "$fast_install" = yes; then
+ $echo >> $output "\
+ program=lt-'$outputname'$exeext
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" || \\
+ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+
+ if test ! -d \"\$progdir\"; then
+ $mkdir \"\$progdir\"
+ else
+ $rm \"\$progdir/\$file\"
+ fi"
+
+ $echo >> $output "\
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+ if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+ else
+ $echo \"\$relink_command_output\" >&2
+ $rm \"\$progdir/\$file\"
+ exit $EXIT_FAILURE
+ fi
+ fi
+
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+ { $rm \"\$progdir/\$program\";
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+ $rm \"\$progdir/\$file\"
+ fi"
+ else
+ $echo >> $output "\
+ program='$outputname'
+ progdir=\"\$thisdir/$objdir\"
+"
+ fi
+
+ $echo >> $output "\
+
+ if test -f \"\$progdir/\$program\"; then"
+
+ # Export our shlibpath_var if we have one.
+ if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ $echo >> $output "\
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ # The second colon is a workaround for a bug in BeOS R4 sed
+ $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ # fixup the dll searchpath if we need to.
+ if test -n "$dllsearchpath"; then
+ $echo >> $output "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ $echo >> $output "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+"
+ case $host in
+ # Backslashes separate directories on plain windows
+ *-*-mingw | *-*-os2*)
+ $echo >> $output "\
+ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+ ;;
+
+ *)
+ $echo >> $output "\
+ exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $echo >> $output "\
+ \$echo \"\$0: cannot exec \$program \$*\"
+ exit $EXIT_FAILURE
+ fi
+ else
+ # The program doesn't exist.
+ \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+ \$echo \"This script is just a wrapper for \$program.\" 1>&2
+ $echo \"See the $PACKAGE documentation for more information.\" 1>&2
+ exit $EXIT_FAILURE
+ fi
+fi\
+"
+ chmod +x $output
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+ esac
+
+ # See if we need to build an old-fashioned archive.
+ for oldlib in $oldlibs; do
+
+ if test "$build_libtool_libs" = convenience; then
+ oldobjs="$libobjs_save"
+ addlibs="$convenience"
+ build_libtool_libs=no
+ else
+ if test "$build_libtool_libs" = module; then
+ oldobjs="$libobjs_save"
+ build_libtool_libs=no
+ else
+ oldobjs="$old_deplibs $non_pic_objects"
+ fi
+ addlibs="$old_convenience"
+ fi
+
+ if test -n "$addlibs"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $addlibs
+ oldobjs="$oldobjs $func_extract_archives_result"
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+ cmds=$old_archive_from_new_cmds
+ else
+ # POSIX demands no paths to be encoded in archives. We have
+ # to avoid creating archives with duplicate basenames if we
+ # might have to extract them afterwards, e.g., when creating a
+ # static archive out of a convenience library, or when linking
+ # the entirety of a libtool archive into another (currently
+ # not supported by libtool).
+ if (for obj in $oldobjs
+ do
+ $echo "X$obj" | $Xsed -e 's%^.*/%%'
+ done | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "copying selected object files to avoid basename conflicts..."
+
+ if test -z "$gentop"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "$mkdir $gentop"
+ $run $mkdir "$gentop"
+ exit_status=$?
+ if test "$exit_status" -ne 0 && test ! -d "$gentop"; then
+ exit $exit_status
+ fi
+ fi
+
+ save_oldobjs=$oldobjs
+ oldobjs=
+ counter=1
+ for obj in $save_oldobjs
+ do
+ objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+ case " $oldobjs " in
+ " ") oldobjs=$obj ;;
+ *[\ /]"$objbase "*)
+ while :; do
+ # Make sure we don't pick an alternate name that also
+ # overlaps.
+ newobj=lt$counter-$objbase
+ counter=`expr $counter + 1`
+ case " $oldobjs " in
+ *[\ /]"$newobj "*) ;;
+ *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+ esac
+ done
+ $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+ $run ln "$obj" "$gentop/$newobj" ||
+ $run cp "$obj" "$gentop/$newobj"
+ oldobjs="$oldobjs $gentop/$newobj"
+ ;;
+ *) oldobjs="$oldobjs $obj" ;;
+ esac
+ done
+ fi
+
+ eval cmds=\"$old_archive_cmds\"
+
+ if len=`expr "X$cmds" : ".*"` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ cmds=$old_archive_cmds
+ else
+ # the command line is too long to link in one step, link in parts
+ $echo "using piecewise archive linking..."
+ save_RANLIB=$RANLIB
+ RANLIB=:
+ objlist=
+ concat_cmds=
+ save_oldobjs=$oldobjs
+
+ # Is there a better way of finding the last object in the list?
+ for obj in $save_oldobjs
+ do
+ last_oldobj=$obj
+ done
+ for obj in $save_oldobjs
+ do
+ oldobjs="$objlist $obj"
+ objlist="$objlist $obj"
+ eval test_cmds=\"$old_archive_cmds\"
+ if len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+ test "$len" -le "$max_cmd_len"; then
+ :
+ else
+ # the above command should be used before it gets too long
+ oldobjs=$objlist
+ if test "$obj" = "$last_oldobj" ; then
+ RANLIB=$save_RANLIB
+ fi
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+ objlist=
+ fi
+ done
+ RANLIB=$save_RANLIB
+ oldobjs=$objlist
+ if test "X$oldobjs" = "X" ; then
+ eval cmds=\"\$concat_cmds\"
+ else
+ eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+ fi
+ fi
+ fi
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ eval cmd=\"$cmd\"
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$generated"; then
+ $show "${rm}r$generated"
+ $run ${rm}r$generated
+ fi
+
+ # Now create the libtool archive.
+ case $output in
+ *.la)
+ old_library=
+ test "$build_old_libs" = yes && old_library="$libname.$libext"
+ $show "creating $output"
+
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ # Quote the link command for shipping.
+ relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+ relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP`
+ if test "$hardcode_automatic" = yes ; then
+ relink_command=
+ fi
+
+
+ # Only create the output if not a dry run.
+ if test -z "$run"; then
+ for installed in no yes; do
+ if test "$installed" = yes; then
+ if test -z "$install_libdir"; then
+ break
+ fi
+ output="$output_objdir/$outputname"i
+ # Replace all uninstalled libtool libraries with the installed ones
+ newdependency_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ *.la)
+ name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdependency_libs="$newdependency_libs $libdir/$name"
+ ;;
+ *) newdependency_libs="$newdependency_libs $deplib" ;;
+ esac
+ done
+ dependency_libs="$newdependency_libs"
+ newdlfiles=
+ for lib in $dlfiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdlfiles="$newdlfiles $libdir/$name"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdlprefiles="$newdlprefiles $libdir/$name"
+ done
+ dlprefiles="$newdlprefiles"
+ else
+ newdlfiles=
+ for lib in $dlfiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ newdlfiles="$newdlfiles $abs"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ newdlprefiles="$newdlprefiles $abs"
+ done
+ dlprefiles="$newdlprefiles"
+ fi
+ $rm $output
+ # place dlname in correct position for cygwin
+ tdlname=$dlname
+ case $host,$output,$installed,$module,$dlname in
+ *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+ esac
+ $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+ if test "$installed" = no && test "$need_relink" = yes; then
+ $echo >> $output "\
+relink_command=\"$relink_command\""
+ fi
+ done
+ fi
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+ $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
+ ;;
+ esac
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool install mode
+ install)
+ modename="$modename: install"
+
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+ # Allow the use of GNU shtool's install command.
+ $echo "X$nonopt" | grep shtool > /dev/null; then
+ # Aesthetically quote it.
+ arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$arg "
+ arg="$1"
+ shift
+ else
+ install_prog=
+ arg=$nonopt
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog$arg"
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=no
+ stripme=
+ for arg
+ do
+ if test -n "$dest"; then
+ files="$files $dest"
+ dest=$arg
+ continue
+ fi
+
+ case $arg in
+ -d) isdir=yes ;;
+ -f)
+ case " $install_prog " in
+ *[\\\ /]cp\ *) ;;
+ *) prev=$arg ;;
+ esac
+ ;;
+ -g | -m | -o) prev=$arg ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*)
+ ;;
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ prev=
+ else
+ dest=$arg
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog $arg"
+ done
+
+ if test -z "$install_prog"; then
+ $echo "$modename: you must specify an install program" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prev' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ $echo "$modename: no file or destination specified" 1>&2
+ else
+ $echo "$modename: you must specify a destination" 1>&2
+ fi
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Strip any trailing slash from the destination.
+ dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=yes
+ if test "$isdir" = yes; then
+ destdir="$dest"
+ destname=
+ else
+ destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$destdir" = "X$dest" && destdir=.
+ destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files
+ if test "$#" -gt 2; then
+ $echo "$modename: \`$dest' is not a directory" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ fi
+ case $destdir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ for file in $files; do
+ case $file in
+ *.lo) ;;
+ *)
+ $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case $file in
+ *.$libext)
+ # Do the static libraries later.
+ staticlibs="$staticlibs $file"
+ ;;
+
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ library_names=
+ old_library=
+ relink_command=
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) current_libdirs="$current_libdirs $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) future_libdirs="$future_libdirs $libdir" ;;
+ esac
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
+ test "X$dir" = "X$file/" && dir=
+ dir="$dir$objdir"
+
+ if test -n "$relink_command"; then
+ # Determine the prefix the user has applied to our future dir.
+ inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
+ # are installed to the same prefix.
+ # At present, this check doesn't affect windows .dll's that
+ # are installed into $libdir/../bin (currently, that works fine)
+ # but it's something to keep an eye on.
+ if test "$inst_prefix_dir" = "$destdir"; then
+ $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$inst_prefix_dir"; then
+ # Stick the inst_prefix_dir data into the link command.
+ relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%" | $NL2SP`
+ else
+ relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%%" | $NL2SP`
+ fi
+
+ $echo "$modename: warning: relinking \`$file'" 1>&2
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ fi
+
+ # See the names of the shared library.
+ set dummy $library_names
+ if test -n "$2"; then
+ realname="$2"
+ shift
+ shift
+
+ srcname="$realname"
+ test -n "$relink_command" && srcname="$realname"T
+
+ # Install the shared library and build the symlinks.
+ $show "$install_prog $dir/$srcname $destdir/$realname"
+ $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
+ if test -n "$stripme" && test -n "$striplib"; then
+ $show "$striplib $destdir/$realname"
+ $run eval "$striplib $destdir/$realname" || exit $?
+ fi
+
+ if test "$#" -gt 0; then
+ # Delete the old symlinks, and create new ones.
+ # Try `ln -sf' first, because the `ln' binary might depend on
+ # the symlink we replace! Solaris /bin/ln does not understand -f,
+ # so we also need to try rm && ln -s.
+ for linkname
+ do
+ if test "$linkname" != "$realname"; then
+ $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+ $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+ fi
+ done
+ fi
+
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ cmds=$postinstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Install the pseudo-library for information purposes.
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ instname="$dir/$name"i
+ $show "$install_prog $instname $destdir/$name"
+ $run eval "$install_prog $instname $destdir/$name" || exit $?
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case $destfile in
+ *.lo)
+ staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+ ;;
+ *.$objext)
+ staticdest="$destfile"
+ destfile=
+ ;;
+ *)
+ $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ if test -n "$destfile"; then
+ $show "$install_prog $file $destfile"
+ $run eval "$install_prog $file $destfile" || exit $?
+ fi
+
+ # Install the old object if enabled.
+ if test "$build_old_libs" = yes; then
+ # Deduce the name of the old-style object file.
+ staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+ $show "$install_prog $staticobj $staticdest"
+ $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+
+ *)
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # If the file is missing, and there is a .exe on the end, strip it
+ # because it is most likely a libtool script we actually want to
+ # install
+ stripped_ext=""
+ case $file in
+ *.exe)
+ if test ! -f "$file"; then
+ file=`$echo $file|${SED} 's,.exe$,,'`
+ stripped_ext=".exe"
+ fi
+ ;;
+ esac
+
+ # Do a test to see if this is really a libtool program.
+ case $host in
+ *cygwin*|*mingw*)
+ wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
+ ;;
+ *)
+ wrapper=$file
+ ;;
+ esac
+ if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
+ notinst_deplibs=
+ relink_command=
+
+ # Note that it is not necessary on cygwin/mingw to append a dot to
+ # foo even if both foo and FILE.exe exist: automatic-append-.exe
+ # behavior happens only for exec(3), not for open(2)! Also, sourcing
+ # `FILE.' does not work on cygwin managed mounts.
+ #
+ # If there is no directory component, then add one.
+ case $wrapper in
+ */* | *\\*) . ${wrapper} ;;
+ *) . ./${wrapper} ;;
+ esac
+
+ # Check the variables that should have been set.
+ if test -z "$notinst_deplibs"; then
+ $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ finalize=yes
+ for lib in $notinst_deplibs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ # If there is no directory component, then add one.
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ fi
+ libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+ finalize=no
+ fi
+ done
+
+ relink_command=
+ # Note that it is not necessary on cygwin/mingw to append a dot to
+ # foo even if both foo and FILE.exe exist: automatic-append-.exe
+ # behavior happens only for exec(3), not for open(2)! Also, sourcing
+ # `FILE.' does not work on cygwin managed mounts.
+ #
+ # If there is no directory component, then add one.
+ case $wrapper in
+ */* | *\\*) . ${wrapper} ;;
+ *) . ./${wrapper} ;;
+ esac
+
+ outputname=
+ if test "$fast_install" = no && test -n "$relink_command"; then
+ if test "$finalize" = yes && test -z "$run"; then
+ tmpdir=`func_mktempdir`
+ file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
+ outputname="$tmpdir/$file"
+ # Replace the output file specification.
+ relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g' | $NL2SP`
+
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ ${rm}r "$tmpdir"
+ continue
+ fi
+ file="$outputname"
+ else
+ $echo "$modename: warning: cannot relink \`$file'" 1>&2
+ fi
+ else
+ # Install the binary that we compiled earlier.
+ file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ # remove .exe since cygwin /usr/bin/install will append another
+ # one anyway
+ case $install_prog,$host in
+ */usr/bin/install*,*cygwin*)
+ case $file:$destfile in
+ *.exe:*.exe)
+ # this is ok
+ ;;
+ *.exe:*)
+ destfile=$destfile.exe
+ ;;
+ *:*.exe)
+ destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
+ ;;
+ esac
+ ;;
+ esac
+ $show "$install_prog$stripme $file $destfile"
+ $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+ test -n "$outputname" && ${rm}r "$tmpdir"
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+ # Set up the ranlib parameters.
+ oldlib="$destdir/$name"
+
+ $show "$install_prog $file $oldlib"
+ $run eval "$install_prog \$file \$oldlib" || exit $?
+
+ if test -n "$stripme" && test -n "$old_striplib"; then
+ $show "$old_striplib $oldlib"
+ $run eval "$old_striplib $oldlib" || exit $?
+ fi
+
+ # Do each command in the postinstall commands.
+ cmds=$old_postinstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$future_libdirs"; then
+ $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+ fi
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ test -n "$run" && current_libdirs=" -n$current_libdirs"
+ exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+ else
+ exit $EXIT_SUCCESS
+ fi
+ ;;
+
+ # libtool finish mode
+ finish)
+ modename="$modename: finish"
+ libdirs="$nonopt"
+ admincmds=
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for dir
+ do
+ libdirs="$libdirs $dir"
+ done
+
+ for libdir in $libdirs; do
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ cmds=$finish_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || admincmds="$admincmds
+ $cmd"
+ done
+ IFS="$save_ifs"
+ fi
+ if test -n "$finish_eval"; then
+ # Do the single finish_eval.
+ eval cmds=\"$finish_eval\"
+ $run eval "$cmds" || admincmds="$admincmds
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ test "$show" = : && exit $EXIT_SUCCESS
+
+ $echo "X----------------------------------------------------------------------" | $Xsed
+ $echo "Libraries have been installed in:"
+ for libdir in $libdirs; do
+ $echo " $libdir"
+ done
+ $echo
+ $echo "If you ever happen to want to link against installed libraries"
+ $echo "in a given directory, LIBDIR, you must either use libtool, and"
+ $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+ $echo "flag during linking and do at least one of the following:"
+ if test -n "$shlibpath_var"; then
+ $echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
+ $echo " during execution"
+ fi
+ if test -n "$runpath_var"; then
+ $echo " - add LIBDIR to the \`$runpath_var' environment variable"
+ $echo " during linking"
+ fi
+ if test -n "$hardcode_libdir_flag_spec"; then
+ libdir=LIBDIR
+ eval flag=\"$hardcode_libdir_flag_spec\"
+
+ $echo " - use the \`$flag' linker flag"
+ fi
+ if test -n "$admincmds"; then
+ $echo " - have your system administrator run these commands:$admincmds"
+ fi
+ if test -f /etc/ld.so.conf; then
+ $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+ fi
+ $echo
+ $echo "See any operating system documentation about shared libraries for"
+ $echo "more information, such as the ld(1) and ld.so(8) manual pages."
+ $echo "X----------------------------------------------------------------------" | $Xsed
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool execute mode
+ execute)
+ modename="$modename: execute"
+
+ # The first argument is the command name.
+ cmd="$nonopt"
+ if test -z "$cmd"; then
+ $echo "$modename: you must specify a COMMAND" 1>&2
+ $echo "$help"
+ exit $EXIT_FAILURE
+ fi
+
+ # Handle -dlopen flags immediately.
+ for file in $execute_dlfiles; do
+ if test ! -f "$file"; then
+ $echo "$modename: \`$file' is not a file" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ dir=
+ case $file in
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+ continue
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+
+ if test -f "$dir/$objdir/$dlname"; then
+ dir="$dir/$objdir"
+ else
+ $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ ;;
+
+ *)
+ $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir="$absdir"
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic="$magic"
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case $file in
+ -*) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+ if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+ args="$args \"$file\""
+ done
+
+ if test -z "$run"; then
+ if test -n "$shlibpath_var"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+ fi
+
+ # Restore saved environment variables
+ for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+ do
+ eval "if test \"\${save_$lt_var+set}\" = set; then
+ $lt_var=\$save_$lt_var; export $lt_var
+ else
+ $lt_unset $lt_var
+ fi"
+ done
+
+
+ # Now prepare to actually exec the command.
+ exec_cmd="\$cmd$args"
+ else
+ # Display what would be done.
+ if test -n "$shlibpath_var"; then
+ eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+ $echo "export $shlibpath_var"
+ fi
+ $echo "$cmd$args"
+ exit $EXIT_SUCCESS
+ fi
+ ;;
+
+ # libtool clean and uninstall mode
+ clean | uninstall)
+ modename="$modename: $mode"
+ rm="$nonopt"
+ files=
+ rmforce=
+ exit_status=0
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ for arg
+ do
+ case $arg in
+ -f) rm="$rm $arg"; rmforce=yes ;;
+ -*) rm="$rm $arg" ;;
+ *) files="$files $arg" ;;
+ esac
+ done
+
+ if test -z "$rm"; then
+ $echo "$modename: you must specify an RM program" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ rmdirs=
+
+ origobjdir="$objdir"
+ for file in $files; do
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$file"; then
+ dir=.
+ objdir="$origobjdir"
+ else
+ objdir="$dir/$origobjdir"
+ fi
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ test "$mode" = uninstall && objdir="$dir"
+
+ # Remember objdir for removal later, being careful to avoid duplicates
+ if test "$mode" = clean; then
+ case " $rmdirs " in
+ *" $objdir "*) ;;
+ *) rmdirs="$rmdirs $objdir" ;;
+ esac
+ fi
+
+ # Don't error if the file doesn't exist and rm -f was used.
+ if (test -L "$file") >/dev/null 2>&1 \
+ || (test -h "$file") >/dev/null 2>&1 \
+ || test -f "$file"; then
+ :
+ elif test -d "$file"; then
+ exit_status=1
+ continue
+ elif test "$rmforce" = yes; then
+ continue
+ fi
+
+ rmfiles="$file"
+
+ case $name in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ . $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ rmfiles="$rmfiles $objdir/$n"
+ done
+ test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+
+ case "$mode" in
+ clean)
+ case " $library_names " in
+ # " " in the beginning catches empty $dlname
+ *" $dlname "*) ;;
+ *) rmfiles="$rmfiles $objdir/$dlname" ;;
+ esac
+ test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+ ;;
+ uninstall)
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ cmds=$postuninstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test "$?" -ne 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ cmds=$old_postuninstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test "$?" -ne 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
+ IFS="$save_ifs"
+ fi
+ # FIXME: should reinstall the best remaining shared library.
+ ;;
+ esac
+ fi
+ ;;
+
+ *.lo)
+ # Possibly a libtool object, so verify it.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+
+ # Read the .lo file
+ . $dir/$name
+
+ # Add PIC object to the list of files to remove.
+ if test -n "$pic_object" \
+ && test "$pic_object" != none; then
+ rmfiles="$rmfiles $dir/$pic_object"
+ fi
+
+ # Add non-PIC object to the list of files to remove.
+ if test -n "$non_pic_object" \
+ && test "$non_pic_object" != none; then
+ rmfiles="$rmfiles $dir/$non_pic_object"
+ fi
+ fi
+ ;;
+
+ *)
+ if test "$mode" = clean ; then
+ noexename=$name
+ case $file in
+ *.exe)
+ file=`$echo $file|${SED} 's,.exe$,,'`
+ noexename=`$echo $name|${SED} 's,.exe$,,'`
+ # $file with .exe has already been added to rmfiles,
+ # add $file without .exe
+ rmfiles="$rmfiles $file"
+ ;;
+ esac
+ # Do a test to see if this is a libtool program.
+ if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ relink_command=
+ . $dir/$noexename
+
+ # note $name still contains .exe if it was in $file originally
+ # as does the version of $file that was added into $rmfiles
+ rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+ if test "$fast_install" = yes && test -n "$relink_command"; then
+ rmfiles="$rmfiles $objdir/lt-$name"
+ fi
+ if test "X$noexename" != "X$name" ; then
+ rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+ fi
+ fi
+ fi
+ ;;
+ esac
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles || exit_status=1
+ done
+ objdir="$origobjdir"
+
+ # Try to remove the ${objdir}s in the directories where we deleted files
+ for dir in $rmdirs; do
+ if test -d "$dir"; then
+ $show "rmdir $dir"
+ $run rmdir $dir >/dev/null 2>&1
+ fi
+ done
+
+ exit $exit_status
+ ;;
+
+ "")
+ $echo "$modename: you must specify a MODE" 1>&2
+ $echo "$generic_help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ if test -z "$exec_cmd"; then
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$generic_help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+fi # test -z "$show_help"
+
+if test -n "$exec_cmd"; then
+ eval exec $exec_cmd
+ exit $EXIT_FAILURE
+fi
+
+# We need to display help for each of the modes.
+case $mode in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+ --config show all configuration variables
+ --debug enable verbose shell tracing
+-n, --dry-run display commands without modifying any files
+ --features display basic configuration information and exit
+ --finish same as \`--mode=finish'
+ --help display this help message and exit
+ --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
+ --quiet same as \`--silent'
+ --silent don't print informational messages
+ --tag=TAG use configuration variables from tag TAG
+ --version print version information
+
+MODE must be one of the following:
+
+ clean remove files from the build directory
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE.
+
+Report bugs to <bug-libtool@gnu.org>."
+ exit $EXIT_SUCCESS
+ ;;
+
+clean)
+ $echo \
+"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+compile)
+ $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+ -o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -prefer-pic try to building PIC objects only
+ -prefer-non-pic try to building non-PIC objects only
+ -static always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+ ;;
+
+execute)
+ $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+ ;;
+
+finish)
+ $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the \`--dry-run' option if you just want to see what would be executed."
+ ;;
+
+install)
+ $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+ ;;
+
+link)
+ $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -avoid-version do not add a version suffix if possible
+ -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -export-symbols SYMFILE
+ try to export only the symbols listed in SYMFILE
+ -export-symbols-regex REGEX
+ try to export only the symbols matching REGEX
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -module build a library that can dlopened
+ -no-fast-install disable the fast-install mode
+ -no-install link a not-installable executable
+ -no-undefined declare that a library does not refer to external symbols
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -objectlist FILE Use a list of object files found in FILE to specify objects
+ -precious-files-regex REGEX
+ don't remove output files matching REGEX
+ -release RELEASE specify package release information
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
+ -static do not do any dynamic linking of uninstalled libtool libraries
+ -static-libtool-libs
+ do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename. Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+ ;;
+
+uninstall)
+ $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+*)
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+esac
+
+$echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit $?
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries. Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them. This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration. But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+disable_libs=shared
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+disable_libs=static
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/missing b/missing
new file mode 100755
index 0000000..894e786
--- /dev/null
+++ b/missing
@@ -0,0 +1,360 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2005-06-08.21
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# 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, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+run=:
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+ configure_ac=configure.ac
+else
+ configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case "$1" in
+--run)
+ # Try to run requested program, and just exit if it succeeds.
+ run=
+ shift
+ "$@" && exit 0
+ # Exit code 63 means version mismatch. This often happens
+ # when the user try to use an ancient version of a tool on
+ # a file that requires a minimum version. In this case we
+ # we should proceed has if the program had been absent, or
+ # if --run hadn't been passed.
+ if test $? = 63; then
+ run=:
+ msg="probably too old"
+ fi
+ ;;
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+ --run try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ help2man touch the output file
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ tar try tar, gnutar, gtar, then tar without non-portable flags
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Send bug reports to <bug-automake@gnu.org>."
+ exit $?
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing $scriptversion (GNU Automake)"
+ exit $?
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+esac
+
+# Now exit if we have it, but it failed. Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program).
+case "$1" in
+ lex|yacc)
+ # Not GNU programs, they don't have --version.
+ ;;
+
+ tar)
+ if test -n "$run"; then
+ echo 1>&2 "ERROR: \`tar' requires --run"
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ exit 1
+ fi
+ ;;
+
+ *)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ # Could not run --version or --help. This is probably someone
+ # running `$TOOL --version' or `$TOOL --help' to check whether
+ # $TOOL exists and not knowing $TOOL uses missing.
+ exit 1
+ fi
+ ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case "$1" in
+ aclocal*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acinclude.m4' or \`${configure_ac}'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`${configure_ac}'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acconfig.h' or \`${configure_ac}'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case "$f" in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ autom4te)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them.
+ You can get \`$1' as part of \`Autoconf' from any GNU
+ archive site."
+
+ file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
+ test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo "#! /bin/sh"
+ echo "# Created by GNU Automake missing as a replacement of"
+ echo "# $ $@"
+ echo "exit 0"
+ chmod +x $file
+ exit 1
+ fi
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' $msg. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f y.tab.h ]; then
+ echo >y.tab.h
+ fi
+ if [ ! -f y.tab.c ]; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f lex.yy.c ]; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ help2man)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a dependency of a manual page. You may need the
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
+
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
+ fi
+ if [ -f "$file" ]; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo ".ab help2man is required to generate this page"
+ exit 1
+ fi
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ # The file to touch is that specified with -o ...
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ # ... or it is the one specified with @setfilename ...
+ infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile`
+ # ... or it is derived from the source name (dir/f.texi becomes f.info)
+ test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+ fi
+ # If the file does not exist, the user really needs makeinfo;
+ # let's fail without touching anything.
+ test -f $file || exit 1
+ touch $file
+ ;;
+
+ tar)
+ shift
+
+ # We have already tried tar in the generic part.
+ # Look for gnutar/gtar before invocation to avoid ugly error
+ # messages.
+ if (gnutar --version > /dev/null 2>&1); then
+ gnutar "$@" && exit 0
+ fi
+ if (gtar --version > /dev/null 2>&1); then
+ gtar "$@" && exit 0
+ fi
+ firstarg="$1"
+ if shift; then
+ case "$firstarg" in
+ *o*)
+ firstarg=`echo "$firstarg" | sed s/o//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ case "$firstarg" in
+ *h*)
+ firstarg=`echo "$firstarg" | sed s/h//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ fi
+
+ echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+ You may want to install GNU tar or Free paxutils, or check the
+ command line arguments."
+ exit 1
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequisites for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/mkinstalldirs b/mkinstalldirs
new file mode 100755
index 0000000..259dbfc
--- /dev/null
+++ b/mkinstalldirs
@@ -0,0 +1,158 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+
+scriptversion=2005-06-29.22
+
+# Original author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain.
+#
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+errstatus=0
+dirmode=
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ...
+
+Create each directory DIR (with mode MODE, if specified), including all
+leading file name components.
+
+Report bugs to <bug-automake@gnu.org>."
+
+# process command line arguments
+while test $# -gt 0 ; do
+ case $1 in
+ -h | --help | --h*) # -h for help
+ echo "$usage"
+ exit $?
+ ;;
+ -m) # -m PERM arg
+ shift
+ test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
+ dirmode=$1
+ shift
+ ;;
+ --version)
+ echo "$0 $scriptversion"
+ exit $?
+ ;;
+ --) # stop option processing
+ shift
+ break
+ ;;
+ -*) # unknown option
+ echo "$usage" 1>&2
+ exit 1
+ ;;
+ *) # first non-opt arg
+ break
+ ;;
+ esac
+done
+
+for file
+do
+ if test -d "$file"; then
+ shift
+ else
+ break
+ fi
+done
+
+case $# in
+ 0) exit 0 ;;
+esac
+
+# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and
+# mkdir -p a/c at the same time, both will detect that a is missing,
+# one will create a, then the other will try to create a and die with
+# a "File exists" error. This is a problem when calling mkinstalldirs
+# from a parallel make. We use --version in the probe to restrict
+# ourselves to GNU mkdir, which is thread-safe.
+case $dirmode in
+ '')
+ if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+ echo "mkdir -p -- $*"
+ exec mkdir -p -- "$@"
+ else
+ # On NextStep and OpenStep, the `mkdir' command does not
+ # recognize any option. It will interpret all options as
+ # directories to create, and then abort because `.' already
+ # exists.
+ test -d ./-p && rmdir ./-p
+ test -d ./--version && rmdir ./--version
+ fi
+ ;;
+ *)
+ if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 &&
+ test ! -d ./--version; then
+ echo "mkdir -m $dirmode -p -- $*"
+ exec mkdir -m "$dirmode" -p -- "$@"
+ else
+ # Clean up after NextStep and OpenStep mkdir.
+ for d in ./-m ./-p ./--version "./$dirmode";
+ do
+ test -d $d && rmdir $d
+ done
+ fi
+ ;;
+esac
+
+for file
+do
+ case $file in
+ /*) pathcomp=/ ;;
+ *) pathcomp= ;;
+ esac
+ oIFS=$IFS
+ IFS=/
+ set fnord $file
+ shift
+ IFS=$oIFS
+
+ for d
+ do
+ test "x$d" = x && continue
+
+ pathcomp=$pathcomp$d
+ case $pathcomp in
+ -*) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ else
+ if test ! -z "$dirmode"; then
+ echo "chmod $dirmode $pathcomp"
+ lasterr=
+ chmod "$dirmode" "$pathcomp" || lasterr=$?
+
+ if test ! -z "$lasterr"; then
+ errstatus=$lasterr
+ fi
+ fi
+ fi
+ fi
+
+ pathcomp=$pathcomp/
+ done
+done
+
+exit $errstatus
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/scripts/Makefile b/scripts/Makefile
new file mode 100644
index 0000000..53fd363
--- /dev/null
+++ b/scripts/Makefile
@@ -0,0 +1,381 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# scripts/Makefile. Generated from Makefile.in by configure.
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 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.
+
+
+srcdir = .
+top_srcdir = ..
+
+pkgdatadir = $(datadir)/ipmiutil
+pkglibdir = $(libdir)/ipmiutil
+pkgincludedir = $(includedir)/ipmiutil
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = /usr/bin/install -c
+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 = x86_64-redhat-linux-gnu
+host_triplet = x86_64-redhat-linux-gnu
+subdir = scripts
+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 =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = ${SHELL} /usr/dev/ipmiutil-2.9.3/missing --run aclocal-1.9
+AMDEP_FALSE = #
+AMDEP_TRUE =
+AMTAR = ${SHELL} /usr/dev/ipmiutil-2.9.3/missing --run tar
+AR = ar
+AUTOCONF = ${SHELL} /usr/dev/ipmiutil-2.9.3/missing --run autoconf
+AUTOHEADER = ${SHELL} /usr/dev/ipmiutil-2.9.3/missing --run autoheader
+AUTOMAKE = ${SHELL} /usr/dev/ipmiutil-2.9.3/missing --run automake-1.9
+AWK = gawk
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPP = gcc -E
+CPPFLAGS =
+CROSS_CFLAGS =
+CROSS_LFLAGS =
+CXX = g++
+CXXCPP = g++ -E
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO = echo
+ECHO_C =
+ECHO_N = -n
+ECHO_T =
+EGREP = grep -E
+EXEEXT =
+F77 = f95
+FFLAGS = -g -O2
+GPL_CFLAGS =
+IA64_CFLAGS =
+INIT_DIR = /etc//rc.d/init.d
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
+INS_LIB =
+LANDESK_CFLAGS =
+LANDESK_LDADD =
+LANPLUS_CFLAGS = -DHAVE_LANPLUS
+LANPLUS_CRYPTO = -lcrypto
+LANPLUS_LDADD = -L../lib -lipmi_lanplus -L/usr/local/lib -lcrypto
+LANPLUS_LIB = ../lib/libipmi_lanplus.a
+LANPLUS_SAM = yes
+LDFLAGS =
+LD_SAMX = ../lib/libipmi_lanplus.a -lcrypto
+LIBOBJS =
+LIBS =
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LIB_DIR = /usr/lib64
+LN_S = ln -s
+LTLIBOBJS =
+MAKEINFO = ${SHELL} /usr/dev/ipmiutil-2.9.3/missing --run makeinfo
+OBJEXT = o
+OS_CFLAGS = -DLINUX -fPIC -fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2
+OS_DRIVERS = imbapi.c ipmimv.c ipmild.c ipmidir.c
+OS_LFLAGS =
+PACKAGE = ipmiutil
+PACKAGE_BUGREPORT =
+PACKAGE_NAME =
+PACKAGE_STRING =
+PACKAGE_TARNAME =
+PACKAGE_VERSION =
+PATH_SEPARATOR = :
+PKG_DIR = /usr/src/redhat
+RANLIB = ranlib
+SED = /bin/sed
+SET_MAKE =
+SHELL = /bin/sh
+SHR_LINK = libipmiutil.so
+STRIP = strip
+SUBDIR_S = doc scripts lib util
+SYSTEMD_DIR = /usr/share/ipmiutil
+VERSION = 2.9.3
+ac_ct_AR = ar
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+ac_ct_F77 = f95
+ac_ct_RANLIB = ranlib
+ac_ct_STRIP = strip
+am__fastdepCC_FALSE = #
+am__fastdepCC_TRUE =
+am__fastdepCXX_FALSE = #
+am__fastdepCXX_TRUE =
+am__include = include
+am__leading_dot = .
+am__quote =
+am__tar = ${AMTAR} chof - "$$tardir"
+am__untar = ${AMTAR} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-redhat-linux-gnu
+build_alias =
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = redhat
+datadir = ${prefix}/share
+exec_prefix = ${prefix}
+host = x86_64-redhat-linux-gnu
+host_alias =
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = redhat
+includedir = ${prefix}/include
+infodir = ${prefix}/info
+install_sh = /usr/dev/ipmiutil-2.9.3/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localstatedir = ${prefix}/var
+mandir = ${prefix}/share/man
+mkdir_p = mkdir -p --
+oldincludedir = /usr/include
+prefix = /usr
+program_transform_name = s,x,x,
+sbindir = ${prefix}/sbin
+sharedstatedir = ${prefix}/com
+sysconfdir = ${prefix}/etc
+target_alias =
+
+#!/bin/sh
+# Makefile to build/install script files
+#
+MKDIR = sh ../mkinstalldirs
+INSTALL_SH = sh ../install-sh -c
+INSTALL_DATA_SH = ${INSTALL_SH} -m 644
+INSTALL_SCRIPT_SH = ${INSTALL_SH} -m 755
+docdir = ${prefix}/share/doc/ipmiutil-${version}
+etcdir = /etc
+datato = ${DESTDIR}${datadir}/ipmiutil
+cronto = ${DESTDIR}${etcdir}/cron.daily
+sbinto = ${DESTDIR}${sbindir}
+varto = ${DESTDIR}/var/lib/ipmiutil
+initto = ${DESTDIR}/etc//rc.d/init.d
+sysdto = ${DESTDIR}/usr/share/ipmiutil
+sysvinit = ${datato}
+sbinfls = ialarms ihealth ifru igetevent ireset icmd isol ilan isensor isel iserial iwdt iconfig ipicmg ifirewall ifwum ihpm
+all: all-am
+
+.SUFFIXES:
+$(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 \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign scripts/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign scripts/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
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$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
+installdirs:
+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:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_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-am: clean-generic clean-libtool mostlyclean-am
+
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-exec install-exec-am \
+ install-info install-info-am install-man install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \
+ uninstall-info-am
+
+
+all:
+
+clean:
+
+clobber:
+
+distclean:
+
+check:
+
+install:
+ $(MKDIR) ${datato}
+ $(MKDIR) ${sbinto}
+ $(MKDIR) ${initto}
+ $(MKDIR) ${varto}
+ $(MKDIR) ${sysdto}
+ ${INSTALL_SCRIPT_SH} ipmi_if.sh ${datato}
+ ${INSTALL_SCRIPT_SH} evt.sh ${datato}
+ if [ -f /etc/debian_version ]; then \
+ sysvinit=${initto}; fi
+ ${INSTALL_SCRIPT_SH} ipmiutil_wdt ${sysvinit}/ipmiutil_wdt
+ ${INSTALL_SCRIPT_SH} ipmiutil_asy ${sysvinit}/ipmiutil_asy
+ ${INSTALL_SCRIPT_SH} ipmiutil_evt ${sysvinit}/ipmiutil_evt
+ ${INSTALL_SCRIPT_SH} ipmi_port.sh ${sysvinit}/ipmi_port
+ ${INSTALL_SCRIPT_SH} ipmi_info ${sysvinit}/ipmi_info
+ ${INSTALL_SCRIPT_SH} checksel ${datato}
+ ${INSTALL_DATA_SH} ipmiutil_wdt.service ${sysdto}
+ ${INSTALL_DATA_SH} ipmiutil_asy.service ${sysdto}
+ ${INSTALL_DATA_SH} ipmiutil_evt.service ${sysdto}
+ ${INSTALL_DATA_SH} ipmi_port.service ${sysdto}
+ ${INSTALL_SCRIPT_SH} ipmiutil.env ${datato}
+ ${INSTALL_SCRIPT_SH} ipmiutil.pre ${datato}
+ ${INSTALL_SCRIPT_SH} ipmiutil.setup ${datato}
+ ${INSTALL_SCRIPT_SH} ipmi.init.basic ${datato}
+ for f in ${sbinfls}; do \
+ ${INSTALL_SCRIPT_SH} $$f ${sbinto}; done
+# 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:
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
new file mode 100644
index 0000000..b693a58
--- /dev/null
+++ b/scripts/Makefile.am
@@ -0,0 +1,60 @@
+#!/bin/sh
+# Makefile to build/install script files
+#
+MKDIR = sh ../mkinstalldirs
+INSTALL_SH = sh ../install-sh -c
+INSTALL_DATA_SH = ${INSTALL_SH} -m 644
+INSTALL_SCRIPT_SH = ${INSTALL_SH} -m 755
+prefix = /usr
+
+datadir = ${prefix}/share
+mandir = ${prefix}/share/man
+docdir = ${prefix}/share/doc/ipmiutil-${version}
+sbindir = ${prefix}/sbin
+etcdir = /etc
+datato = ${DESTDIR}${datadir}/ipmiutil
+cronto = ${DESTDIR}${etcdir}/cron.daily
+sbinto = ${DESTDIR}${sbindir}
+varto = ${DESTDIR}/var/lib/ipmiutil
+initto = ${DESTDIR}@INIT_DIR@
+sysdto = ${DESTDIR}@SYSTEMD_DIR@
+sysvinit = ${datato}
+sbinfls = ialarms ihealth ifru igetevent ireset icmd isol ilan isensor isel iserial iwdt iconfig ipicmg ifirewall ifwum ihpm
+
+all:
+
+clean:
+
+clobber:
+
+distclean:
+
+check:
+
+install:
+ $(MKDIR) ${datato}
+ $(MKDIR) ${sbinto}
+ $(MKDIR) ${initto}
+ $(MKDIR) ${varto}
+ $(MKDIR) ${sysdto}
+ ${INSTALL_SCRIPT_SH} ipmi_if.sh ${datato}
+ ${INSTALL_SCRIPT_SH} evt.sh ${datato}
+ if [ -f /etc/debian_version ]; then \
+ sysvinit=${initto}; fi
+ ${INSTALL_SCRIPT_SH} ipmiutil_wdt ${sysvinit}/ipmiutil_wdt
+ ${INSTALL_SCRIPT_SH} ipmiutil_asy ${sysvinit}/ipmiutil_asy
+ ${INSTALL_SCRIPT_SH} ipmiutil_evt ${sysvinit}/ipmiutil_evt
+ ${INSTALL_SCRIPT_SH} ipmi_port.sh ${sysvinit}/ipmi_port
+ ${INSTALL_SCRIPT_SH} ipmi_info ${sysvinit}/ipmi_info
+ ${INSTALL_SCRIPT_SH} checksel ${datato}
+ ${INSTALL_DATA_SH} ipmiutil_wdt.service ${sysdto}
+ ${INSTALL_DATA_SH} ipmiutil_asy.service ${sysdto}
+ ${INSTALL_DATA_SH} ipmiutil_evt.service ${sysdto}
+ ${INSTALL_DATA_SH} ipmi_port.service ${sysdto}
+ ${INSTALL_SCRIPT_SH} ipmiutil.env ${datato}
+ ${INSTALL_SCRIPT_SH} ipmiutil.pre ${datato}
+ ${INSTALL_SCRIPT_SH} ipmiutil.setup ${datato}
+ ${INSTALL_SCRIPT_SH} ipmi.init.basic ${datato}
+ for f in ${sbinfls}; do \
+ ${INSTALL_SCRIPT_SH} $$f ${sbinto}; done
+
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
new file mode 100644
index 0000000..f8587da
--- /dev/null
+++ b/scripts/Makefile.in
@@ -0,0 +1,381 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 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@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+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@
+subdir = scripts
+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 =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+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@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GPL_CFLAGS = @GPL_CFLAGS@
+IA64_CFLAGS = @IA64_CFLAGS@
+INIT_DIR = @INIT_DIR@
+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@
+LDFLAGS = @LDFLAGS@
+LD_SAMX = @LD_SAMX@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_DIR = @LIB_DIR@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+OS_CFLAGS = @OS_CFLAGS@
+OS_DRIVERS = @OS_DRIVERS@
+OS_LFLAGS = @OS_LFLAGS@
+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@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHR_LINK = @SHR_LINK@
+STRIP = @STRIP@
+SUBDIR_S = @SUBDIR_S@
+SYSTEMD_DIR = @SYSTEMD_DIR@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+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@
+datadir = ${prefix}/share
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = ${prefix}/share/man
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = /usr
+program_transform_name = @program_transform_name@
+sbindir = ${prefix}/sbin
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+
+#!/bin/sh
+# Makefile to build/install script files
+#
+MKDIR = sh ../mkinstalldirs
+INSTALL_SH = sh ../install-sh -c
+INSTALL_DATA_SH = ${INSTALL_SH} -m 644
+INSTALL_SCRIPT_SH = ${INSTALL_SH} -m 755
+docdir = ${prefix}/share/doc/ipmiutil-${version}
+etcdir = /etc
+datato = ${DESTDIR}${datadir}/ipmiutil
+cronto = ${DESTDIR}${etcdir}/cron.daily
+sbinto = ${DESTDIR}${sbindir}
+varto = ${DESTDIR}/var/lib/ipmiutil
+initto = ${DESTDIR}@INIT_DIR@
+sysdto = ${DESTDIR}@SYSTEMD_DIR@
+sysvinit = ${datato}
+sbinfls = ialarms ihealth ifru igetevent ireset icmd isol ilan isensor isel iserial iwdt iconfig ipicmg ifirewall ifwum ihpm
+all: all-am
+
+.SUFFIXES:
+$(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 \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign scripts/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign scripts/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
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$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
+installdirs:
+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:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_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-am: clean-generic clean-libtool mostlyclean-am
+
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-exec install-exec-am \
+ install-info install-info-am install-man install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \
+ uninstall-info-am
+
+
+all:
+
+clean:
+
+clobber:
+
+distclean:
+
+check:
+
+install:
+ $(MKDIR) ${datato}
+ $(MKDIR) ${sbinto}
+ $(MKDIR) ${initto}
+ $(MKDIR) ${varto}
+ $(MKDIR) ${sysdto}
+ ${INSTALL_SCRIPT_SH} ipmi_if.sh ${datato}
+ ${INSTALL_SCRIPT_SH} evt.sh ${datato}
+ if [ -f /etc/debian_version ]; then \
+ sysvinit=${initto}; fi
+ ${INSTALL_SCRIPT_SH} ipmiutil_wdt ${sysvinit}/ipmiutil_wdt
+ ${INSTALL_SCRIPT_SH} ipmiutil_asy ${sysvinit}/ipmiutil_asy
+ ${INSTALL_SCRIPT_SH} ipmiutil_evt ${sysvinit}/ipmiutil_evt
+ ${INSTALL_SCRIPT_SH} ipmi_port.sh ${sysvinit}/ipmi_port
+ ${INSTALL_SCRIPT_SH} ipmi_info ${sysvinit}/ipmi_info
+ ${INSTALL_SCRIPT_SH} checksel ${datato}
+ ${INSTALL_DATA_SH} ipmiutil_wdt.service ${sysdto}
+ ${INSTALL_DATA_SH} ipmiutil_asy.service ${sysdto}
+ ${INSTALL_DATA_SH} ipmiutil_evt.service ${sysdto}
+ ${INSTALL_DATA_SH} ipmi_port.service ${sysdto}
+ ${INSTALL_SCRIPT_SH} ipmiutil.env ${datato}
+ ${INSTALL_SCRIPT_SH} ipmiutil.pre ${datato}
+ ${INSTALL_SCRIPT_SH} ipmiutil.setup ${datato}
+ ${INSTALL_SCRIPT_SH} ipmi.init.basic ${datato}
+ for f in ${sbinfls}; do \
+ ${INSTALL_SCRIPT_SH} $$f ${sbinto}; done
+# 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:
diff --git a/scripts/checksel b/scripts/checksel
new file mode 100755
index 0000000..63ea9a9
--- /dev/null
+++ b/scripts/checksel
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# checksel
+#
+# This script runs ipmiutil sel, writing any new records to syslog,
+# and will then clear the SEL if free space is low.
+#
+# The IPMI SEL should not normally be cleared, because the history
+# of the events is important, but if the IPMI SEL fills up, no new
+# events are logged, so saving the previous SEL events and clearing
+# the SEL must be done occasionally, as needed.
+#
+# app=`basename $0`
+# pdir=`echo $0 |sed -e "s/$app//"`
+pdir=/usr/bin
+ddir=/var/lib/ipmiutil
+# First check to see if the IPMI SEL is enabled on this system.
+# If not, do nothing else.
+$pdir/ipmiutil sel -v >/dev/null 2>&1
+if [ $? -eq 0 ]; then
+ # Write new SEL events to syslog, and check if free space is low
+ $pdir/ipmiutil sel -w |grep "WARNING: free space"
+ if [ $? -eq 0 ]; then
+ today=`date +%y%m%d`
+ # The old SEL records are in syslog, but save a copy in $ddir also.
+ $pdir/ipmiutil sel -e >$ddir/ipmisel_${today}.txt
+ # Clear the IPMI SEL
+ $pdir/ipmiutil sel -d
+ fi
+fi
diff --git a/scripts/checksel.cmd b/scripts/checksel.cmd
new file mode 100644
index 0000000..2897b76
--- /dev/null
+++ b/scripts/checksel.cmd
@@ -0,0 +1,15 @@
+@echo off
+REM checksel.cmd
+REM This at script runs ipmiutil sel, writing any new records to syslog,
+REM and will then clear the SEL if free space is low.
+
+REM Get path from arg 0
+set ipmiutildir=%~d0%~p0
+
+cd %ipmiutildir%
+cmd /c %ipmiutildir%\ipmiutil sel -w | findstr /c:"WARNING: free space"
+if errorlevel 1 goto done
+cmd /c %ipmiutildir%\ipmiutil sel -d
+
+:done
+
diff --git a/scripts/evt.sh b/scripts/evt.sh
new file mode 100755
index 0000000..b600481
--- /dev/null
+++ b/scripts/evt.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+# evt.sh
+# A sample script to use via ipmiutil getevt -s -r /path/evt.sh
+#
+evtdesc=$1
+log=/var/log/ipmi_evt.log
+
+echo "$0 got IPMI event `date`" >>$log
+echo "$evtdesc" >>$log
+# Check SEVerity for anything other than INFormational.
+echo $evtdesc |grep -v INF >/dev/null 2>&1
+if [ $? -eq 0 ]; then
+ # Could take various specific actions here, like snmptrap, or other alert.
+ echo "*** Non-INF IPMI Event requiring attention ***" >>$log
+ snmpdest=`grep trapsink /etc/snmp/snmpd.conf 2>/dev/null |head -n1`
+ if [ "x$snmpdest" = "x" ]; then
+ echo "No SNMP trapsink destination" >>$log
+ else
+ snmpipadr=`echo $snmpdest |awk '{ print $2 }'`
+ community=`echo $snmpdest |awk '{ print $3 }'`
+ snmphost=`uname -n`
+ uptim=`cat /proc/uptime |cut -f1 -d' '`
+ trapoid="enterprises.1"
+ vboid1=".enterprises.1.1" #trapString
+ vboid2=".enterprises.1.2" #trapSeverity
+ sev=`echo $evtdesc |cut -c24-26`
+ case $sev in
+ MIN)
+ tsev=2
+ ;;
+ MAJ)
+ tsev=3
+ ;;
+ CRT)
+ tsev=4
+ ;;
+ *)
+ tsev=1
+ ;;
+ esac
+ snmptrap -v 1 -c $community $snmpipadr $trapoid $snmphost 6 0 $uptim $vboid1 s "$evtdesc" $vboid2 i $tsev
+ echo "Send SNMP trap to $snmpipadr for IPMI $sev event, status=$?" >>$log
+ fi
+fi
+
diff --git a/scripts/ialarms b/scripts/ialarms
new file mode 100755
index 0000000..f303bff
--- /dev/null
+++ b/scripts/ialarms
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil alarms $*
diff --git a/scripts/ialarms.cmd b/scripts/ialarms.cmd
new file mode 100644
index 0000000..e5e4519
--- /dev/null
+++ b/scripts/ialarms.cmd
@@ -0,0 +1 @@
+ipmiutil alarms %*
diff --git a/scripts/icmd b/scripts/icmd
new file mode 100755
index 0000000..291d6bd
--- /dev/null
+++ b/scripts/icmd
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil cmd $*
diff --git a/scripts/icmd.cmd b/scripts/icmd.cmd
new file mode 100644
index 0000000..4cea630
--- /dev/null
+++ b/scripts/icmd.cmd
@@ -0,0 +1 @@
+ipmiutil cmd %*
diff --git a/scripts/iconfig b/scripts/iconfig
new file mode 100755
index 0000000..50ef90a
--- /dev/null
+++ b/scripts/iconfig
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil config $*
diff --git a/scripts/iconfig.cmd b/scripts/iconfig.cmd
new file mode 100644
index 0000000..08927fd
--- /dev/null
+++ b/scripts/iconfig.cmd
@@ -0,0 +1 @@
+ipmiutil config %*
diff --git a/scripts/idiscover.cmd b/scripts/idiscover.cmd
new file mode 100644
index 0000000..e2d07e5
--- /dev/null
+++ b/scripts/idiscover.cmd
@@ -0,0 +1 @@
+ipmiutil discover %*
diff --git a/scripts/ifirewall b/scripts/ifirewall
new file mode 100755
index 0000000..999176a
--- /dev/null
+++ b/scripts/ifirewall
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil firewall $*
diff --git a/scripts/ifru b/scripts/ifru
new file mode 100755
index 0000000..1b0a996
--- /dev/null
+++ b/scripts/ifru
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil fru $*
diff --git a/scripts/ifru.cmd b/scripts/ifru.cmd
new file mode 100644
index 0000000..0c4f048
--- /dev/null
+++ b/scripts/ifru.cmd
@@ -0,0 +1 @@
+ipmiutil fru %*
diff --git a/scripts/ifwum b/scripts/ifwum
new file mode 100755
index 0000000..d4c3272
--- /dev/null
+++ b/scripts/ifwum
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil fwum $*
diff --git a/scripts/igetevent b/scripts/igetevent
new file mode 100755
index 0000000..76b2a25
--- /dev/null
+++ b/scripts/igetevent
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil getevt $*
diff --git a/scripts/igetevent.cmd b/scripts/igetevent.cmd
new file mode 100644
index 0000000..f31d2d0
--- /dev/null
+++ b/scripts/igetevent.cmd
@@ -0,0 +1 @@
+ipmiutil getevt %*
diff --git a/scripts/ihealth b/scripts/ihealth
new file mode 100755
index 0000000..31fcfd7
--- /dev/null
+++ b/scripts/ihealth
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil health $*
diff --git a/scripts/ihealth.cmd b/scripts/ihealth.cmd
new file mode 100644
index 0000000..2dab741
--- /dev/null
+++ b/scripts/ihealth.cmd
@@ -0,0 +1 @@
+ipmiutil health %*
diff --git a/scripts/ihpm b/scripts/ihpm
new file mode 100755
index 0000000..15240b0
--- /dev/null
+++ b/scripts/ihpm
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil hpm $*
diff --git a/scripts/ilan b/scripts/ilan
new file mode 100755
index 0000000..a822176
--- /dev/null
+++ b/scripts/ilan
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil lan $*
diff --git a/scripts/ilan.cmd b/scripts/ilan.cmd
new file mode 100644
index 0000000..68d097e
--- /dev/null
+++ b/scripts/ilan.cmd
@@ -0,0 +1 @@
+ipmiutil lan %*
diff --git a/scripts/init.sh b/scripts/init.sh
new file mode 100755
index 0000000..d08fcd6
--- /dev/null
+++ b/scripts/init.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+# init.sh - run this at install time if rpm postinstall not used
+#
+sbindir=/usr/bin
+vardir=/var/lib/ipmiutil
+datadir=/usr/share/ipmiutil
+sensorout=$vardir/sensor_out.txt
+
+ if [ -x $datadir/setlib.sh ]; then
+ $datadir/setlib.sh
+ fi
+
+ mkdir -p $vardir
+ if [ ! -f $vardir/ipmi_if.txt ]; then
+ $datadir/ipmi_if.sh
+ fi
+
+ # Run some ipmiutil command to see if any IPMI interface works.
+ $sbindir/ipmiutil wdt >/dev/null 2>&1
+ IPMIret=$?
+
+ # If IPMIret==0, the IPMI cmd was successful, and IPMI is enabled locally.
+ if [ $IPMIret -eq 0 ]; then
+ # IPMI_IS_ENABLED, so enable services
+ if [ -x /sbin/chkconfig ]; then
+ /sbin/chkconfig --add ipmi_port
+ /sbin/chkconfig --add ipmiutil_wdt
+ /sbin/chkconfig --add ipmiutil_asy
+ fi
+
+ # Capture a snapshot of IPMI sensor data once now for later reuse.
+ if [ ! -f $sensorout ]; then
+ $sbindir/ipmiutil sensor -q >$sensorout
+ fi
+ fi
+
diff --git a/scripts/install-solaris.sh b/scripts/install-solaris.sh
new file mode 100755
index 0000000..b452602
--- /dev/null
+++ b/scripts/install-solaris.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+# Solaris or BSD install.sh
+#
+datadir=/usr/share/ipmiutil
+vardir=/var/lib/ipmiutil
+sbindir=/usr/bin
+mandir=/usr/share/man/man8
+manfiles="ialarms.8 iconfig.8 ihealth.8 ievents.8 ifru.8 igetevent.8 ireset.8 icmd.8 idiscover.8 ipmiutil.8 isol.8 ilan.8 isensor.8 isel.8 iserial.8 iwdt.8"
+shfiles="checksel ipmi_if.sh ipmi_port.sh ipmiutil_wdt"
+mibfiles="bmclanpet.mib"
+
+mkdir -p $datadir
+mkdir -p $vardir
+mkdir -p $mandir
+cp ipmiutil ievents idiscover ipmi_port $sbindir
+cp $manfiles $mandir
+cp UserGuide $mibfiles $shfiles $datadir
+$sbindir/ipmiutil sensor -q >$vardir/sensor_out.txt
+# Admin should set up checksel cron script also
+
diff --git a/scripts/install.cmd b/scripts/install.cmd
new file mode 100644
index 0000000..da0e860
--- /dev/null
+++ b/scripts/install.cmd
@@ -0,0 +1,26 @@
+@echo off
+REM install Windows ipmiutil on this system
+REM install the DLLs, registry entries, and start the checksel task
+REM Use the current directory as the starting path
+set ipmiutildir=%CD%
+set orgdir=%SystemDrive%\Program Files\sourceforge
+set installdir=%orgdir%\ipmiutil
+
+REM DLLs: showsel.dll, libeay32.dll, ssleay32.dll
+copy *.dll %SystemRoot%\system32
+%ipmiutildir%\showsel.reg
+
+echo Copying files to "%installdir%"
+mkdir "%orgdir%"
+mkdir "%installdir%"
+copy "%ipmiutildir%\*.*" "%installdir%"
+
+REM echo PATH=%PATH%
+set PATH=%PATH%;%installdir%
+
+set pathkey="HKLM\System\CurrentControlSet\Control\Session Manager\Environment"
+reg add %pathkey% /v Path /t REG_EXPAND_SZ /d "%PATH%;%installdir%"
+REM reg query %pathkey% /v Path
+
+at 23:30 /every:m,t,w,th,f,s,su "%installdir%\checksel.cmd" >"%installdir%\checksel.id"
+
diff --git a/scripts/install.vbs b/scripts/install.vbs
new file mode 100644
index 0000000..e5a1b56
--- /dev/null
+++ b/scripts/install.vbs
@@ -0,0 +1,47 @@
+' This VBScript should run after all files have been copied onto the system.
+
+Set sh = CreateObject("WScript.Shell")
+Set fso = CreateObject("Scripting.FileSystemObject")
+
+Dim installer : Set installer = Nothing
+Set installer = CreateObject("WindowsInstaller.Installer")
+Dim sOutFile, outs, sScrFile
+
+' Find out where our files were installed
+If(IsEmpty(Session)) Then
+ 'Not running from within installer. Source path is current directory.
+ InstallLoc = sh.CurrentDirectory
+Else
+ 'Running inside the installer, use CustomActionData "[TARGETDIR]".
+ ' InstallLoc = installer.ProductInfo(productCode, "InstallLocation")
+ InstallLoc = Session.Property("CustomActionData")
+ If(IsEmpty(InstallLoc)) Then
+ InstallLoc = "C:\Program Files\sourceforge\ipmiutil"
+ End If
+End If
+' wscript.echo "InstallLoc=" & InstallLoc
+
+' Find System Folder (usually c:\windows\system32).
+key = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot"
+SysLoc = sh.RegRead(key) & "\system32"
+
+' Add InstallLoc to the Environment Path
+key3 = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\Path"
+EnvPath = sh.RegRead(key3) & ";" & InstallLoc
+sh.RegWrite key3, EnvPath, "REG_EXPAND_SZ"
+
+' Set up the showsel EventLog source
+' showselmsg.dll is copied by the installer already
+keybase = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\showsel\"
+key1 = keybase & "EventMessageFile"
+key2 = keybase & "TypesSupported"
+sh.RegWrite key1, "%SystemRoot%\system32\showselmsg.dll", "REG_EXPAND_SZ"
+sh.RegWrite key2, 7, "REG_DWORD"
+'val1 = sh.RegRead(key1)
+'val2 = sh.RegRead(key2)
+'wscript.echo "showsel: msgfile " & val1 & " types " & val2
+
+' Schedule the checksel.cmd to run
+sScrFile = InstallLoc & "\checksel.cmd"
+sh.Run "at 23.30 /every:m,t,w,th,f,s,su """ & sScrFile & """ ", 0, True
+
diff --git a/scripts/ipdiff.sh b/scripts/ipdiff.sh
new file mode 100755
index 0000000..1aeef2a
--- /dev/null
+++ b/scripts/ipdiff.sh
@@ -0,0 +1,31 @@
+# ipdiff.sh
+# For non-shared BMC LAN channels, take the OS IP and add an increment,
+# then run pefconfig -I to set the new BMC LAN IP.
+#
+# eth: Get the OS IP from eth0 by default
+# incr: Increment is 128. by default
+# Customers may wish to customize the $eth and $incr parameters below to
+# vary these for their network environments.
+#
+# This produces a series of systems with IP addresses allocated like this:
+# OS IP BMC LAN IP
+# system1 192.168.0.1 192.168.0.129
+# system2 192.168.0.2 192.168.0.130
+# system3 192.168.0.3 192.168.0.131
+# ...
+eth=eth0
+incr=128
+ip=`ifconfig $eth |grep "inet addr:" |cut -f2 -d':' |awk '{print $1}'`
+last=`echo $ip |cut -f4 -d'.'`
+first=`echo $ip |cut -f1-3 -d'.'`
+sysname=`uname -n`
+
+newlast=`expr $last + $incr`
+if [ $newlast -ge 255 ]
+then
+ # overflow, so wrap IP (could return error instead)
+ newlast=`expr $newlast - 255`
+fi
+newip=${first}.${newlast}
+echo "$sysname: $eth IP = $ip, BMC IP = $newip"
+ipmiutil lan -e -I $newip
diff --git a/scripts/ipicmg b/scripts/ipicmg
new file mode 100755
index 0000000..d66588e
--- /dev/null
+++ b/scripts/ipicmg
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil picmg $*
diff --git a/scripts/ipmi.init.basic b/scripts/ipmi.init.basic
new file mode 100755
index 0000000..f12c743
--- /dev/null
+++ b/scripts/ipmi.init.basic
@@ -0,0 +1,80 @@
+#!/bin/sh
+#
+# ipmi: OpenIPMI Driver init script (basic only)
+# Author: Andy Cress
+#
+# chkconfig: - 13 87
+# description: OpenIPMI Driver init script
+#
+# Use this if the Linux distro does not provide one.
+#Sample script to install it without chkconfig:
+#=====
+#ipmisvc=/etc/init.d/ipmi
+#cp -f ipmi.init.basic $ipmisvc
+#ln -s $ipmisvc /etc/rc0.d/K87ipmi
+#ln -s $ipmisvc /etc/rc1.d/K87ipmi
+#ln -s $ipmisvc /etc/rc6.d/K87ipmi
+#ln -s $ipmisvc /etc/rc2.d/S13ipmi
+#ln -s $ipmisvc /etc/rc3.d/S13ipmi
+#ln -s $ipmisvc /etc/rc4.d/S13ipmi
+#ln -s $ipmisvc /etc/rc5.d/S13ipmi
+#=====
+#
+rv=0
+
+start() {
+ lsmod |grep ipmi_dev >/dev/null
+ if [ $? -ne 0 ]; then
+ echo "Starting OpenIPMI driver ..."
+ # load the ipmi modules, if not already loaded or builtin
+ cat /proc/kallsyms |grep ipmi_init_msghandler >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ modprobe ipmi_msghandler
+ fi
+ cat /proc/kallsyms |grep init_ipmi_si >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ modprobe ipmi_si
+ rv=$?
+ if [ $rv -ne 0 ]; then
+ modprobe ipmi_si_drv # try old module name
+ fi
+ fi
+ modprobe ipmi_devintf
+ modprobe ipmi_watchdog 2>/dev/null
+ fi
+
+ maj=$(cat /proc/devices | awk '/ipmidev/{print $1}')
+ if [ "x$maj" != "x" ]; then
+ test -e /dev/ipmi0 && rm -f /dev/ipmi0
+ /bin/mknod /dev/ipmi0 c $maj 0
+ fi
+}
+
+stop() {
+ lsmod |grep ipmi_msghandler >/dev/null
+ if [ $? -eq 0 ]; then
+ echo "Stopping OpenIPMI driver ..."
+ rmmod ipmi_poweroff 2>/dev/null
+ rmmod ipmi_watchdog 2>/dev/null
+ rmmod ipmi_devintf 2>/dev/null
+ rmmod ipmi_si
+ rv=$?
+ rmmod ipmi_msghandler
+ else
+ rv=2
+ fi
+}
+
+status() {
+ lsmod |grep ipmi
+ rv=$?
+}
+
+case "$1" in
+ start) start ;;
+ stop) stop ;;
+ status) status ;;
+ *) start ;;
+esac
+
+exit $rv
diff --git a/scripts/ipmi_if.sh b/scripts/ipmi_if.sh
new file mode 100755
index 0000000..4068717
--- /dev/null
+++ b/scripts/ipmi_if.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+# ipmi_if.sh
+# detect IPMI Interface type, usually KCS or SSIF
+#
+# Future: also include preferred Driver type on another line
+#
+# ifdir=/usr/share/ipmiutil
+ifdir=/var/lib/ipmiutil
+ifout=$ifdir/ipmi_if.txt
+dmiout=/tmp/dmi.out.$$
+
+mkdir -p $ifdir
+which dmidecode >/dev/null 2>&1
+if [ $? -ne 0 ]
+then
+ # if no dmidecode, old, so assume KCS
+ echo "Interface type: KCS" >$ifout
+ exit 0
+fi
+dmidecode >$dmiout
+# dmidecode |grep IPMI >/dev/null 2>&1
+grep IPMI $dmiout >/dev/null 2>&1
+if [ $? -ne 0 ]
+then
+ echo "Interface type: None" >$ifout
+ exit 0
+fi
+iftype=`grep "Interface Type:" $dmiout |cut -f2 -d':'`
+echo $iftype |grep KCS >/dev/null 2>&1
+if [ $? -eq 0 ]
+then
+ echo "Interface type: KCS" >$ifout
+else
+ echo $iftype |grep "OUT OF SPEC" >/dev/null 2>&1
+ if [ $? -eq 0 ]
+ then
+ echo "Interface type: SSIF" >$ifout
+ else
+ echo "Interface type: $iftype" >$ifout
+ fi
+fi
+# echo "IPMI `cat $ifout` interface found"
+
+sa=`grep "I2C Slave Address:" $dmiout |cut -f2 -d':'`
+echo "I2C Slave Address: $sa" >>$ifout
+base=`grep "Base Address:" $dmiout |tail -n1 |cut -f2 -d':'`
+echo "Base Address: $base" >>$ifout
+
+spacing=1
+spac_str=`grep "Register Spacing:" $dmiout |cut -f2 -d':'`
+echo $spac_str | grep "Successive Byte" >/dev/null 2>&1
+if [ $? -eq 0 ]; then
+ spacing=1
+else
+ echo $spac_str | grep "32-bit" >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ spacing=4
+ else
+ spacing=2
+ fi
+fi
+echo "Register Spacing: $spacing" >>$ifout
+
+biosver=`grep "Version: " $dmiout |head -n1 |cut -f2 -d':'`
+echo "BIOS Version: $biosver" >>$ifout
+exit 0
diff --git a/scripts/ipmi_info b/scripts/ipmi_info
new file mode 100755
index 0000000..b3b3f9a
--- /dev/null
+++ b/scripts/ipmi_info
@@ -0,0 +1,124 @@
+#! /bin/sh
+#
+# ipmi_info
+#
+# chkconfig: 345 91 07
+# description: ipmi_info saves the OS info (hostname, OS release) into
+# the IPMI System Info variables, if supported.
+# It does nothing if IPMI System Info is not supported.
+#
+### BEGIN INIT INFO
+# Provides: ipmi_info
+# Required-Start: $local_fs $network $remote_fs
+# Required-Stop: $local_fs $network $remote_fs
+# Default-Start:
+# Default-Stop:
+# Short-Description: ipmi_info saves OS info to the IPMI system info
+# Description: ipmi_info saves OS info to the IPMI system info
+### END INIT INFO
+
+name=ipmi_info
+iuprog=/usr/bin/ipmiutil
+tmp=/tmp/ipmi_info.tmp
+
+getosver() {
+ if [ -f /etc/os-release ]; then
+ . /etc/os-release
+ echo "${NAME} ${VERSION} kernel ${KERNEL_VERSION}"
+ elif [ -f /etc/redhat-release ]; then
+ cat /etc/redhat-release |head -n1
+ elif [ -f /etc/SuSE-release ]; then
+ cat /etc/SuSE-release |head -n1
+ elif [ -f /etc/mvl-release ]; then
+ sver=`grep Monta /etc/mvl-release |awk '{ print $4 }' |cut -f1 -d'.'`
+ echo "Monta Vista Linux version $sver"
+ elif [ -f /etc/debian_version ]; then
+ sver=`grep Debian /etc/issue |awk '{ print $3 }'`
+ echo "Debian Linux version $sver"
+ else
+ sver=`uname -r`
+ styp=`uname -s`
+ echo "$styp $sver"
+ fi
+}
+
+start()
+{
+ echo -n $"Starting $name: "
+ echo
+ retval=0
+ PID=0
+
+ ${iuprog} health -i >$tmp 2>&1
+ if [ $? -eq 0 ]; then
+ name=`hostname`
+ os=`getosver`
+ echo "setting name=$name, os=$os ..." >>$tmp
+ ${iuprog} health -n "$name" >>$tmp 2>&1
+ ${iuprog} health -o "$os" >>$tmp 2>&1
+ else
+ # IPMI System Info is not supported.
+ retval=0
+ fi
+ echo
+ return $retval
+}
+
+stop()
+{
+ echo -n $"Stopping $name: "
+ echo
+ retval=0
+ echo
+ return $retval
+}
+
+restart()
+{
+ stop
+ start
+}
+
+rh_status() {
+ echo "$name is stopped"
+ retval=3
+ return $retval
+}
+
+rh_status_q() {
+ rh_status >/dev/null 2>&1
+}
+
+case "$1" in
+ start)
+ rh_status_q && exit 0
+ start
+ ;;
+ stop)
+ rh_status_q || exit 0
+ stop
+ ;;
+ status)
+ rh_status
+ ;;
+ restart)
+ restart
+ ;;
+ reload)
+ rh_status_q || exit 7
+ restart
+ ;;
+ force_reload)
+ restart
+ ;;
+ condrestart|try-restart)
+ rh_status_q || exit 0
+ restart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
+ exit 2
+esac
+
+exit $?
+
diff --git a/scripts/ipmi_port.service b/scripts/ipmi_port.service
new file mode 100644
index 0000000..d09b37c
--- /dev/null
+++ b/scripts/ipmi_port.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=ipmiutil ipmi_port service
+After=network.target
+
+[Service]
+Type=forking
+PIDFile=/run/ipmi_port.pid
+EnvironmentFile=/usr/share/ipmiutil/ipmiutil.env
+ExecStartPre=/usr/share/ipmiutil/ipmiutil.setup
+ExecStart=/usr/sbin/ipmi_port -b
+
+[Install]
+WantedBy=multi-user.target
+
+
diff --git a/scripts/ipmi_port.sh b/scripts/ipmi_port.sh
new file mode 100755
index 0000000..85539ea
--- /dev/null
+++ b/scripts/ipmi_port.sh
@@ -0,0 +1,187 @@
+#! /bin/sh
+#
+# ipmi_port
+#
+# chkconfig: 345 91 07
+# description: ipmi_port reserves the IPMI RMCP port 623 from portmap
+# which prevents portmap from trying to use port 623.
+# This script also applies any saved IPMI thresholds, and
+# copies the bmclanpet.mib to where SNMP can find it.
+# It is recommended that this service be started for
+# all systems with ipmiutil that also have portmap.
+#
+### BEGIN INIT INFO
+# Provides: ipmi_port
+# Required-Start: $local_fs $network $remote_fs
+# Required-Stop: $local_fs $network $remote_fs
+# Default-Start: 3 4 5 3 4 5
+# Default-Stop: 0 1 2 6 0 1 2 6
+# Short-Description: ipmi_port reserves the RMCP port from portmap
+# Description: ipmi_port is used to reserve the RMCP port from portmap
+### END INIT INFO
+#
+#if [ -f /etc/init.d/functions ]; then
+# Source function library.
+#. /etc/init.d/functions
+#fi
+
+name=ipmi_port
+progdir=/usr/sbin
+prog="$progdir/$name"
+lockfile=/var/lock/subsys/$name
+portmap=/etc/init.d/portmap
+shardir=/usr/share
+mibdir=$shardir/snmp/mibs
+datadir=$shardir/ipmiutil
+vardir=/var/lib/ipmiutil
+ifout=${vardir}/ipmi_if.txt
+sensorout=${vardir}/sensor_out.txt
+threshout=${vardir}/thresh_out.txt
+# This threshold script could be created by ipmiutil sensor -p ...
+thresh="${vardir}/thresholds.sh"
+
+getpid () {
+ # This is messy if the parent script is same name as $1
+ p=`ps -ef |grep "$1" |grep -v grep |awk '{print $2}'`
+ echo $p
+}
+
+start()
+{
+ echo -n $"Starting $name: "
+ echo
+ retval=1
+ PID=0
+
+ mkdir -p $vardir
+ # if [ ! -f $ifout ]; then
+ # ${datadir}/ipmi_if.sh
+ # fi
+ if [ ! -f $sensorout ]; then
+ # Capture a snapshot of IPMI sensor data for later reuse.
+ ipmiutil sensor -q >$sensorout
+ fi
+ if [ -f $thresh ]
+ then
+ # apply saved IPMI sensor thresholds, if any
+ sh $thresh >$threshout 2>&1
+ fi
+ if [ -d ${mibdir} ]
+ then
+ # put bmclanpet MIB where SNMP can find it
+ cp -f $datadir/bmclanpet.mib ${mibdir}/BMCLAN-PET-MIB.txt
+ fi
+
+ dpc=`getpid dpcproxy`
+ if [ "x${dpc}" != "x" ]
+ then
+ echo "$name: dpcproxy is already running on port 623,"
+ echo "so $name is not needed."
+ retval=6
+ else
+ [ -x $portmap ] || exit 6
+ [ -x $prog ] || exit 5
+ $prog -b
+ retval=$?
+ if [ $retval -eq 0 ]; then
+ PID=`getpid "$prog -b"`
+ echo $PID >$lockfile
+ fi
+ fi
+ echo
+ return $retval
+}
+
+stop()
+{
+ echo -n $"Stopping $name: "
+ echo
+ retval=1
+ if [ -f $lockfile ]; then
+ p=`cat $lockfile`
+ if [ "x$p" = "x" ]; then
+ p=`getpid "$prog -b"`
+ fi
+ if [ "x$p" != "x" ]; then
+ kill $p
+ retval=$?
+ fi
+ fi
+ echo
+ if [ -d ${mibdir} ]; then
+ rm -f ${mibdir}/BMCLAN-PET-MIB.txt
+ fi
+ [ $retval -eq 0 ] && rm -f $lockfile
+ return $retval
+}
+
+restart()
+{
+ stop
+ start
+}
+
+rh_status() {
+ if [ -f $lockfile ]; then
+ p=`cat $lockfile`
+ if [ "x$p" != "x" ]; then
+ pid=`getpid $p`
+ if [ "x$pid" != "x" ]; then
+ echo "$name (pid $pid) is running..."
+ retval=0
+ else
+ echo "$name is dead but $lockfile exists"
+ retval=1
+ fi
+ else
+ echo "$name $lockfile exists but is empty"
+ retval=2
+ fi
+ else
+ echo "$name is stopped"
+ retval=3
+ fi
+ return $retval
+}
+
+rh_status_q() {
+ rh_status >/dev/null 2>&1
+}
+
+if [ ! -d /var/lock/subsys ]; then
+ lockfile=/var/run/$name.pid
+fi
+
+case "$1" in
+ start)
+ rh_status_q && exit 0
+ start
+ ;;
+ stop)
+ rh_status_q || exit 0
+ stop
+ ;;
+ status)
+ rh_status
+ ;;
+ restart)
+ restart
+ ;;
+ reload)
+ rh_status_q || exit 7
+ restart
+ ;;
+ force_reload)
+ restart
+ ;;
+ condrestart|try-restart)
+ rh_status_q || exit 0
+ restart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
+ exit 2
+esac
+
+exit $?
+
diff --git a/scripts/ipmiutil.env b/scripts/ipmiutil.env
new file mode 100644
index 0000000..e06bdda
--- /dev/null
+++ b/scripts/ipmiutil.env
@@ -0,0 +1,22 @@
+#!/bin/sh
+# These environment variables go with ipmiutil systemd services.
+#
+IDATADIR=/usr/share/ipmiutil
+
+# For ipmiutil_evt
+# Its log is /var/log/ipmiutil_evt.log
+IPMIUTILEVTARGS="-s -b -t 0"
+# to run a script for each IPMI event, use this instead:
+# IPMIUTILEVTARGS="-s -b -t 0 -r /usr/share/ipmiutil/evt.sh"
+
+# For ipmiutil_asy:
+# Its log is /var/log/ipmiutil_asy.log
+
+# For ipmi_port:
+IPORTMAP=/etc/init.d/portmap
+IMIBDIR=/usr/share/snmp/mibs
+IVARDIR=/var/lib/ipmiutil
+ISENSOROUT=${IVARDIR}/sensor_out.txt
+# This threshold script could be created by ipmiutil sensor -p ...
+ITHRESH="${IVARDIR}/thresholds.sh"
+IINITDIR=/etc/init.d
diff --git a/scripts/ipmiutil.pre b/scripts/ipmiutil.pre
new file mode 100755
index 0000000..a059dcc
--- /dev/null
+++ b/scripts/ipmiutil.pre
@@ -0,0 +1,12 @@
+#!/bin/sh
+#
+# Before starting an ipmiutil service, make sure we have a driver loaded,
+# since running driverless for multi-user is not supported.
+/usr/bin/ipmiutil cmd -k 2>/dev/null |grep "driverless" >/dev/null 2>&1
+if [ $? -eq 0 ]; then
+ rv=1
+ echo "No Linux IPMI driver loaded, aborting."
+else
+ rv=0
+fi
+exit $rv
diff --git a/scripts/ipmiutil.setup b/scripts/ipmiutil.setup
new file mode 100755
index 0000000..9087021
--- /dev/null
+++ b/scripts/ipmiutil.setup
@@ -0,0 +1,47 @@
+#! /bin/sh
+# ipmiutil ipmi_port setup script for systemd
+#
+
+. /usr/share/ipmiutil/ipmiutil.env
+
+getpid () {
+ # This is messy if the parent script is same name as $1
+ p=`ps -ef |grep "$1" |grep -v grep |awk '{print $2}'`
+ echo $p
+}
+
+isetup() {
+ retval=1
+ PID=0
+
+ mkdir -p $IVARDIR
+ if [ ! -f $ISENSOROUT ]; then
+ # Capture a snapshot of IPMI sensor data for later reuse.
+ ipmiutil sensor -q >$ISENSOROUT
+ fi
+ if [ -f $ITHRESH ]
+ then
+ # apply saved IPMI sensor thresholds, if any
+ sh $ITHRESH
+ fi
+ if [ -d ${IMIBDIR} ]
+ then
+ # put bmclanpet MIB where SNMP can find it
+ cp -f $IDATADIR/bmclanpet.mib ${IMIBDIR}/BMCLAN-PET-MIB.txt
+ fi
+
+ dpc=`getpid dpcproxy`
+ if [ "x${dpc}" != "x" ]
+ then
+ echo "dpcproxy is already running on port 623, so not needed."
+ retval=6
+ else
+ # portmap may have been replaced by portreserve
+ [ -x $IPORTMAP ] || exit 6
+ retval=0
+ fi
+ return $retval
+}
+
+isetup
+
diff --git a/scripts/ipmiutil_asy b/scripts/ipmiutil_asy
new file mode 100755
index 0000000..2899af4
--- /dev/null
+++ b/scripts/ipmiutil_asy
@@ -0,0 +1,155 @@
+#! /bin/sh
+#
+# ipmiutil_asy init script
+#
+# chkconfig: - 91 59
+# description: ipmiutil async bridge agent, listens for IPMI LAN client requests
+#
+# This starts a daemon that listens for asynchronous IPMI LAN soft-shutdown
+# requests from a remote ipmiutil reset (-o/-D). It depends upon an imb or
+# openipmi driver.
+#
+### BEGIN INIT INFO
+# Provides: ipmiutil_asy
+# Required-Start: $local_fs $remote_fs $syslog
+# Required-Stop: $local_fs $remote_fs $syslog
+# Default-Start: 3 4 5 3 4 5
+# Default-Stop: 0 1 2 6 0 1 2 6
+# Short-Description: ipmiutil async bridge agent init script
+# Description: Init script starts ipmiutil async bridge agent for remote reset
+### END INIT INFO
+#
+
+#if [ -f /etc/init.d/functions ]; then
+# Source function library.
+#. /etc/init.d/functions
+#fi
+
+name="ipmiutil_asy"
+dname="ipmiutil_asy bridge agent"
+getevtlog=/var/log/${name}.log
+lockfile=/var/lock/subsys/${name}
+prog=/usr/bin/ipmiutil
+
+
+getpid () {
+ p=`ps -ef |grep "$1" |grep -v grep |awk '{print $2}'`
+ echo $p
+}
+
+start()
+{
+ echo -n $"Starting $dname: "
+ driverok=0
+ dtype=`ipmiutil cmd -k |grep "IPMI access" |cut -f2 -d'=' |awk '{ print $1 }'`
+ if [ "x$dtype" = "xopen" ]; then
+ driverok=1
+ fi
+ if [ "x$dtype" = "ximb" ]; then
+ driverok=1
+ fi
+ if [ $driverok -eq 1 ]
+ then
+ [ -x $prog ] || exit 5
+ $prog getevt -a -b >$getevtlog &
+ retval=$?
+ PID=$!
+ if [ $retval -eq 0 ]; then
+ echo $PID >$lockfile
+ fi
+ else
+ echo "No imb or ipmi driver loaded, aborting."
+ retval=1
+ fi
+ echo
+ return $retval
+}
+
+stop()
+{
+ echo -n $"Stopping $dname: "
+ retval=1
+ if [ -f $lockfile ]; then
+ p=`cat $lockfile`
+ if [ "x$p" = "x" ]; then
+ p=`getpid "$prog getevt -a"`
+ fi
+ if [ "x$p" != "x" ]; then
+ kill $p
+ retval=$?
+ fi
+ fi
+ echo
+ [ $retval -eq 0 ] && rm -f $lockfile
+ return $retval
+}
+
+restart() {
+ stop
+ start
+}
+
+
+rh_status() {
+ if [ -f $lockfile ]; then
+ p=`cat $lockfile`
+ if [ "x$p" != "x" ]; then
+ pid=`getpid $p`
+ if [ "x$pid" != "x" ]; then
+ echo "$dname (pid $pid) is running..."
+ retval=0
+ else
+ echo "$dname is dead but $lockfile exists"
+ retval=1
+ fi
+ else
+ echo "$dname $lockfile exists but is empty"
+ retval=1
+ fi
+ else
+ echo "$dname is stopped"
+ retval=3
+ fi
+ return $retval
+}
+
+rh_status_q() {
+ rh_status >/dev/null 2>&1
+}
+
+if [ ! -d /var/lock/subsys ]; then
+ lockfile=/var/run/${name}.pid
+fi
+
+case "$1" in
+ start)
+ rh_status_q && exit 0
+ start
+ ;;
+ stop)
+ rh_status_q || exit 0
+ stop
+ ;;
+ restart)
+ restart
+ ;;
+ reload)
+ rh_status_q || exit 7
+ restart
+ ;;
+ force-reload)
+ restart
+ ;;
+ status)
+ rh_status
+ ;;
+ condrestart|try-restart)
+ rh_status_q || exit 0
+ restart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
+ exit 2
+esac
+exit $?
+
diff --git a/scripts/ipmiutil_asy.service b/scripts/ipmiutil_asy.service
new file mode 100644
index 0000000..d9eabdc
--- /dev/null
+++ b/scripts/ipmiutil_asy.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=ipmiutil Async Bridge Agent
+After=network.target
+
+[Service]
+Type=forking
+PIDFile=/run/ipmiutil_asy.pid
+EnvironmentFile=/usr/share/ipmiutil/ipmiutil.env
+ExecStartPre=/usr/share/ipmiutil/ipmiutil.pre
+ExecStart=/usr/bin/ipmiutil getevt -a -b
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/scripts/ipmiutil_evt b/scripts/ipmiutil_evt
new file mode 100755
index 0000000..e8a9e20
--- /dev/null
+++ b/scripts/ipmiutil_evt
@@ -0,0 +1,158 @@
+#! /bin/sh
+#
+# ipmiutil_evt init script
+#
+# chkconfig: - 91 59
+# description: ipmiutil event monitoring service
+#
+# This starts a daemon that listens for IPMI events. Any events are logged
+# in /var/log/ipmiutil_evt.log and also to syslog.
+# By changing RUNSCRIPT below, the specified script could also be invoked
+# whenever an event occurs. A sample event script is provided at
+# /usr/share/ipmiutil/evt.sh
+#
+### BEGIN INIT INFO
+# Provides: ipmiutil_evt
+# Required-Start: $local_fs $remote_fs $syslog
+# Required-Stop: $local_fs $remote_fs $syslog
+# Default-Start: 3 4 5 3 4 5
+# Default-Stop: 0 1 2 6 0 1 2 6
+# Short-Description: ipmiutil event monitoring init script
+# Description: Init script starts ipmiutil event monitoring service
+### END INIT INFO
+#
+
+#if [ -f /etc/init.d/functions ]; then
+# Source function library.
+#. /etc/init.d/functions
+#fi
+
+name="ipmiutil_evt"
+getevtlog=/var/log/$name.log
+lockfile=/var/lock/subsys/$name
+prog=/usr/bin/ipmiutil
+RUNSCRIPT=
+# RUNSCRIPT="-r /usr/share/ipmiutil/evt.sh"
+
+
+getpid () {
+ p=`ps -ef |grep "$1" |grep -v grep |awk '{print $2}'`
+ echo $p
+}
+
+start()
+{
+ echo -n $"Starting $name: "
+ # do not start if in driverless mode
+ ipmiutil cmd -k |grep "driverless" >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ driverok=0
+ else
+ driverok=1
+ fi
+ if [ $driverok -eq 1 ]
+ then
+ [ -x $prog ] || exit 5
+ $prog getevt -s -b -t 0 $RUNSCRIPT >$getevtlog
+ retval=$?
+ PID=$!
+ if [ $retval -eq 0 ]; then
+ PID=`getpid "$prog getevt -s"`
+ echo $PID >$lockfile
+ fi
+ else
+ echo "No imb or ipmi driver loaded, aborting."
+ retval=1
+ fi
+ echo
+ return $retval
+}
+
+stop()
+{
+ echo -n $"Stopping $name: "
+ retval=1
+ if [ -f $lockfile ]; then
+ p=`cat $lockfile`
+ if [ "x$p" = "x" ]; then
+ p=`getpid "$prog getevt -s"`
+ fi
+ if [ "x$p" != "x" ]; then
+ kill $p
+ retval=$?
+ fi
+ fi
+ echo
+ [ $retval -eq 0 ] && rm -f $lockfile
+ return $retval
+}
+
+restart() {
+ stop
+ start
+}
+
+
+rh_status() {
+ if [ -f $lockfile ]; then
+ p=`cat $lockfile`
+ if [ "x$p" != "x" ]; then
+ pid=`getpid $p`
+ if [ "x$pid" != "x" ]; then
+ echo "$name (pid $pid) is running..."
+ retval=0
+ else
+ echo "$name is dead but $lockfile exists"
+ retval=1
+ fi
+ else
+ echo "$name $lockfile exists but is empty"
+ retval=1
+ fi
+ else
+ echo "$name is stopped"
+ retval=3
+ fi
+ return $retval
+}
+
+rh_status_q() {
+ rh_status >/dev/null 2>&1
+}
+
+if [ ! -d /var/lock/subsys ]; then
+ lockfile=/var/run/$name.pid
+fi
+
+case "$1" in
+ start)
+ rh_status_q && exit 0
+ start
+ ;;
+ stop)
+ rh_status_q || exit 0
+ stop
+ ;;
+ restart)
+ restart
+ ;;
+ reload)
+ rh_status_q || exit 7
+ restart
+ ;;
+ force-reload)
+ restart
+ ;;
+ status)
+ rh_status
+ ;;
+ condrestart|try-restart)
+ rh_status_q || exit 0
+ restart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
+ exit 2
+esac
+exit $?
+
diff --git a/scripts/ipmiutil_evt.service b/scripts/ipmiutil_evt.service
new file mode 100644
index 0000000..3cd5b6d
--- /dev/null
+++ b/scripts/ipmiutil_evt.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=ipmiutil Event Daemon
+After=network.target
+
+[Service]
+Type=forking
+PIDFile=/run/ipmiutil_evt.pid
+EnvironmentFile=/usr/share/ipmiutil/ipmiutil.env
+ExecStartPre=/usr/share/ipmiutil/ipmiutil.pre
+ExecStart=/usr/bin/ipmiutil getevt $IPMIUTILEVTARGS
+
+[Install]
+WantedBy=multi-user.target
+
+
diff --git a/scripts/ipmiutil_wdt b/scripts/ipmiutil_wdt
new file mode 100755
index 0000000..6c2bd73
--- /dev/null
+++ b/scripts/ipmiutil_wdt
@@ -0,0 +1,146 @@
+#! /bin/sh
+#
+# wdt Enable & reset the IPMI watchdog timer via cron
+#
+# chkconfig: - 91 59
+# description: wdt is a utility from ipmiutil.sf.net to configure the \
+# IPMI watchdog timer.
+#
+# It enables watchdog for 90 second timeout, reset every 1 min (60 sec).
+# It uses the cron daemon which reads files from /etc/cron.d
+# Note that the $crond_sh variable is different for RedHat & SuSE.
+#
+### BEGIN INIT INFO
+# Provides: ipmiutil_wdt
+# Required-Start: $local_fs $remote_fs $syslog
+# Required-Stop: $local_fs $remote_fs $syslog
+# Default-Start: 3 4 5 3 4 5
+# Default-Stop: 0 1 2 6 0 1 2 6
+# Short-Description: ipmiutil watchdog timer init script
+# Description: Init script to enable and reset ipmiutil watchdog timer via cron
+### END INIT INFO
+#
+#if [ -f /etc/init.d/functions ]; then
+# Source function library.
+#. /etc/init.d/functions
+#fi
+
+name=ipmiutil_wdt
+prog="/usr/bin/ipmiutil wdt"
+wdtcron=/etc/cron.d/wdt
+LOCKFILE=/var/lock/subsys/$name
+wdtlog=/var/log/$name
+#tmpcron=/tmp/wdtcron.$$
+# tmpcron2=/tmp/wdtcron2.$$
+
+start() {
+ echo -n $"Starting $prog: "
+ echo
+ # do not start if in driverless mode
+ ipmiutil cmd -k |grep "driverless" >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ driverok=0
+ else
+ driverok=1
+ fi
+ if [ $driverok -eq 0 ]
+ then
+ echo "No ipmi driver loaded, aborting."
+ RETVAL=1
+ else
+ # configure the watchdog for a 90 second timeout
+ $prog -e -t 90 >$wdtlog
+ RETVAL=$?
+ if [ $RETVAL -eq 0 ]
+ then
+ # restart the watchdog every 60 seconds via crontab (skip)
+ # cat - <<%%% >$tmpcron
+#* * * * * $prog -r
+#%%%
+ # crontab $tmpcron
+ # RETVAL=$?
+ # restart the watchdog every 60 seconds via /etc/cron.d
+ cat - <<%%% >$wdtcron
+* * * * * root $prog -r
+%%%
+ # make crond re-read the /etc/cron.d
+ $crond_sh restart >>$wdtlog
+ touch $LOCKFILE
+ fi
+ fi
+ echo
+ return $RETVAL
+}
+
+stop() {
+ echo -n $"Stopping $prog: "
+ echo
+ # first disable the watchdog
+ $prog -d >>$wdtlog
+ RETVAL=$?
+ # now remove the wdt cron job
+ # crontab -l >$tmpcron
+ # grep -v $prog $tmpcron |grep -v "^#" >$tmpcron2
+ # crontab $tmpcron2
+ rm -f $wdtcron
+ # make crond re-read the /etc/cron.d
+ $crond_sh restart >>$wdtlog
+ rm -f ${LOCKFILE}
+ echo
+ return $RETVAL
+}
+
+restart() {
+ stop
+ start
+}
+
+get_status() {
+ $prog
+ if [ -f ${LOCKFILE} ]; then
+ if [ -f $wdtcron ]; then
+ echo "$name is running..."
+ retval=0
+ else
+ echo "$name is not running but ${LOCKFILE} exists"
+ retval=1
+ fi
+ else
+ echo "$name is stopped"
+ retval=3
+ fi
+ return $retval
+}
+
+# Begin mainline script here
+if [ -f /etc/redhat-release ]
+then
+ crond_sh=/etc/init.d/crond
+else
+ # SuSE, MontaVista, etc.
+ crond_sh=/etc/init.d/cron
+fi
+if [ ! -d /var/lock/subsys ]; then
+ LOCKFILE=/var/run/$name.pid
+fi
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ status)
+ get_status
+ ;;
+ restart)
+ restart
+ ;;
+ reload)
+ restart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|reload}"
+ exit 1
+esac
diff --git a/scripts/ipmiutil_wdt.cmd b/scripts/ipmiutil_wdt.cmd
new file mode 100755
index 0000000..6c74c20
--- /dev/null
+++ b/scripts/ipmiutil_wdt.cmd
@@ -0,0 +1,10 @@
+REM ipmiutil_wdt.cmd
+REM wdt Reset the IPMI watchdog timer every NSEC seconds
+
+set NSEC 60
+
+:WDTLOOP
+ipmiutil wdt -r
+sleep %NSEC%
+goto WDTLOOP
+
diff --git a/scripts/ipmiutil_wdt.service b/scripts/ipmiutil_wdt.service
new file mode 100644
index 0000000..6f67fad
--- /dev/null
+++ b/scripts/ipmiutil_wdt.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=ipmiutil Watchdog Timer Service using cron
+After=network.target
+
+[Service]
+ExecStart=/usr/share/ipmiutil/ipmiutil_wdt start
+ExecStop=/usr/share/ipmiutil/ipmiutil_wdt stop
+ExecReload=/usr/share/ipmiutil/ipmiutil_wdt restart
+RemainAfterExit=1
+
+[Install]
+WantedBy=multi-user.target
+
+
diff --git a/scripts/ireset b/scripts/ireset
new file mode 100755
index 0000000..86926a3
--- /dev/null
+++ b/scripts/ireset
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil reset $*
diff --git a/scripts/ireset.cmd b/scripts/ireset.cmd
new file mode 100644
index 0000000..a0d07af
--- /dev/null
+++ b/scripts/ireset.cmd
@@ -0,0 +1 @@
+ipmiutil reset %*
diff --git a/scripts/isel b/scripts/isel
new file mode 100755
index 0000000..ef7f958
--- /dev/null
+++ b/scripts/isel
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil sel $*
diff --git a/scripts/isel.cmd b/scripts/isel.cmd
new file mode 100644
index 0000000..9aba3b9
--- /dev/null
+++ b/scripts/isel.cmd
@@ -0,0 +1 @@
+ipmiutil sel %*
diff --git a/scripts/isensor b/scripts/isensor
new file mode 100755
index 0000000..781f1dc
--- /dev/null
+++ b/scripts/isensor
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil sensor $*
diff --git a/scripts/isensor.cmd b/scripts/isensor.cmd
new file mode 100644
index 0000000..9441517
--- /dev/null
+++ b/scripts/isensor.cmd
@@ -0,0 +1 @@
+ipmiutil sensor %*
diff --git a/scripts/iserial b/scripts/iserial
new file mode 100755
index 0000000..ca18c35
--- /dev/null
+++ b/scripts/iserial
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil serial $*
diff --git a/scripts/iserial.cmd b/scripts/iserial.cmd
new file mode 100644
index 0000000..4af066f
--- /dev/null
+++ b/scripts/iserial.cmd
@@ -0,0 +1 @@
+ipmiutil serial %*
diff --git a/scripts/isol b/scripts/isol
new file mode 100755
index 0000000..5cba66d
--- /dev/null
+++ b/scripts/isol
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil sol $*
diff --git a/scripts/isol.cmd b/scripts/isol.cmd
new file mode 100644
index 0000000..73222bd
--- /dev/null
+++ b/scripts/isol.cmd
@@ -0,0 +1 @@
+ipmiutil sol %*
diff --git a/scripts/iwdt b/scripts/iwdt
new file mode 100755
index 0000000..129c265
--- /dev/null
+++ b/scripts/iwdt
@@ -0,0 +1,2 @@
+#!/bin/sh
+ipmiutil wdt $*
diff --git a/scripts/iwdt.cmd b/scripts/iwdt.cmd
new file mode 100644
index 0000000..fe5d4e0
--- /dev/null
+++ b/scripts/iwdt.cmd
@@ -0,0 +1 @@
+ipmiutil wdt %*
diff --git a/scripts/setlib.sh b/scripts/setlib.sh
new file mode 100755
index 0000000..eca184e
--- /dev/null
+++ b/scripts/setlib.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+# setup sequence for ipmiutil
+#
+# Resolve whatever libcrypto.so is present to the one that ipmiutil
+# was built to reference.
+# The default build on RHEL4.4 references libcrypto.so.4
+libver=4
+found=0
+
+# check where the libcrypto.so is located
+dirs="/usr/lib64 /lib64 /usr/lib /lib"
+for d in $dirs
+do
+ libt=`ls $d/libcrypto.so.0.* 2>/dev/null |tail -n1`
+ if [ "x$libt" != "x" ]; then
+ # Found a libcrypto.so
+ libcry=$libt
+ libdir=$d
+ found=1
+ libnew=$libdir/libcrypto.so.$libver
+ echo "libcry=$libcry libdir=$libdir libnew=$libnew"
+ if [ ! -f $libnew ]; then
+ # Need a sym-link to resolve it
+ echo "ln -s $libcry $libnew"
+ ln -s $libcry $libnew
+ ldconfig
+ fi
+ fi
+done
+
+if [ $found -eq 0 ]; then
+ echo "libcrypto.so not found, install openssl rpm"
+ rv=1
+else
+ rv=0
+fi
+exit $rv
+
diff --git a/scripts/showsel.mc b/scripts/showsel.mc
new file mode 100644
index 0000000..6efd47c
--- /dev/null
+++ b/scripts/showsel.mc
@@ -0,0 +1,29 @@
+; // This is the header section.
+
+MessageIdTypedef=DWORD
+
+SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
+ Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
+ Warning=0x2:STATUS_SEVERITY_WARNING
+ Error=0x3:STATUS_SEVERITY_ERROR
+ )
+
+FacilityNames=(System=0x0:FACILITY_SYSTEM
+ Runtime=0x2:FACILITY_RUNTIME
+ Stubs=0x3:FACILITY_STUBS
+ Io=0x4:FACILITY_IO_ERROR_CODE
+ )
+
+LanguageNames=(English=0x409:MSG00409)
+
+; // The following are message definitions.
+
+MessageId=0x101
+Severity=Informational
+Facility=System
+SymbolicName=MSG_SEL_RECORD
+Language=English
+SEL: %1
+.
+
+
diff --git a/scripts/showsel.reg b/scripts/showsel.reg
new file mode 100644
index 0000000..036876f
--- /dev/null
+++ b/scripts/showsel.reg
@@ -0,0 +1,10 @@
+REGEDIT4
+
+[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\showsel]
+"EventMessageFile"="%SystemRoot%\\system32\\showselmsg.dll"
+"TypesSupported"=dword:00000007
+"IndexFile"="%ipmiutildir%\\sel.idx"
+
+[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Schedule]
+"AtTaskMaxHours"=dword:00000000
+
diff --git a/scripts/showselun.reg b/scripts/showselun.reg
new file mode 100644
index 0000000..8b4622c
--- /dev/null
+++ b/scripts/showselun.reg
@@ -0,0 +1,4 @@
+REGEDIT4
+
+[-HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\showsel]
+
diff --git a/scripts/startsol b/scripts/startsol
new file mode 100755
index 0000000..8884e4d
--- /dev/null
+++ b/scripts/startsol
@@ -0,0 +1,16 @@
+# start a serial-over-lan session
+# BMC port 0x26f (=623).
+#
+if [ $# -gt 0 ]
+then
+ host=$1
+else
+ host=telco64
+fi
+echo "Starting Serial-Over-LAN session to $host ..."
+
+# Use isolconsole application for IPMI LAN 2.0 SOL
+# If IPMI 1.5, use dpccli.
+
+ipmiutil sol -a -N $host
+
diff --git a/scripts/uninstall.cmd b/scripts/uninstall.cmd
new file mode 100644
index 0000000..33ebaed
--- /dev/null
+++ b/scripts/uninstall.cmd
@@ -0,0 +1,31 @@
+@echo off
+REM uninstall Windows ipmiutil on this system
+REM uninstall the DLLs, registry entries, and stop the checksel task
+set installdir=%SystemDrive%\Program Files\sourceforge\ipmiutil
+
+"%installdir%\showselun.reg"
+del /Q %SystemRoot%\system32\showsel.dll
+
+REM remove %installdir% from the PATH
+set pathkey="HKLM\System\CurrentControlSet\Control\Session Manager\Environment"
+REM reg query %pathkey% /v Path |findstr Path
+set NEWPATH=%PATH:;%installdir%=%
+reg add %pathkey% /v Path /t REG_EXPAND_SZ /d "%NEWPATH%"
+set PATH=%NEWPATH%
+
+REM type "%installdir%\checksel.id"
+FOR /F "usebackq tokens=1*" %%i IN (`type "%installdir%\checksel.id"`) DO call :SETAT %%i %%j
+goto :NEXTJ
+
+:SETAT
+REM %1 %2 %3 %4 %5 %6 %7 %8
+REM Added a new job with job ID = 2
+echo %1 %2 %3 %4 %5 %6 %7 %8 %9
+set ATJOB=%8
+echo at %ATJOB% /DELETE
+at %ATJOB% /DELETE
+goto :EOF
+
+:NEXTJ
+
+del /Q "%installdir%\*.*"
diff --git a/scripts/uninstall.vbs b/scripts/uninstall.vbs
new file mode 100644
index 0000000..b392a46
--- /dev/null
+++ b/scripts/uninstall.vbs
@@ -0,0 +1,63 @@
+' This VBScript should run before any files are actually removed
+
+On Error Resume Next
+
+Set sh = CreateObject("WScript.Shell")
+' Set fso = CreateObject("Scripting.FileSystemObject")
+
+Dim installer : Set installer = Nothing
+Set installer = CreateObject("WindowsInstaller.Installer")
+
+'key = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot"
+'SysLoc = sh.RegRead(key) & "\system32"
+
+' remove the showsel EventLog source entries
+keybase = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\showsel"
+key1 = keybase & "\EventMessageFile"
+key2 = keybase & "\TypesSupported"
+sh.RegDelete key1
+sh.RegDelete key2
+sh.RegDelete keybase
+
+' Find out where our files were installed
+If(IsEmpty(Session)) Then
+ 'Not running from within installer. Source path is current directory.
+ InstallLoc = sh.CurrentDirectory
+Else
+ 'Running inside the installer, use CustomActionData "[TARGETDIR]".
+ ' InstallLoc = installer.ProductInfo(productCode, "InstallLocation")
+ InstallLoc = Session.Property("CustomActionData")
+ If(IsEmpty(InstallLoc)) Then
+ InstallLoc = "C:\Program Files\sourceforge\ipmiutil"
+ End If
+End If
+' wscript.echo "InstallLoc=" & InstallLoc
+
+' Remove the InstallLoc from the Environment Path
+key3 = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\Path"
+EnvPath = sh.RegRead(key3)
+' wscript.echo "EnvPath= " & EnvPath
+
+' Calculates strStartAt which cuts the strSearchFor value from the path
+' strSearchFor = ";C:\program files\intel\ipmirastools"
+strSearchFor = ";" & InstallLoc
+newPath = EnvPath
+iStartAt = "0"
+strSearchForLen=len(strSearchFor)
+strStartAt = inStr(lCase(newPath), lCase(strSearchFor))
+If (strStartAt > "0") then
+ iStartAt = (strStartAt-1)
+' wscript.echo "strStartAt= " & strStartAt & " iStartAt= " & iStartAt
+
+' Builds the new Path
+' Joins the Values to the left and right of strSearchFor
+ strTotalLen=len(newPath)
+ newPathLeft=left(newPath,iStartAt)
+ newPathRight=right(newPath, (strTotalLen-strSearchForLen-iStartAt))
+ newPath=newPathLeft + newPathRight
+end if
+
+' wscript.echo "newPath= " & newPath
+sh.RegWrite key3, newPath, "REG_EXPAND_SZ"
+
+
diff --git a/setver b/setver
new file mode 100755
index 0000000..054798a
--- /dev/null
+++ b/setver
@@ -0,0 +1,271 @@
+#!/bin/sh
+# setver - set version number for ipmiutil package
+#
+# Usage: setver [version] [doinc?=y/n/r]
+# if [version] is specified, assume increment, unless
+# [doinc?] is 'n'.
+# if [doinc?] is 'r', reverse increment (decrement).
+#
+ver=2.9.3
+rel=1
+tmped=/tmp/edver.tmp
+tmpspec=/tmp/edspec.tmp
+cmdf=/tmp/cmd.tmp
+skipinc=0
+reverseinc=0
+v12=`echo $ver |cut -f1,2 -d'.'`
+v3=`echo $ver |cut -f3 -d'.'`
+vras=`echo $ver |sed -e 's/\.//g'`
+
+if [ $# -gt 0 ]
+then
+ ver=$1
+ if [ "$2" = "n" ]
+ then
+ # no, skip incrementing the versions
+ skipinc=1
+ else
+ if [ "$2" = "r" ]
+ then
+ # r = reverse increment
+ reverseinc=1
+ else
+ # yes, increment the versions
+ skipinc=0
+ fi
+ fi
+fi
+
+distro=`echo $MACHTYPE |cut -d'-' -f2`
+if [ "$distro" = "suse" ]
+then
+ pkgdir=/usr/src/packages
+else
+ if [ "$distro" = "hardhat" ]
+ then
+ pkgdir=/usr/src/montavista
+ else
+ # usu redhat if here
+ pkgdir=/usr/src/$distro
+ fi
+fi
+
+cat - <<%%% >$tmped
+1
+/^AM_INIT_AUTOMAKE(
+c
+AM_INIT_AUTOMAKE(ipmiutil,$ver)
+.
+w
+q
+%%%
+if [ -f configure.in ]; then
+ ed configure.in <$tmped
+else
+ sed -i "/INIT_AUTOMAKE(ipmiutil/cAM_INIT_AUTOMAKE(ipmiutil,$ver)" configure.ac
+fi
+
+cat - <<%%% >$tmped
+1
+/^PKGDIR=
+c
+PKGDIR=${pkgdir}
+.
+w
+q
+%%%
+ed Makefile.am <$tmped
+
+cat - <<%%% >$tmped
+1
+/^VERSION =
+c
+VERSION = $ver
+.
+w
+q
+%%%
+ed configure <$tmped
+
+cat - <<%%% >$tmpspec
+1
+/^Version:
+c
+Version: ${ver}
+.
+/^Release:
+c
+Release: ${rel}%{?dist}
+.
+w
+q
+%%%
+ed doc/ipmiutil.spec <$tmpspec
+
+# mk_* - scripts used for my local mods
+cat - <<%%% >$tmped
+1
+/^iver
+c
+iver=${ver}
+.
+w
+q
+%%%
+if [ -f ../buildipmiutil.sh ]
+then
+ ed ../buildipmiutil.sh <$tmped
+fi
+
+if [ -f ../win32/src/mkzip.bat ]
+then
+ cat - <<%%% >$tmped
+1
+/^set pkgver
+c
+set pkgver=${ver}
+.
+w
+q
+%%%
+ ed ../win32/src/mkzip.bat <$tmped
+fi
+if [ -f ../win32/src/mkzip64.bat ]; then
+ ed ../win32/src/mkzip64.bat <$tmped
+fi
+
+if [ -f ../win32/mkraszip.bat ]
+then
+ cat - <<%%% >$tmped
+1
+/^set pkgver
+c
+set pkgver=${vras}
+.
+w
+q
+%%%
+ ed ../win32/mkraszip.bat <$tmped
+fi
+
+if [ -f doc/UserGuide ]
+then
+ cat - <<%%% >$tmped
+1
+/VERSION
+c
+ VERSION ${ver}
+.
+w
+q
+%%%
+ ed doc/UserGuide <$tmped
+fi
+
+if [ -f ../../ipmimisc/buildmisc.sh ]
+then
+ cat - <<%%% >$tmped
+1
+/^utilver
+c
+utilver=${ver}
+.
+w
+q
+%%%
+ ed ../../ipmimisc/buildmisc.sh <$tmped
+fi
+
+if [ -f debian/changelog ]; then
+ rdate=`date -R`
+ cat - <<%%% >$tmped
+1
+i
+ipmiutil (${ver}-${rel}) unstable; urgency=low
+
+ * New upstream version.
+
+ -- Andy Cress <arcress@users.sourceforge.net> ${rdate}
+
+.
+w
+q
+%%%
+ ed debian/changelog <$tmped
+fi
+
+cmdc="ialarms.c icmd.c iconfig.c ievents.c ifru.c igetevent.c ihealth.c
+ ilan.c ireset.c isel.c isensor.c iserial.c isol.c iwdt.c
+ ifruset.c oem_sun.c ipicmg.c ifirewall.c oem_dell.c itsol.c
+ idcmi.c iseltime.c oem_supermicro.c
+ iekanalyzer.c ifwum.c ihpm.c idiscover.c"
+
+if [ $skipinc -ne 1 ]
+then
+ # set each of the utility progver values to the specified version.
+ relnote=/tmp/ipmiutil.rel
+ #utilc="ipmiutil.c ialarms.c icmd.c iconfig.c igetevent.c ihealth.c
+ #ifru.c ilan.c ireset.c isensor.c isel.c iserial.c isol.c iwdt.c
+ #ievents.c idiscover.c ipmi_port.c"
+ utilc="ipmiutil.c $cmdc ipmi_port.c"
+ echo $utilc >$cmdf
+
+ cd util
+ echo " ipmiutil-$ver contains:" >$relnote
+ for f in $utilc
+ do
+ fver=`grep "progver = " $f |cut -f2 -d'=' |cut -f2 -d'"'`
+ fver1=`echo $fver |cut -f1 -d'.'`
+ fver2=`echo $fver |cut -f2 -d'.'`
+ if [ $reverseinc -eq 1 ]
+ then
+ fvernew=${fver1}.`expr $fver2 - 1`
+ else
+ # fvernew=${fver1}.`expr $fver2 + 1`
+ # use the specified version from above
+ fvernew=${v12}${v3}
+ fi
+ tmpf=/tmp/$f.new
+ tag=`grep "progname = " $f |cut -f2 -d'=' |cut -f2 -d'"'`
+ alias=`grep "int argc" $f |head -n1 |cut -f1 -d'(' |awk '{print $2}' |sed -e 's/i_/ipmiutil /'`
+ if [ "$f" = "ipmi_port.c" ]; then
+ do_incr=0
+ tag=ipmi_port
+ alias=ipmi_port
+ elif [ "$f" = "iseltime.c" ]; then
+ alias=iseltime
+ elif [ "$f" = "ifruset.c" ]; then
+ alias=ifruset
+ elif [ "$f" = "idiscover.c" ]; then
+ do_incr=0
+ elif [ "$f" = "iekanalyzer.c" ]; then
+ do_incr=0
+ elif [ "$f" = "ifwum.c" ]; then
+ do_incr=0
+ elif [ "$f" = "ihpm.c" ]; then
+ do_incr=0
+ else
+ do_incr=1
+ fi
+ f1=`echo $f |cut -f1 -d'.'`
+ if [ $do_incr -eq 0 ]
+ then
+ # don't update the version
+ fvernew=$fver
+ echo "$tag progver: $fvernew"
+ echo " $tag ($alias) ver $fvernew" >>$relnote
+ else
+ # update the version automatically
+ echo "$tag progver: $fvernew"
+ echo " $tag ($alias) ver $fvernew" >>$relnote
+ sed -e "s/progver = .${fver}/progver = \"${fvernew}/" $f >$tmpf
+ cp -f $tmpf $f
+ fi
+ done
+ cd ..
+ cat $relnote >>ChangeLog
+fi
+
+echo ""
+echo "Version changed to $ver, now run beforeconf.sh, then ./configure"
+
diff --git a/stamp-h b/stamp-h
new file mode 100644
index 0000000..9788f70
--- /dev/null
+++ b/stamp-h
@@ -0,0 +1 @@
+timestamp
diff --git a/stamp-h.in b/stamp-h.in
new file mode 100644
index 0000000..9788f70
--- /dev/null
+++ b/stamp-h.in
@@ -0,0 +1 @@
+timestamp
diff --git a/test/Kconfig b/test/Kconfig
new file mode 100644
index 0000000..0c24991
--- /dev/null
+++ b/test/Kconfig
@@ -0,0 +1,12 @@
+#
+# DOPANIC device configuration
+#
+
+menu "DOPANIC"
+config DOPANIC
+ tristate 'Do Panic'
+ help
+ This causes a Linux kernel panic when loaded.
+ If unsure, say N.
+
+endmenu
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..2c5ba97
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,325 @@
+################################################################################
+#
+#
+# Copyright(c) 1999 - 2007 Intel Corporation. All rights reserved.
+#
+# 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 WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. 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.
+#
+# The full GNU General Public License is included in this distribution in the
+# file called LICENSE.
+#
+# Contact Information:
+# Linux NICS <linux.nics@intel.com>
+# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+#
+################################################################################
+MYDIR =$(shell echo `pwd`)
+
+###########################################################################
+# Driver files
+
+# core driver files
+CFILES = dopanic_drv.c
+HFILES =
+ifeq (,$(BUILD_KERNEL))
+BUILD_KERNEL=$(shell uname -r)
+endif
+
+###########################################################################
+# Environment tests
+
+# Kernel Search Path
+# All the places we look for kernel source
+KSP := /lib/modules/$(BUILD_KERNEL)/source \
+ /lib/modules/$(BUILD_KERNEL)/build \
+ /usr/src/linux-$(BUILD_KERNEL) \
+ /usr/src/linux-$($(BUILD_KERNEL) | sed 's/-.*//') \
+ /usr/src/kernel-headers-$(BUILD_KERNEL) \
+ /usr/src/kernel-source-$(BUILD_KERNEL) \
+ /usr/src/linux-$($(BUILD_KERNEL) | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \
+ /usr/src/linux
+
+# prune the list down to only values that exist
+# and have an include/linux sub-directory
+test_dir = $(shell [ -e $(dir)/include/linux ] && echo $(dir))
+KSP := $(foreach dir, $(KSP), $(test_dir))
+
+# we will use this first valid entry in the search path
+ifeq (,$(KSRC))
+ KSRC := $(firstword $(KSP))
+endif
+
+ifeq (,$(KSRC))
+ $(error Linux kernel source not found)
+else
+ifeq (/lib/modules/$(shell uname -r)/source, $(KSRC))
+ KOBJ := /lib/modules/$(shell uname -r)/build
+else
+ KOBJ := $(KSRC)
+endif
+endif
+
+# check for version.h and autoconf.h for running kernel in /boot (SUSE)
+ifneq (,$(wildcard /boot/vmlinuz.version.h))
+ VERSION_FILE := /boot/vmlinuz.version.h
+ CONFIG_FILE := /boot/vmlinuz.autoconf.h
+ KVER := $(shell $(CC) $(CFLAGS) -E -dM $(VERSION_FILE) | \
+ grep UTS_RELEASE | awk '{ print $$3 }' | sed 's/\"//g')
+ ifeq ($(KVER),$(shell uname -r))
+ # set up include path to override headers from kernel source
+ x:=$(shell rm -rf include)
+ x:=$(shell mkdir -p include/linux)
+ x:=$(shell cp /boot/vmlinuz.version.h include/linux/version.h)
+ x:=$(shell cp /boot/vmlinuz.autoconf.h include/linux/autoconf.h)
+ CFLAGS += -I./include
+ else
+ VERSION_FILE := $(KOBJ)/include/linux/version.h
+ CONFIG_FILE := $(KSRC)/include/linux/autoconf.h
+ endif
+else
+ VERSION_FILE := $(KOBJ)/include/linux/version.h
+ CONFIG_FILE := $(KSRC)/include/linux/autoconf.h
+endif
+
+ifeq (,$(wildcard $(VERSION_FILE)))
+ $(error Linux kernel source not configured - missing version.h)
+endif
+
+ifeq (,$(wildcard $(CONFIG_FILE)))
+ $(error Linux kernel source not configured - missing config.h)
+endif
+
+# pick a compiler
+ifneq (,$(findstring egcs-2.91.66, $(shell cat /proc/version)))
+ CC := kgcc gcc cc
+else
+ CC := gcc cc
+endif
+test_cc = $(shell $(cc) --version > /dev/null 2>&1 && echo $(cc))
+CC := $(foreach cc, $(CC), $(test_cc))
+CC := $(firstword $(CC))
+ifeq (,$(CC))
+ $(error Compiler not found)
+endif
+
+# we need to know what platform the driver is being built on
+# some additional features are only built on Intel platforms
+ARCH := $(shell uname -m | sed 's/i.86/i386/')
+ifeq ($(ARCH),alpha)
+ CFLAGS += -ffixed-8 -mno-fp-regs
+endif
+ifeq ($(ARCH),x86_64)
+ CFLAGS += -mcmodel=kernel -mno-red-zone
+endif
+ifeq ($(ARCH),ppc)
+ CFLAGS += -msoft-float
+endif
+ifeq ($(ARCH),ppc64)
+ CFLAGS += -m64 -msoft-float
+ LDFLAGS += -melf64ppc
+endif
+
+# standard flags for module builds
+CFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall
+CFLAGS += -I$(KSRC)/include -I.
+CFLAGS += $(shell [ -f $(KSRC)/include/linux/modversions.h ] && \
+ echo "-DMODVERSIONS -DEXPORT_SYMTAB \
+ -include $(KSRC)/include/linux/modversions.h")
+
+CFLAGS += $(CFLAGS_EXTRA)
+#ifeq (,$(shell echo $(CFLAGS_EXTRA) | grep NAPI))
+#CFLAGS += -DE1000_NO_NAPI
+#CFLAGS_EXTRA += -DE1000_NO_NAPI
+#endif
+
+RHC := $(KSRC)/include/linux/rhconfig.h
+ifneq (,$(wildcard $(RHC)))
+ # 7.3 typo in rhconfig.h
+ ifneq (,$(shell $(CC) $(CFLAGS) -E -dM $(RHC) | grep __module__bigmem))
+ CFLAGS += -D__module_bigmem
+ endif
+endif
+
+# get the kernel version - we use this to find the correct install path
+KVER := $(shell $(CC) $(CFLAGS) -E -dM $(VERSION_FILE) | grep UTS_RELEASE | \
+ awk '{ print $$3 }' | sed 's/\"//g')
+
+KKVER := $(shell echo $(KVER) | \
+ awk '{ if ($$0 ~ /2\.[4-9]\./) print "1"; else print "0"}')
+# ifeq ($(KKVER), 0)
+# $(error *** Aborting the build. \
+# *** This driver is not supported on kernel versions older than 2.4.0)
+# endif
+
+# set the install path
+INSTDIR := /lib/modules/$(KVER)/kernel/drivers/char
+
+# look for SMP in config.h
+SMP := $(shell $(CC) $(CFLAGS) -E -dM $(CONFIG_FILE) | \
+ grep CONFIG_SMP | awk '{ print $$3 }')
+ifneq ($(SMP),1)
+ SMP := 0
+endif
+
+ifneq ($(SMP),$(shell uname -a | grep SMP > /dev/null 2>&1 && echo 1 || echo 0))
+ $(warning ***)
+ ifeq ($(SMP),1)
+ $(warning *** Warning: kernel source configuration (SMP))
+ $(warning *** does not match running kernel (UP))
+ else
+ $(warning *** Warning: kernel source configuration (UP))
+ $(warning *** does not match running kernel (SMP))
+ endif
+ $(warning *** Continuing with build,)
+ $(warning *** resulting driver may not be what you want)
+ $(warning ***)
+endif
+
+ifeq ($(SMP),1)
+ CFLAGS += -D__SMP__
+endif
+
+# Any special handling for this driver
+
+###########################################################################
+# 2.4.x & 2.6.x Specific rules
+
+K_VERSION:=$(shell uname -r | cut -c1-3 | sed 's/2\.[56]/2\.6/')
+
+ifeq ($(K_VERSION), 2.6)
+
+# Makefile for 2.6.x kernel
+TARGET = dopanic.ko
+
+# man page
+MANSECTION = 8
+MANFILE = $(TARGET:.ko=.$(MANSECTION))
+# ifeq (,$(wildcard /etc/SuSE-release))
+# CFLAGS_DOPANIC += -I$(KSRC)/include/asm/mach-generic
+# CFLAGS_EXTRA += $(CFLAGS_DOPANIC)
+# endif
+
+ifneq ($(PATCHLEVEL),)
+EXTRA_CFLAGS += $(CFLAGS_EXTRA)
+obj-m += dopanic.o
+dopanic-objs := $(CFILES:.c=.o)
+else
+default:
+ifeq ($(KOBJ),$(KSRC))
+ make -C $(KSRC) V=1 SUBDIRS=$(shell pwd) modules
+else
+ make -C $(KSRC) V=1 O=$(KOBJ) SUBDIRS=$(shell pwd) modules
+endif
+endif
+
+else # ifeq ($(K_VERSION),2.6)
+
+# Makefile for 2.4.x kernel
+TARGET = dopanic
+
+# man page
+MANSECTION = 8
+MANFILE = $(TARGET:.o=.$(MANSECTION))
+
+# Get rid of compile warnings in kernel header files from SuSE
+ifneq (,$(wildcard /etc/SuSE-release))
+ CFLAGS += -Wno-sign-compare -fno-strict-aliasing
+endif
+
+# Get rid of compile warnings in kernel header files from fedora
+ifneq (,$(wildcard /etc/fedora-release))
+ CFLAGS += -fno-strict-aliasing
+endif
+
+.SILENT: $(TARGET)
+$(TARGET): $(filter-out $(TARGET), $(CFILES:.c=.o))
+ $(LD) $(LDFLAGS) -r $^ -o $@
+ echo; echo
+ echo "**************************************************"
+ echo "** $(TARGET) built for $(KVER)"
+ echo -n "** SMP "
+ if [ "$(SMP)" = "1" ]; \
+ then echo "Enabled"; else echo "Disabled"; fi
+ echo "**************************************************"
+ echo
+
+$(CFILES:.c=.o): $(HFILES) Makefile
+default:
+ echo "** CFLAGS = $(CFLAGS)"
+ make
+
+endif # ifeq ($(K_VERSION),2.6)
+
+ifeq (,$(MANDIR))
+ # find the best place to install the man page
+ MANPATH := $(shell (manpath 2>/dev/null || echo $MANPATH) | sed 's/:/ /g')
+ ifneq (,$(MANPATH))
+ # test based on inclusion in MANPATH
+ test_dir = $(findstring $(dir), $(MANPATH))
+ else
+ # no MANPATH, test based on directory existence
+ test_dir = $(shell [ -e $(dir) ] && echo $(dir))
+ endif
+ # our preferred install path
+ # should /usr/local/man be in here ?
+ MANDIR := /usr/share/man /usr/man
+ MANDIR := $(foreach dir, $(MANDIR), $(test_dir))
+ MANDIR := $(firstword $(MANDIR))
+endif
+ifeq (,$(MANDIR))
+ # fallback to /usr/man
+ MANDIR := /usr/man
+endif
+
+# depmod version for rpm builds
+DEPVER := $(shell /sbin/depmod -V 2>/dev/null | \
+ awk 'BEGIN {FS="."} NR==1 {print $$2}')
+
+###########################################################################
+# Build rules
+
+$(MANFILE).gz: ../$(MANFILE)
+ gzip -c $< > $@
+
+install: default $(MANFILE).gz
+ # remove all old versions of the driver
+ find $(INSTALL_MOD_PATH)/lib/modules/$(KVER) -name $(TARGET) -exec rm -f {} \; || true
+ find $(INSTALL_MOD_PATH)/lib/modules/$(KVER) -name $(TARGET).gz -exec rm -f {} \; || true
+ install -D -m 644 $(TARGET) $(INSTALL_MOD_PATH)$(INSTDIR)/$(TARGET)
+ifeq (,$(INSTALL_MOD_PATH))
+ /sbin/depmod -a || true
+else
+ ifeq ($(DEPVER),1 )
+ /sbin/depmod -r $(INSTALL_MOD_PATH) -a || true
+ else
+ /sbin/depmod -b $(INSTALL_MOD_PATH) -a -n > /dev/null || true
+ endif
+endif
+ install -D -m 644 $(MANFILE).gz $(INSTALL_MOD_PATH)$(MANDIR)/man$(MANSECTION)/$(MANFILE).gz
+ man -c -P'cat > /dev/null' $(MANFILE:.$(MANSECTION)=) || true
+
+uninstall:
+ if [ -e $(INSTDIR)/$(TARGET) ] ; then \
+ rm -f $(INSTDIR)/$(TARGET) ; \
+ fi
+ /sbin/depmod -a
+ if [ -e $(MANDIR)/man$(MANSECTION)/$(MANFILE).gz ] ; then \
+ rm -f $(MANDIR)/man$(MANSECTION)/$(MANFILE).gz ; \
+ fi
+
+.PHONY: clean install
+
+clean:
+ rm -rf $(TARGET) $(TARGET:.ko=.o) $(TARGET:.ko=.mod.c) $(TARGET:.ko=.mod.o) $(CFILES:.c=.o) $(MANFILE).gz .*cmd .tmp_versions
diff --git a/test/Makefile-24 b/test/Makefile-24
new file mode 100644
index 0000000..51f01af
--- /dev/null
+++ b/test/Makefile-24
@@ -0,0 +1,63 @@
+#
+# Makefile for building the dopanic module on Linux 2.4
+#
+
+MOD=dopanic
+MOD_CONF= $(MOD:%=%.conf)
+RHVER=RH7.1
+KVER=2.6.0
+KTAG=
+KSRC=/usr/src/linux
+# Note: /usr/src/linux should point to /usr/src/linux-$(KVER)$(KTAG).
+# The KVER is only used here for "make install".
+
+CC=gcc
+#Use the cflags that shows all warnings or the one that doesn't.
+#CFLAGS = -O2 -Wall -DLINUX_DEBUG
+CFLAGS = -O2
+
+#Note: Use the following to build a driver with no versioning.
+#K_CFLAGS = -D__KERNEL__ -DMODULE -D__SMP__ -DCONFIG_X86_LOCAL_APIC -D__NO_VERSION__
+#
+#The K_CFLAGS is used to build on all RedHat systems.
+#ADDK_CFLAGS is used only when building on pre RedHat 7.0 systems.
+#
+K_CFLAGS = -D__KERNEL__ -DMODULE -D__SMP__ -DCONFIG_X86_LOCAL_APIC -DMODULES
+ADDK_CFLAGS = -DMODVERSIONS -include /usr/include/linux/modversions.h
+
+CPPFLAGS = -I. -DLINUX -I/usr/src/linux/include
+
+K_VERSION:=$(shell uname -r | cut -c1-3 | sed 's/2\.[56]/2\.6/')
+ifeq ($(K_VERSION), 2.6)
+ TARGET = dopanic.ko
+ # CFILES = dopanic.c
+ # dopanic-objs := $(CFILES:.c=.o)
+ obj-m += dopanic.o
+ make -C $(KSRC) V=1 SUBDIRS=$(shell pwd) modules
+endif
+
+#List all the relevant files here
+OBJS = dopanic.o
+
+all: $(MOD)
+
+$(MOD): $(OBJS)
+ $(LD) -r -o $(MOD) $(OBJS)
+
+%.o: %.c
+ if [ "$(RHVER)" = "PRE-7.0" ]; \
+ then \
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) $(K_CFLAGS) $(ADDK_CFLAGS) -o $@ $< ; \
+ else \
+ $(CC) -c $(CFLAGS) $(CPPFLAGS) $(K_CFLAGS) -o $@ $< ; \
+ fi
+
+install: $(MOD)
+ cp $(MOD) /lib/modules/$(KVER)$(KTAG)/kernel/arch/i386/kernel
+
+clean:
+ rm -f $(OBJS) $(MOD)
+
+clobber:
+ rm -f $(OBJS) $(MOD)
+
diff --git a/test/Makefile-26 b/test/Makefile-26
new file mode 100644
index 0000000..e682f1a
--- /dev/null
+++ b/test/Makefile-26
@@ -0,0 +1,9 @@
+#
+# Makefile for the dopanic module.
+#
+
+TARGET = dopanic.ko
+
+CONFIG_DOPANIC=m
+
+obj-$(CONFIG_DOPANIC) += dopanic.o
diff --git a/test/dopanic.8 b/test/dopanic.8
new file mode 100644
index 0000000..edc1725
--- /dev/null
+++ b/test/dopanic.8
@@ -0,0 +1,33 @@
+.TH DOPANIC 8 "Version 1.0: 28 Feb 2007"
+.SH NAME
+dopanic \- kernel module to cause a panic
+.SH SYNOPSIS
+.B "insmod ./dopanic.ko"
+
+.SH DESCRIPTION
+dopanic is a Linux kernel module that calls panic when it is loaded.
+
+This can be used to test the CONFIG_IPMI_PANIC_STRING feature in
+the OpenIPMI driver.
+
+.SH "SEE ALSO"
+pefconfig(8) showsel(8)
+
+.SH WARNINGS
+Be sure to sync your filesystem before using this module.
+See http://ipmiutil.sourceforge.net/ for the latest version and any bug fix list.
+
+.SH COPYRIGHT
+Copyright (C) 2007 Intel Corp.
+.PP
+See the file COPYING in the distribution for more details
+regarding redistribution.
+.PP
+This utility is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY.
+
+.SH AUTHOR
+.PP
+Andy Cress <arcress at users.sourceforge.net>
+.br
+
diff --git a/test/dopanic_drv.c b/test/dopanic_drv.c
new file mode 100644
index 0000000..a8540ff
--- /dev/null
+++ b/test/dopanic_drv.c
@@ -0,0 +1,51 @@
+/* dopanic.c
+ *
+ * Cause a panic in a loadable driver.
+ */
+#include <linux/kernel.h> /* We're doing kernel work */
+#include <linux/module.h> /* Specifically, a module */
+
+static int device_open(void *inode,
+ void *file)
+{
+ printk (KERN_DEBUG "device_open(%p,%p)\n", inode, file);
+ return 0;
+}
+
+static int device_release(void *inode,
+ void *file)
+{
+ printk ("device_release(%p,%p)\n", inode, file);
+ return 0;
+}
+
+
+static int device_read(void *file,
+ char *buffer, /* The buffer to fill with data */
+ int length, /* The length of the buffer */
+ int *offset) /* Our offset in the file */
+{
+ return 0;
+}
+
+static int device_write(void *file,
+ const char *buffer, /* The buffer */
+ int length, /* The length of the buffer */
+ int *offset) /* Our offset in the file */
+{
+ return -1;
+}
+
+/* Initialize the module */
+int init_module()
+{
+ panic("dopanic: init_module calls panic");
+ return 0;
+}
+
+
+/* Cleanup - unregister the appropriate file from /proc */
+void cleanup_module()
+{
+}
+
diff --git a/test/ipmievt.sh b/test/ipmievt.sh
new file mode 100755
index 0000000..e61c1d6
--- /dev/null
+++ b/test/ipmievt.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+# ipmievt.sh - generate an IPMI temperature event
+#
+# Baseboard Temp is usually index 0d, 0e or 15, & sensor num 0x30
+# Note that values displayed/used are in hex.
+#
+# sensor |grep -i "Baseboard Temp"
+# 000d SDR Full 01 39 20 a 01 snum 30 Baseboard Temp = 2f OK 47.00 degrees C
+# ^^=ibasetemp ^^=nbasetemp ^^+4=lotemp
+#
+pattn="Temp"
+sensorfil=/var/lib/ipmiutil/sensor_out.txt
+if [ ! -f $sensorfil ]; then
+ sensorfil=/usr/share/ipmiutil/sensor_out.txt
+fi
+# get sensor readings again, since current temp may have changed
+ipmiutil sensor >$sensorfil
+#ibasetemp=0d
+#nbasetemp=30 # usually snum 30 on my test unit
+#lotemp=33
+nbasetemp=`grep -i "$pattn" $sensorfil |head -n1|awk '{print $10}'`
+ibasetemp=`grep "snum $nbasetemp" $sensorfil |awk '{print $1}'`
+curtemp=`grep "snum $nbasetemp" $sensorfil| cut -f2 -d'=' |awk '{print $3}'|cut -f1 -d'.'`
+lotemp=`expr $curtemp + 4`
+hitemp=`expr $curtemp - 4`
+hinorm=`expr $curtemp + 25`
+
+if [ "x$curtemp" = "x" ]; then
+ echo "Cannot find sensor reading for /$pattn/ in $sensorfil"
+ exit 1
+fi
+
+echo "Setting $pattn upper threshold to $hitemp - current temp = $curtemp"
+# cause a crit-hi for Baseboard Temp
+ipmiutil sensor -i $ibasetemp -t -n $nbasetemp -h $hitemp
+
+# give it 2 secs before clearing to OK
+sleep 2
+# put Baseboard Temp back to OK
+ipmiutil sensor -i $ibasetemp -t -n $nbasetemp -h $hinorm
+
+sleep 1
+# show the SEL events
+ipmiutil sel -l6
+
diff --git a/test/make260 b/test/make260
new file mode 100755
index 0000000..7a914b0
--- /dev/null
+++ b/test/make260
@@ -0,0 +1,17 @@
+# build dopanic as a linux 2.6 module
+#
+kdir=/usr/src/linux
+basename=dopanic
+
+# gcc -Wp,-MD,${basename}.o.d -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=pentium3 -I$kdir/include/asm-i386/mach-default -D__KERNEL__ -I$kdir/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=pentium3 -I$kdir/include/asm-i386/mach-default -fomit-frame-pointer -DMODULE -c -o ${basename}.o ${basename}.c
+# gcc -Wp,-MD,${basename}.mod.o.d -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=pentium3 -I$kdir/include/asm-i386/mach-default -D__KERNEL__ -I$kdir/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=pentium3 -I$kdir/include/asm-i386/mach-default -fomit-frame-pointer -DMODULE -c -o ${basename}.mod.o ${basename}.mod.c
+# ld -m elf_i386 -r -o ${basename}.ko ${basename}.o ${basename}.mod.o
+
+mkdir -p $kdir/drivers/char/dopanic
+cp dopanic.c $kdir/drivers/char/dopanic
+cp Kconfig $kdir/drivers/char/dopanic
+cp Makefile-26 $kdir/drivers/char/dopanic/Makefile
+make -C $kdir V=1 SUBDIRS=drivers/char/dopanic modules
+
+ls -l $kdir/drivers/char/dopanic/dopanic.ko
+
diff --git a/test/panicsel-c.sh b/test/panicsel-c.sh
new file mode 100755
index 0000000..c668be8
--- /dev/null
+++ b/test/panicsel-c.sh
@@ -0,0 +1,19 @@
+# ABAT test for panicsel component utilities
+# tag: rh71__build
+# util=/usr/share/panicsel/showsel
+util=/usr/sbin/isel
+echo "panicsel component, basic acceptance test"
+if [ ! -f $util ]
+then
+ echo "%%FAILURE%%"
+ exit 1
+fi
+$util >/dev/null 2>&1
+if [ $? -eq 0 ]
+then
+ echo "%%SUCCESS%%"
+ exit 0
+else
+ echo "%%FAILURE%%"
+ exit 1
+fi
diff --git a/test/panicsel-k.sh b/test/panicsel-k.sh
new file mode 100755
index 0000000..6737698
--- /dev/null
+++ b/test/panicsel-k.sh
@@ -0,0 +1,13 @@
+# ABAT test for panicsel kernel patch
+# tag: panicsel__build
+echo "panicsel kernel patch (BMC_PANIC), basic acceptance test"
+# dmesg |grep "BMC IPMI" >/dev/null 2>&1
+dmesg |grep bmc_panic >/dev/null 2>&1
+if [ $? -eq 0 ]
+then
+ echo "%%SUCCESS%%"
+ exit 0
+else
+ echo "%%FAILURE%%"
+ exit 1
+fi
diff --git a/test/panicsel_apptool_test.sh b/test/panicsel_apptool_test.sh
new file mode 100644
index 0000000..475f305
--- /dev/null
+++ b/test/panicsel_apptool_test.sh
@@ -0,0 +1,550 @@
+#!/bin/sh
+linux_type="redhat"
+# pkg=panicsel
+# isel=showsel
+# ipef=pefconfig
+# iserial=tmconfig
+pkg=ipmiutil
+isel=isel
+ipef=ilan
+iserial=iserial
+iselout=/tmp/isel.out
+ipefout=/tmp/pefconfigoutput
+
+basic_test()
+{
+ $isel > /dev/null 2>&1
+ if [ "$?" -eq 0 ];then
+ echo "PASS_BASIC: The $isel tool can run correctly"
+ return 0
+ else
+ echo "FAIL_BASIC: The $isel tool can not run correctly"
+ return 1
+ fi
+}
+showsel_ov()
+{
+ $isel -v|grep version|grep -v BMC > /dev/null
+ if [ "$?" -eq "0" ];then
+ $isel -v|grep "Free" > /dev/null 2>&1
+ if [ "$?" -eq 0 ];then
+ echo "PASS: $isel option -v testing"
+ return 0
+ else
+ echo "FAIL: $isel testing -v fail"
+ fi
+ else
+ echo "FAIL: $isel testing -v fail"
+ return 1
+ fi
+}
+
+showsel_oc()
+{
+ message_original=`$isel|wc -l`
+ $isel -c > /dev/null 2>&1
+ message_now=`$isel|wc -l`
+ if [ "$message_original" -ge "$message_now" ];then
+ echo "PASS: $isel option -c testing"
+ return 0
+ else
+ echo "FAIL: $isel option -c testing"
+ return 1
+ fi
+}
+
+check_os()
+{
+ if [ -d "/usr/src/redhat" ];then
+ linux_type="redhat"
+ fi
+ if [ -d "/usr/src/hardhat" ];then
+ linux_type="hardhat"
+ fi
+}
+
+check_driver()
+{
+ lsmod|grep "ipmi_comb" > /dev/null 2>&1
+ if [ $? -eq 0 ];then
+ echo "The ipmi_comb driver has been inserted already"
+ Major=`cat /proc/devices|grep imb|awk '{print $1}'`
+ if [ ! -c /dev/imb ];then
+ mknod /dev/imb c $Major 0
+ fi
+ return 1
+ fi
+ modprobe "ipmi_comb" > /dev/null 2>&1
+ if [ $? -eq 0 ];then
+ echo "The ipmi_comb driver be inserted corretly"
+ else
+ # echo "There are no ipmi driver or ipmi driver can not be inserted correctly"
+ return 1
+ fi
+
+ lsmod|grep "ipmi_comb" > /dev/null 2>&1
+ if [ $? -eq 0 ];then
+ Major=`cat /proc/devices|grep imb|awk '{print $1}'`
+ if [ ! -c /dev/imb ];then
+ mknod /dev/imb c $Major 0
+ fi
+ fi
+
+}
+showsel_ow()
+{
+ cp -f /var/log/messages /tmp/tempbackup
+ if [ ! -d /usr/share/$pkg ];then
+ mkdir /usr/share/$pkg
+ fi
+ if [ -f /usr/share/$pkg/sel.idx ];then
+ rm -f sel.idx
+ fi
+ $isel -w > /dev/null 2>&1
+ idx=`cat /usr/share/$pkg/sel.idx |awk '{ print $2}'`
+ diff /var/log/messages /tmp/tempbackup > /tmp/diff_log
+ log=`cat /tmp/diff_log|grep $idx`
+ if [ -n "$idx" -a -n "$log" ];then
+ echo "PASS: $isel option w"
+ else
+ echo "FAIL: $isel option w"
+ fi
+
+}
+###########################################
+#test show OS critical message correctly###
+###########################################
+showsel_os()
+{
+ $isel > $iselout
+ osnumber=`grep "OS Critical Stop" $iselout|wc -l`
+ if [ $osnumber -eq 0 ];then
+ echo "SKIP: $isel option s - no OS critical messages"
+ return 1
+ fi
+ $isel -s >$iselout
+ osnumber=`grep "OS Critical Stop" $iselout|wc -l`
+ if [ $? -eq 0 -a $osnumber -gt 0 ];then
+ echo " PASS: $isel option s "
+ return 0
+ else
+ echo "FAIL: $isel option s"
+ return 1
+ fi
+
+}
+showsel_test()
+{
+ check_os
+ check_driver
+ basic_test
+ if [ "$?" -eq 0 ];then
+ showsel_ov
+ showsel_oc
+ showsel_ow
+ showsel_os
+ fi
+}
+#####################################################################
+#test pefconfig can read PEF entry ###
+#####################################################################
+pefconfig_basic()
+{
+ if [ -f $ipefout ];then
+ rm -rf $ipefout
+ fi;
+ $ipef -r > $ipefout 2>&1
+ pefnumber=`grep PEFilter $ipefout|wc -l`
+ lannumber=`grep Lan $ipefout|wc -l`
+ if [ $pefnumber -ge 12 ];then
+ echo "PASS: $ipef basic requirement "
+ return 0
+ else
+ echo "FAIL: $ipef basic requirement"
+ return 1
+ fi;
+ if [ -f $ipefout ];then
+ rm -rf $ipefout
+ fi;
+}
+
+#####################################################################
+#test pefconfig can enable or disable the new PEF 0x20 events ###
+#####################################################################
+pefconfig_od()
+{
+ ipefdout=/tmp/pefconfigoutputd
+ if [ -f $ipefdout ];then
+ rm $ipefdout
+ fi
+ $ipef -d > $ipefdout 2>&1
+ disable=`cat $ipefdout|grep "Access = Disabled"`
+ if [ -n "$disable" ];then
+ echo "PASS: pefconfig disable OS critical Event "
+ return 0
+ else
+ echo "FAIL: pefconfig disable OS critical Event "
+ return 1
+ fi
+}
+
+#####################################################################
+#test pefconfig can write new entry at different offset than 12 ###
+#####################################################################
+ts_pefconfign()
+{
+total=`$ipef -r | grep PEFilter | wc -l`
+total=`echo $((total))`
+PASS="PASS"
+tmp_num=$1
+num=`echo $((tmp_num))`
+peftmp=/tmp/ipefn
+if [ "$num" -le "$total" ];then
+ $ipef -n $num |grep PEFilter|tail -n $num > ${peftmp}_$num
+ $ipef -r |grep PEFilter|head -n $num > ${peftmp}_r$num
+ dif=`diff ${peftmp}_$num ${peftmp}_r$num`
+ if [ -n "$dif" ];then
+ PASS="FAIL"
+ fi
+ rm -f ${peftmp}_$num
+ rm -f ${peftmp}_r$num
+else
+ succnum=`$ipef e -x -n $num |grep SetPefEntry|awk '{print $2}'|grep "successful"|wc -l`
+ succnum=`echo $((succnum))`
+ eqnum=`expr $num \* 2 - 1`
+ if [ "$succnum" -eq "$eqnum" ];then
+ lastrecord=`$ipef -n 15 |grep PEFilter|tail -n 1|awk '{print $3}'`
+ if [ $lastrecord -ne "80" ];then
+ PASS="FAIL"
+ fi
+ fi
+fi
+ if [ $PASS == "$FAIL" ];then
+ echo "FAIL: $ipef -n" $1
+ else
+ echo "PASS: $ipef -n" $1
+ fi
+}
+#####################################################################
+#test pefconfig can output more debug information ###
+#####################################################################
+ts_pefconfigx()
+{
+ ipefxout=/tmp/pefconfigoutputx
+ if [ -f $ipefout ];then
+ rm -rf $ipefout
+ fi
+ if [ -f $ipefxout ];then
+ rm -rf $ipefxout
+ fi
+ $ipef -x >> $ipefxout
+ test=`grep "PEF record" $ipefxout`
+ if [ ! -z test ];then
+ echo "PASS: $ipef parameter x "
+ return 0
+ else
+ echo "FAIL: $ipef parameter x"
+ return 1
+ fi
+ if [ -f $ipefxout ];then
+ rm -rf $ipefxout
+ fi
+
+}
+##############################################################
+#Basic function for testing pefconfig configuration
+################################################################
+get_host_ip_address()
+{
+ ifconfig|grep "inet addr"|grep -v "127.0.0.1"|awk '{print $2}'|cut -d: -f2
+}
+get_host_mac_address()
+{
+ ifconfig|grep eth0|awk '{print $5}'
+}
+get_route_ip_address()
+{
+ netstat -rn|grep eth0|grep UG|awk '{print $2}'
+ #cat /proc/net/arp|grep -v "HW"|awk '{print $1}'
+}
+get_route_mac_address()
+{
+ routeip=`get_route_ip_address`
+ cat /proc/net/arp|grep -v "HW"|grep $routeip|awk '{print $4}'
+}
+get_subnet_mask_address()
+{
+ ifconfig|grep Mask|grep -v "127.0.0.1"|awk '{print $4}'|cut -d: -f2
+}
+get_alert_ip_address()
+{
+ cat /etc/snmp/snmpd.conf|grep trapsink|cut -f2 -d' '
+}
+get_alert_mac_address()
+{
+ routip=get_route_ip_address
+ arping -c 1 $routeip > /dev/null 2>&1
+ arping -c 2 $1|grep reply|tail -1|awk '{print $5}'|cut -c2-18
+}
+
+get_pef_ip_address()
+{
+ cat $1|grep $2|grep -v "Param"|awk '{print $2}'|cut -d= -f2
+}
+get_pef_mac_address()
+{
+ cat $1|grep $2|grep -v "Param"|awk '{print $3}'|cut -d= -f2
+}
+check_pef()
+{
+ cat $1|grep "SetLanEntry"|grep "($2"|awk '{print $4}'
+}
+upper()
+{
+ echo $1|tr 'a-z' 'A-Z'
+}
+####################################################
+#Test pefconfig set host ip and mac addresses
+###################################################
+
+ts_pefconfig_sethost()
+{
+ rm /tmp/pefconfig_host
+ ip=`get_host_ip_address`
+ mac=`get_host_mac_address`
+ ip=192.168.2.222
+ # $ipef -I $ip -M $mac > /tmp/pefconfig_host 2>&1
+ $ipef -e -I $ip > /tmp/pefconfig_host 2>&1
+ setip=`get_pef_ip_address /tmp/pefconfig_host eth0`
+ setmac=`get_pef_mac_address /tmp/pefconfig_host eth0`
+ setmac=`upper $setmac`
+ isip=`check_pef /tmp/pefconfig_host 3`
+ ismac=`check_pef /tmp/pefconfig_host 4`
+ # if [ $mac == $setmac ] && [ $ismac -eq 0 ]; then
+ if [ $ip == $setip ] && [ $isip -eq 0 ] ; then
+ echo "PASS: $ipef Set host ip address to $ip"
+ return 0
+ else
+ echo "FAIL: $ipef Set host ip address"
+ return 1
+ fi
+}
+###############################################################
+##Test pefconfig set route ip and mac addresses
+###############################################################
+ts_pefconfig_setroute()
+{
+ ip=`get_route_ip_address`
+ count=`get_route_ip_address`
+ mac=`get_route_mac_address`
+ $ipef -e -G $ip -H $mac > /tmp/pefconfig_route 2>&1
+ setip=`get_pef_ip_address /tmp/pefconfig_route gateway`
+ setmac=`get_pef_mac_address /tmp/pefconfig_route gateway`
+ setmac=`upper $setmac`
+ isip=`check_pef /tmp/pefconfig_route 12`
+ ismac=`check_pef /tmp/pefconfig_route 13`
+ if [ $ip == $setip ] && [ $mac == $setmac ] \
+ && [ $isip -eq 0 ] && [ $ismac -eq 0 ];then
+ echo "PASS: $ipef Set route ip $ip and mac address"
+ return 0
+ else
+ echo "FAIL: $ipef Set route ip and mac address"
+ return 1
+ fi
+}
+get_alert_setip_address()
+{
+ cat $1|grep $2|awk '{print $3}'|cut -d= -f2
+}
+get_alert_setmac_address()
+{
+ cat $1|grep $2|awk '{print $4}'|cut -d= -f2
+}
+ps_pefconfig_setalert()
+{
+ rm -f /tmp/pefconfig_alert > /dev/null 2>&1
+ ip=`get_host_ip_address`
+ mac=`get_host_mac_address`
+ $ipef -A $ip -B $mac > /tmp/pefconfig_alert 2>&1
+ setip=`get_alert_setip_address /tmp/pefconfig_alert alert`
+ setmac=`get_alert_setmac_address /tmp/pefconfig_alert alert`
+ setmac=`upper $setmac`
+ isip=`check_pef /tmp/pefconfig_alert 18`
+ ismac=`check_pef /tmp/pefconfig_alert 19`
+ if [ $ip == $setip ] && [ $mac == $setmac ] \
+ && [ $isip -eq 0 ] && [ $ismac -eq 0 ];then
+ echo "PASS: $ipef Set alert"
+ return 0
+ else
+ echo "FAIL: $ipef Set Alert"
+ return 1
+ fi
+}
+###########################################################
+#Test pefconfig set community
+###########################################################
+ts_pefconfig_setcommunity()
+{
+ rm -f /tmp/pefconfig_comm
+ $ipef -A 127.0.0.1 -C private > /tmp/pefconfig_comm 2>&1
+ pef_comm=`cat /tmp/pefconfig_comm|grep Community|awk '{print $5}'`
+ if [ $pef_comm == "private" ];then
+ echo "PASS: $ipef set community"
+ return 0
+ else
+ echo "FAIL: $ipef set community"
+ return 1
+ fi
+}
+get_pef_subnet()
+{
+ a=`cat $1|grep Subnet|awk '{print $5}'`
+ b=`cat $1|grep Subnet|awk '{print $6}'`
+ c=`cat $1|grep Subnet|awk '{print $7}'`
+ d=`cat $1|grep Subnet|awk '{print $8}'`
+ echo $a.$b.$c.$d
+}
+##############################################################
+#Test pefconfig set subnet mask
+###############################################################
+ts_pefconfig_setsubnet()
+{
+
+ subnet=`get_subnet_mask_address`;
+ $ipef -S $subnet > /tmp/pefconfig_subnet 2>&1
+ pef_subnet=`get_pef_subnet /tmp/pefconfig_subnet`
+ if [ $subnet == $pef_subnet ];then
+ echo "PASS: $ipef get sub net mask address"
+ return 0
+ else
+ echo "FAIL: $ipef get sub net mask address"
+ return 1
+ fi
+}
+
+pefconfig_test()
+{
+ pefconfig_basic
+ if [ "$?" -eq 0 ];then
+ ts_pefconfign 9
+ ts_pefconfign 12
+ ts_pefconfign 16
+ ts_pefconfigx
+ ts_pefconfig_sethost
+ ts_pefconfig_setroute
+ ts_pefconfig_setsubnet
+ else
+ echo "System does not support pefconfig function"
+ fi
+}
+#*****************************************************/
+#Test the tmconfig util******************************/
+#*****************************************************/
+EntryTest()
+{
+ which $iserial > /dev/null 2>&1
+ if [ $? -ne 0 ];then
+ if [ -f /usr/share/$pkg/$iserial ];then
+ cp -f /usr/share/$pkg/$iserial /usr/sbin
+ else
+ echo "$iserial: there is no $iserial util"
+ exit 1
+ fi
+ fi
+}
+TestPara()
+{
+ result=`cat $1|grep $2|awk '{print $4}'|cut -d , -f 1`
+ if [ "x$result" = "x" ]; then
+ echo "FAIL: $iserial $2, no result"
+ return 1
+ fi
+ if [ $result -eq 0 ];then
+ echo "PASS: $iserial $2"
+ return 0
+ else
+ echo "FAIL: $iserial $2"
+ return 1
+ fi
+
+}
+ts_tmconfigr()
+{
+ infoline="$iserial Test parameter r"
+ EntryTest
+ $iserial -r > /dev/null 2>&1
+ if [ $? -eq 0 ];then
+ echo "PASS: $infoline"
+ return 0
+ else
+ echo "FAIL: $infoline"
+ return 1
+ fi
+}
+
+ts_tmconfigs()
+{
+ infoline="$iserial Test parameter n"
+ EntryTest
+ $iserial -s > /tmp/tmconfigs 2>&1
+ TestPara /tmp/tmconfigs "SetChanAcc(ser)" $infoline
+}
+ts_tmconfigup()
+{
+ infoline="$iserial Test parameter u and p"
+ EntryTest
+ $iserial -u root -p password >/dev/null 2>&1
+ if [ $? -eq 0 ];then
+ echo PASS: $infoline
+ else
+ echo FAIL: $infoline
+ fi
+}
+LanTest()
+{
+ infoline="$iserial Test parameter l"
+ $iserial -l > /tmp/tmconfigl
+ line=`cat /tmp/tmconfigl|grep "Lan Param"|wc -l`
+ if [ $line -ge 22 ];then
+ echo "PASS: $infoline"
+ else
+ echo "FAIL: $infoline"
+ fi
+}
+ts_tmconfigl()
+{
+ EntryTest
+ LanTest
+}
+
+ts_tmconfign()
+{
+ infoline="$iserial Test parameter m0"
+ EntryTest
+ $iserial -m0 >/tmp/tmconfign 2>&1
+ TestPara /tmp/tmconfign "SetSerialMux(System)" $infoline
+}
+ts_tmconfigt()
+{
+ infoline="$iserial Test parameter m1"
+ EntryTest
+ $iserial -m1 >/tmp/tmconfigt 2>&1
+ TestPara /tmp/tmconfigt "SetSerialMux(BMC)" $infoline
+}
+
+tmconfig_test()
+{
+ ts_tmconfigr
+ if [ $? -eq 0 ];then
+ ts_tmconfigs
+ ts_tmconfigl
+ ts_tmconfign
+ ts_tmconfigup
+ ts_tmconfigt
+ else
+ echo "FAIL:Basic tmconfig testing"
+ fi
+}
+showsel_test
+pefconfig_test
+tmconfig_test
diff --git a/test/panicsel_test_needreboot.sh b/test/panicsel_test_needreboot.sh
new file mode 100644
index 0000000..61a183f
--- /dev/null
+++ b/test/panicsel_test_needreboot.sh
@@ -0,0 +1,162 @@
+#!/bin/sh
+# pkg=panicsel
+# isel=showsel
+# ipef=pefconfig
+# ireset=hwreset
+pkg=ipmiutil
+isel=isel
+ipef=ilan
+ireset=ireset
+env()
+{
+ if [ -x /usr/local/bin/$isel ];then
+ PATH_EXEC="/usr/local/bin"
+ fi
+ if [ -x /usr/sbin/$isel ];then
+ PATH_EXEC="/usr/sbin"
+ fi
+}
+check_os()
+{
+ if [ -d "/etc/redhat-release" ];then
+ linux_type="redhat"
+ fi
+ if [ -d "/etc/SuSE-release" ];then
+ linux_type="suse"
+ fi
+ if [ -d "/usr/src/hardhat" ];then
+ linux_type="hardhat"
+ fi
+}
+
+check_driver()
+{
+ lsmod|grep "ipmi_comb" > /dev/null 2>&1
+ if [ $? -eq 0 ];then
+ echo "The ipmi_comb driver has been inserted already"
+ Major=`cat /proc/devices|grep imb|awk '{print $1}'`
+ if [ ! -c /dev/imb ];then
+ mknod /dev/imb c $Major 0
+ return 0
+ fi
+ fi
+
+ modprobe "ipmi_comb" > /dev/null 2>&1
+ if [ $? -eq 0 ];then
+ echo "The ipmi_comb driver be inserted corretly"
+ else
+ # echo "There are no ipmi driver or ipmi driver can not be inserted correctly"
+ return 0
+ fi
+
+ lsmod|grep "ipmi_comb" > /dev/null 2>&1
+ if [ $? -eq 0 ];then
+ Major=`cat /proc/devices|grep imb|awk '{print $1}'`
+ if [ ! -c /dev/imb ];then
+ mknod /dev/imb c $Major 0
+ fi
+ fi
+
+}
+
+prepare()
+{
+ env
+ # check_driver
+}
+Test_kernelpatch()
+{
+ oldnum=0
+ newnum=0
+ prepare
+ DIR=`pwd`
+ if [ -f /tmp/mark ];then
+ MARK=`cat /tmp/mark`
+ else
+ MARK=0
+ fi
+ $PATH_EXEC/$ipef -A $1 -C public
+ if [ $? -ne 0 ];then
+ echo "Pefconfig incorrectly,pls check your machine"
+ exit 1
+ fi
+ cd /usr/share/$pkg
+ if [ "$MARK" -ne "1" ];then
+ cd $DIR
+ cp -f ./dopanic /usr/share/$pkg/
+ echo "Init a panic for $pkg..."
+ $PATH_EXEC/$isel -s|grep -c "OS Critical Stop" > /tmp/ocs_num
+ sync
+ sleep 2
+ echo 1 > /tmp/mark
+ cd /usr/share/$pkg
+ insmod -f ./dopanic
+ fi
+ echo "check the result for $pkg..."
+ read oldnum < /tmp/ocs_num
+ $PATH_EXEC/$isel -s |grep -c "OS Critical Stop" > /tmp/ocs_num
+ read newnum < /tmp/ocs_num
+ let oldnum=oldnum+1
+ if [ $newnum -eq $oldnum ]
+ then
+ echo "PASS:KernelPactch:Panic sel insert record"
+ return 0
+ else
+ echo "FAIL: Kernel PatchPanic sel insert record"
+ return 1
+ fi
+ rm -f /tmp/mark
+
+}
+ts_hwresetr()
+{
+ prepare
+ if [ -f /tmp/count ];then
+ COUNT=`cat /tmp/count`
+ else
+ COUNT=0
+ fi
+ if [ "$COUNT" -ne "1" ];then
+ $PATH_EXEC/$isel -c >/dev/null 2>&1
+ echo 1 > /tmp/count
+ $PATH_EXEC/$ireset #reset the system
+ fi
+ $PATH_EXEC/$isel > /tmp/hwreset 2>&1
+ isevent=`cat /tmp/hwreset|grep "System Event"`
+ isboot=`cat /tmp/hwreset|grep "System Boot"`
+ if [ -n "$isevent" ] && [ -n "$isboot" ];then
+ echo "PASS: $pkg power reset"
+ return 0
+ else
+ echo "FAIL: $pkg power reset"
+ return 1
+ fi
+ rm -f /tmp/count
+}
+
+ts_hwresetc()
+{
+ prepare
+ if [ -f /tmp/hwresetc ];then
+ MARK=`cat /tmp/hwresetc`
+ else
+ MARK=0
+ fi
+ if [ "$MARK" -ne "1" ];then
+ $PATH_EXEC/$isel -c >/dev/null 2>&1
+ echo 1 > /tmp/hwresetc
+ $PATH_EXEC/$ireset -c #reset the system
+ fi
+
+ $PATH_EXEC/$isel >/tmp/hwresetc 2>&1
+ power=`cat /tmp/hwresetc|grep "Power Off/Down"`
+ if [ -n "$power" ];then
+ echo "PASS: $pkg power cycle"
+ return 0
+ else
+ echo "FAIL: $pkg power cycle"
+ return 1
+ fi
+ rm -f /tmp/hwresetc
+}
+
diff --git a/test/retro.sh b/test/retro.sh
new file mode 100755
index 0000000..42a60a9
--- /dev/null
+++ b/test/retro.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# retro.sh
+#
+# retrofit ipmiutil subcommand naming for pre-2.6.0 scripts.
+#
+# old new full command
+#alarms ialarms (ipmiutil alarms)
+#bmcconfig iconfig (ipmiutil config)
+#bmchealth ihealth (ipmiutil health)
+#fruconfig ifru (ipmiutil fru)
+#getevent igetevent (ipmiutil getevent)
+#hwreset ireset (ipmiutil reset)
+#icmd icmd (ipmiutil cmd)
+#idiscover idiscover (ipmiutil discover)
+#ievents ievents (ipmiutil events)
+#isolconsole isol (ipmiutil sol)
+#pefconfig ilan (ipmiutil lan)
+#sensor isensor (ipmiutil sensor)
+#showsel isel (ipmiutil sel)
+#tmconfig iserial (ipmiutil serial)
+#wdt iwdt (ipmiutil wdt)
+
+mydir=`pwd`
+
+cd /usr/sbin
+ln ialarms alarms
+ln iconfig bmcconfig
+ln ihealth bmchealth
+ln ifru fruconfig
+ln igetevent getevent
+ln ireset hwreset
+ln isol isolconsole
+ln ilan pefconfig
+ln isensor sensor
+ln iserial tmconfig
+ln iwdt wdt
+cd $mydir
diff --git a/test/sensor-CG2100.txt b/test/sensor-CG2100.txt
new file mode 100644
index 0000000..0545fec
--- /dev/null
+++ b/test/sensor-CG2100.txt
@@ -0,0 +1,148 @@
+ipmiutil ver 2.53
+sensor: version 2.53
+-- BMC version 0.48, IPMI version 2.0
+_ID_ SDR_Type_xx ET Own Typ S_Num Sens_Description Hex & Interp Reading
+0001 SDR Full 01 01 20 a 02 snum 10 BB +1.1V IOH = e9 OK 1.09 Volts
+0002 SDR Full 01 01 20 a 02 snum 11 BB +1.1V P1 Vccp = a1 OK 0.99 Volts
+0003 SDR Full 01 01 20 a 02 snum 12 BB +1.1V P2 Vccp = a2 OK 0.99 Volts
+0004 SDR Full 01 01 20 a 02 snum 13 BB +1.5V P1 DDR3 = ec OK 1.53 Volts
+0005 SDR Full 01 01 20 a 02 snum 14 BB +1.5V P2 DDR3 = eb OK 1.52 Volts
+0006 SDR Full 01 01 20 a 02 snum 15 BB +1.8V AUX = e8 OK 1.77 Volts
+0007 SDR Full 01 01 20 a 02 snum 16 BB +3.3V = e8 OK 3.34 Volts
+0008 SDR Full 01 01 20 a 02 snum 17 BB +3.3V STBY = e6 OK 3.31 Volts
+0009 SDR Full 01 01 20 a 02 snum 18 BB +3.3V Vbat = e7 OK 3.01 Volts
+000a SDR Full 01 01 20 a 02 snum 19 BB +5.0V = e0 OK 4.90 Volts
+000b SDR Full 01 01 20 a 02 snum 1a BB +5.0V STBY = e8 OK 5.08 Volts
+000c SDR Full 01 01 20 a 02 snum 1b BB +12.0V = e3 OK 11.99 Volts
+000d SDR Full 01 01 20 a 02 snum 1c BB -12.0V = be OK -11.59 Volts
+000e SDR Full 01 01 20 a 01 snum 20 Baseboard Temp = 1d OK 29.00 degrees C
+000f SDR Full 01 01 20 a 01 snum 21 Front Panel Temp = 18 OK 24.00 degrees C
+0010 SDR Full 01 01 20 a 01 snum 22 IOH Therm Margin = cf OK -49.00 degrees C
+0011 SDR Full 01 01 20 a 01 snum 23 Mem P1 Thrm Mrgn = d8 OK -40.00 degrees C
+0012 SDR Full 01 01 20 a 01 snum 24 Mem P2 Thrm Mrgn = d6 OK -42.00 degrees C
+0013 SDR Full 01 01 20 m 04 snum 30 System Fan 1 = 66 OK 4590.00 RPM
+0014 SDR Full 01 01 20 m 04 snum 31 System Fan 2 = 65 OK 4545.00 RPM
+0015 SDR Full 01 01 20 m 04 snum 32 System Fan 3 = 67 OK 4635.00 RPM
+0016 SDR Full 01 01 20 m 04 snum 33 System Fan 4 = 65 OK 4545.00 RPM
+0017 SDR Full 01 01 20 m 04 snum 38 System Fan 5 = 72 OK 5700.00 RPM
+0018 SDR Full 01 01 20 m 04 snum 39 System Fan 6 = 72 OK 5700.00 RPM
+0019 SDR Full 01 01 20 a 0b snum 52 PS1 Power In = 2a OK 168.00 Watts
+001a SDR Full 01 01 20 a 03 snum 54 PS1 Curr Out % = 14 OK 20.00 unspecified
+001b SDR Full 01 01 20 a 01 snum 56 PS1 Temperature = 1b OK 27.00 degrees C
+001c SDR Full 01 01 20 a 01 snum 62 P1 Therm Margin = b9 OK -71.00 degrees C
+001d SDR Full 01 01 20 a 01 snum 63 P2 Therm Margin = b8 OK -72.00 degrees C
+001e SDR Full 01 01 20 a 01 snum 64 P1 Therm Ctrl % = 00 OK 0.00 unspecified
+001f SDR Full 01 01 20 a 01 snum 65 P2 Therm Ctrl % = 00 OK 0.00 unspecified
+0020 SDR Full 01 01 c0 a 01 snum 01 HSBP Temperature = 19 OK* 25.00 degrees C
+0021 SDR Comp 02 6f 20 a 09 snum 01 Power Unit Stat = 00 c0 00 00 Enabled
+0022 SDR Comp 02 6f 20 a 23 snum 03 IPMI Watchdog = 00 c0 00 00 OK
+0023 SDR Comp 02 6f 20 a 05 snum 04 Physical Scrty = 00 c0 01 00 ChassisIntrus
+0024 SDR Comp 02 6f 20 a 13 snum 05 FP NMI Diag Int = 00 c0 00 00 OK
+0025 SDR Comp 02 03 20 a f3 snum 06 SMI Timeout = 00 c0 00 00 Disabled
+0026 SDR Comp 02 6f 20 a 10 snum 07 System Event Log = 00 c0 00 00 MemLogDisab
+0027 SDR Comp 02 6f 20 a 12 snum 08 System Event = 00 c0 00 00 OK
+0028 SDR Comp 02 6f 20 a 14 snum 09 Button = 00 c0 00 00 OK
+0029 SDR Comp 02 08 20 a 04 snum 40 Fan 1 Present = 00 c0 02 00 Present
+002a SDR Comp 02 08 20 a 04 snum 41 Fan 2 Present = 00 c0 02 00 Present
+002b SDR Comp 02 08 20 a 04 snum 42 Fan 3 Present = 00 c0 02 00 Present
+002c SDR Comp 02 08 20 a 04 snum 43 Fan 4 Present = 00 c0 02 00 Present
+002d SDR Comp 02 08 20 a 04 snum 44 Fan 5 Present = 00 c0 02 00 Present
+002e SDR Comp 02 08 20 a 04 snum 45 Fan 6 Present = 00 c0 02 00 Present
+002f SDR Comp 02 0b 20 a 04 snum 46 Fan Redundancy = 00 c0 01 00 Redundant
+0030 SDR Comp 02 6f 20 a 08 snum 50 PS1 Status = 00 c0 01 00 Present
+0031 SDR Comp 02 6f 20 m 07 snum 60 P1 Status = 00 c0 80 00 ProcPresent
+0032 SDR Comp 02 6f 20 m 07 snum 61 P2 Status = 00 c0 80 00 ProcPresent
+0033 SDR Comp 02 05 20 m 01 snum 66 P1 VRD Hot = 00 c0 00 00 OK
+0034 SDR Comp 02 05 20 m 01 snum 67 P2 VRD Hot = 00 c0 00 00 OK
+0035 SDR Comp 02 03 20 m 07 snum 68 CATERR = 00 c0 00 00 OK
+0036 SDR Comp 02 03 20 m 07 snum 69 CPU Missing = 00 c0 00 00 OK
+0037 SDR Comp 02 03 20 m 01 snum 6a IOH Therm Trip = 00 c0 00 00 OK
+0038 SDR Comp 02 74 2c a dc snum 1a NM Capabilities = 00 00 00 00 NotAvailable
+0039 SDR Comp 02 6f c0 a 0d snum 02 Drv 0 Stat = 00 c0 00 8e Ready
+003a SDR Comp 02 6f c0 a 0d snum 03 Drv 1 Stat = 00 c0 00 80 Unused
+003b SDR Comp 02 6f c0 a 0d snum 04 Drv 2 Stat = 00 c0 00 80 Unused
+003c SDR Comp 02 6f c0 a 0d snum 05 Drv 3 Stat = 00 c0 00 80 Unused
+003d SDR Comp 02 6f c0 a 0d snum 06 Drv 4 Stat = 00 c0 00 80 Unused
+003e SDR Comp 02 6f c0 a 0d snum 07 Drv 5 Stat = 00 c0 00 80 Unused
+003f SDR Comp 02 08 c0 a 0d snum 09 Drv 0 Pres = 00 c0 02 80 Present
+0040 SDR Comp 02 08 c0 a 0d snum 0a Drv 1 Pres = 00 c0 00 80 Unused
+0041 SDR Comp 02 08 c0 a 0d snum 0b Drv 2 Pres = 00 c0 00 80 Unused
+0042 SDR Comp 02 08 c0 a 0d snum 0c Drv 3 Pres = 00 c0 00 80 Unused
+0043 SDR Comp 02 08 c0 a 0d snum 0d Drv 4 Pres = 00 c0 00 80 Unused
+0044 SDR Comp 02 08 c0 a 0d snum 0e Drv 5 Pres = 00 c0 00 80 Unused
+0045 SDR EvtO 03 19 2c 00 snum 17 SPS FW Health = 00 00 00 00 OK
+0046 SDR EvtO 03 18 2c 00 snum 18 NM Exception = 00 00 00 00 OK
+0047 SDR EvtO 03 15 2c 00 snum 19 NM Health = 00 00 00 00 OK
+0048 SDR EvtO 03 18 2c 00 snum 1b NM Threshold = 00 00 00 00 OK
+0049 SDR EvtO 03 1b 33 01 snum 01 Mem Mirr Sensor = 00 00 00 00 OK
+004a SDR EvtO 03 1b 33 01 snum 02 Mmry ECC Sensor = 00 00 00 00 OK
+004b SDR EvtO 03 1b 33 01 snum 03 PCI Lgcy Sensor = 00 00 00 00 OK
+004c SDR EvtO 03 1b 33 01 snum 04 PCIe Fat Sensor = 00 00 00 00 OK
+004d SDR EvtO 03 1b 33 01 snum 05 PCIe Cor Sensor = 00 00 00 00 OK
+004e SDR EvtO 03 1b 33 01 snum 06 QPI Corr Sensor = 00 00 00 00 OK
+004f SDR EvtO 03 1b 33 01 snum 07 QPI NonF Sensor = 00 00 00 00 OK
+0050 SDR EvtO 03 1b 33 01 snum 11 Mem Spar Sensor = 00 00 00 00 OK
+0051 SDR EvtO 03 1b 33 01 snum 12 Mirr Mod Sensor = 00 00 00 00 OK
+0052 SDR EvtO 03 1b 33 01 snum 13 Spar Mod Sensor = 00 00 00 00 OK
+0053 SDR EvtO 03 1b 33 01 snum 14 Mem Parity Snsr = 00 00 00 00 OK
+0054 SDR EvtO 03 1b 33 01 snum 17 QPI Fatl Sensor = 00 00 00 00 OK
+0055 SDR EvtO 03 1b 33 01 snum 18 QPI Fatl Sensor = 00 00 00 00 OK
+0056 SDR EvtO 03 1b 01 01 snum 83 BIOS Evt Sensor = 00 00 00 00 OK
+0057 SDR FRU 11 14 dev: 20 00 80 00 07 01 Baseboard
+0058 SDR FRU 11 1b dev: 20 01 80 00 15 01 Power Dist Board
+0059 SDR FRU 11 1b dev: 20 02 80 00 0a 01 Pwr Supply 1 FRU
+005a SDR IPMB 12 1b dev: 20 00 bf 07 01 Basbrd Mgmt Ctlr
+005b SDR IPMB 12 17 dev: c0 00 29 0f 01 HotSwap Ctlr
+005c SDR IPMB 12 0d dev: 2c 06 21 2e 01 ME
+005d SDR OEM c0 0b Intel: 0d 01 2c 60 19 18 1a 1b
+005e SDR OEM c0 15 Intel: 05 46 00 04 04 01 30 40 31 41 32 42 33 43 38 44 39 45
+005f SDR OEM c0 32 Intel: 09 0f 10 54 14 11 88 0f 12 88 0f 13 a5 0e 14 a5 0e 15 73 0c 16 b6 0a 17 b6 0a 18 d5 09 19 bb 0a 1a bb 0a 1b d5 0a 1c 39 1e 1d 44 10 1e 44 10
+0060 SDR OEM c0 1e Intel: 0a 00 00 50 2d 50 2d 50 2d 50 2d 00 01 00 01 00 01 00 01 c8 32 c8 32 00 01 00 01
+0061 SDR OEM c0 0e Intel: 0b 01 01 23 07 10 21 90 01 01 08
+0062 SDR OEM c0 0e Intel: 0b 01 02 23 07 10 21 90 01 01 08
+0063 SDR OEM c0 0e Intel: 0b 01 04 23 07 10 21 90 01 01 08
+0064 SDR OEM c0 0e Intel: 0b 01 08 23 07 10 21 90 01 01 08
+0065 SDR OEM c0 0e Intel: 0b 01 10 23 07 10 21 90 01 01 08
+0066 SDR OEM c0 0e Intel: 0b 01 20 23 07 10 21 90 01 01 08
+0067 SDR OEM c0 0e Intel: 0b 01 40 23 07 10 21 90 01 01 08
+0068 SDR OEM c0 0e Intel: 0b 01 80 23 07 10 21 90 01 01 08
+0069 SDR OEM c0 0e Intel: 0b 02 ff 23 07 10 21 90 01 03 08
+006a SDR OEM c0 1a Intel: 0c 01 00 19 ff 01 02 03 20 21 64 00 41 10 04 14 26 19 2a 1e 31 23 38
+006b SDR OEM c0 1a Intel: 0c 01 00 19 ff 01 02 0c 20 21 64 00 41 10 04 14 28 19 2d 1e 35 23 3e
+006c SDR OEM c0 1a Intel: 0c 01 00 19 ff 01 02 30 20 21 64 00 41 10 04 14 2e 19 31 1e 3b 23 41
+006d SDR OEM c0 1a Intel: 0c 01 00 19 ff 01 02 c0 20 21 64 00 41 10 04 14 39 19 3c 1e 48 23 50
+006e SDR OEM c0 1a Intel: 0c 01 00 19 ff 01 02 03 20 21 64 00 41 50 04 14 32 19 37 1e 3f 23 4b
+006f SDR OEM c0 1a Intel: 0c 01 00 19 ff 01 02 0c 20 21 64 00 41 50 04 14 32 19 37 1e 41 23 55
+0070 SDR OEM c0 1a Intel: 0c 01 00 19 ff 01 02 30 20 21 64 00 41 50 04 14 37 00 37 1e 41 23 55
+0071 SDR OEM c0 1a Intel: 0c 01 00 19 ff 01 02 c0 20 21 64 00 41 50 04 14 46 00 37 1e 41 23 55
+0072 SDR OEM c0 15 Intel: 0c 01 00 19 ff 01 02 ff 20 63 64 00 42 28 40 00 00 11
+0073 SDR OEM c0 15 Intel: 0c 01 00 19 ff 01 02 ff 20 23 64 00 42 38 10 00 fc 00
+0074 SDR OEM c0 10 Intel: 0c 01 00 14 ff 01 02 ff ff 64 64 ff 00
+0075 SDR OEM c0 0e Intel: 0c 01 00 14 ff 01 02 ff fd 01 04
+0076 SDR OEM c0 1a Intel: 0c 01 01 19 ff 01 02 03 20 21 64 00 41 10 04 14 26 19 2a 1e 31 23 38
+0077 SDR OEM c0 1a Intel: 0c 01 01 19 ff 01 02 0c 20 21 64 00 41 10 04 14 28 19 2d 1e 35 23 3e
+0078 SDR OEM c0 1a Intel: 0c 01 01 19 ff 01 02 30 20 21 64 00 41 10 04 14 2e 19 31 1e 3b 23 41
+0079 SDR OEM c0 1a Intel: 0c 01 01 19 ff 01 02 c0 20 21 64 00 41 10 04 14 39 19 3c 1e 48 23 50
+007a SDR OEM c0 1a Intel: 0c 01 01 19 ff 01 02 03 20 21 64 00 41 50 04 14 32 19 37 1e 3f 23 4b
+007b SDR OEM c0 1a Intel: 0c 01 01 19 ff 01 02 0c 20 21 64 00 41 50 04 14 32 19 37 1e 41 23 55
+007c SDR OEM c0 1a Intel: 0c 01 01 19 ff 01 02 30 20 21 64 00 41 50 04 14 37 19 41 1e 55 23 64
+007d SDR OEM c0 1a Intel: 0c 01 01 19 ff 01 02 c0 20 21 64 00 41 50 04 14 46 19 50 1e 5a 23 64
+007e SDR OEM c0 15 Intel: 0c 01 01 19 ff 01 02 ff 20 62 64 00 42 28 40 00 00 01
+007f SDR OEM c0 15 Intel: 0c 01 01 19 ff 01 02 ff 20 24 64 00 42 38 10 00 fc 10
+0080 SDR OEM c0 10 Intel: 0c 01 01 14 ff 01 02 ff ff 64 64 ff 00
+0081 SDR OEM c0 0e Intel: 0c 01 01 14 ff 01 02 ff fd 01 04
+0082 SDR OEM c0 1a Intel: 0c 01 02 19 ff 01 02 03 20 21 64 00 41 10 04 14 26 19 2a 1e 31 23 38
+0083 SDR OEM c0 1a Intel: 0c 01 02 19 ff 01 02 0c 20 21 64 00 41 10 04 14 28 19 2d 1e 35 23 3e
+0084 SDR OEM c0 1a Intel: 0c 01 02 19 ff 01 02 30 20 21 64 00 41 10 04 14 2e 19 31 1e 3b 23 41
+0085 SDR OEM c0 1a Intel: 0c 01 02 19 ff 01 02 c0 20 21 64 00 41 10 04 14 39 19 3c 1e 48 23 50
+0086 SDR OEM c0 1a Intel: 0c 01 02 19 ff 01 02 03 20 21 64 00 41 50 04 14 32 19 37 1e 3f 23 4b
+0087 SDR OEM c0 1a Intel: 0c 01 02 19 ff 01 02 0c 20 21 64 00 41 50 04 14 32 19 37 1e 41 23 55
+0088 SDR OEM c0 1a Intel: 0c 01 02 19 ff 01 02 30 20 21 64 00 41 50 04 14 37 19 41 1e 55 23 64
+0089 SDR OEM c0 1a Intel: 0c 01 02 19 ff 01 02 c0 20 21 64 00 41 50 04 14 46 19 50 1e 5a 23 64
+008a SDR OEM c0 15 Intel: 0c 01 02 19 ff 01 02 ff 20 22 64 00 42 38 00 01 fb 00
+008b SDR OEM c0 10 Intel: 0c 01 02 14 ff 01 02 ff ff 64 64 ff 00
+008c SDR OEM c0 0e Intel: 0c 01 02 14 ff 01 02 ff fd 01 04
+008d SDR OEM c0 14 Intel: 0e 01 07 01 06 30 2a 31 2b 32 34 33 35 38 36 39 37
+008e GetSDR error 0xca Cannot return requested number of data bytes, rlen=0
+ SDR IPMI sensor: Power On Hours = 255 hours
+sensor Cannot return requested number of data bytes
diff --git a/test/sensor-TIGW1U.txt b/test/sensor-TIGW1U.txt
new file mode 100644
index 0000000..4426d2e
--- /dev/null
+++ b/test/sensor-TIGW1U.txt
@@ -0,0 +1,106 @@
+sensor: version 2.3
+-- BMC version 0.16, IPMI version 2.0
+_ID_ SDR_Type_xx Sz Own Typ S_Num Sens_Description Hex & Interp Reading
+0001 SDR Full 01 37 20 a 02 snum 10 BB +1.2V Vtt = be OK 1.20 Volts
+0002 SDR Full 01 3b 20 a 02 snum 11 BB+1.9V NIC Core = cb OK 1.91 Volts
+0003 SDR Full 01 37 20 a 02 snum 12 BB +1.5V AUX = bd OK 1.47 Volts
+0004 SDR Full 01 33 20 a 02 snum 13 BB +1.5V = 75 OK 1.52 Volts
+0005 SDR Full 01 33 20 a 02 snum 14 BB +1.8V = af OK 1.78 Volts
+0006 SDR Full 01 33 20 a 02 snum 15 BB +3.3V = c1 OK 3.32 Volts
+0007 SDR Full 01 37 20 a 02 snum 16 BB +3.3V STB = be OK 3.27 Volts
+0008 SDR Full 01 37 20 a 02 snum 17 BB +1.5V ESB = be OK 1.48 Volts
+0009 SDR Full 01 31 20 a 02 snum 18 BB +5V = c3 OK 5.07 Volts
+000a SDR Full 01 37 20 a 02 snum 19 BB +1.2V NIC = ed OK 1.21 Volts
+000b SDR Full 01 36 20 a 02 snum 1a BB +12V AUX = c1 OK 11.97 Volts
+000c SDR Full 01 33 20 a 02 snum 1b BB +0.9V = ba OK 0.89 Volts
+000d SDR Full 01 39 20 a 01 snum 30 Baseboard Temp = 30 OK 48.00 degrees C
+000e SDR Full 01 3b 20 a 01 snum 32 Front Panel Temp = 1a OK 26.00 degrees C
+000f SDR Full 01 31 20 m 04 snum 50 Fan 1A = 6f OK 7659.00 RPM
+0010 SDR Full 01 31 20 m 04 snum 51 Fan 1B = 6c OK 5508.00 RPM
+0011 SDR Full 01 31 20 m 04 snum 52 Fan 2A = 68 OK 7176.00 RPM
+0012 SDR Full 01 31 20 m 04 snum 53 Fan 2B = 6b OK 5457.00 RPM
+0013 SDR Full 01 31 20 m 04 snum 54 Fan 3A = 6c OK 7452.00 RPM
+0014 SDR Full 01 31 20 m 04 snum 55 Fan 3B = 6b OK 5457.00 RPM
+0015 SDR Full 01 31 20 m 04 snum 56 Fan 4A = 6f OK 7659.00 RPM
+0016 SDR Full 01 31 20 m 04 snum 57 Fan 4B = 69 OK 5355.00 RPM
+0017 SDR Full 01 30 20 m 04 snum 58 Fan 5 = 63 OK 6534.00 RPM
+0018 SDR Full 01 39 20 a 03 snum 78 PS1 AC Current = 05 OK 0.62 Amps
+0019 SDR Full 01 39 20 a 03 snum 79 PS2 AC Current = 16 OK 2.75 Amps
+001a SDR Full 01 3b 20 a 03 snum 7a PS1 +12V Current = 01 OK 0.50 Amps
+001b SDR Full 01 3b 20 a 03 snum 7b PS2 +12V Current = 11 OK 8.50 Amps
+001c SDR Full 01 39 20 a 0b snum 7c PS1 +12V Power = 01 OK 4.00 Watts
+001d SDR Full 01 39 20 a 0b snum 7d PS2 +12V Power = 19 OK 100.00 Watts
+001e SDR Full 01 3a 20 a 01 snum 99 P1 Therm Margin = c9 OK -55.00 degrees C
+001f SDR Full 01 3a 20 m 01 snum c0 P1 Therm Ctrl % = 00 OK 0.00 unspecified
+0020 SDR Full 01 36 20 a 02 snum d0 Proc 1 Vccp = c3 OK 1.21 Volts
+0021 SDR Full 01 38 c0 a 01 snum 01 SAS HSBP Temp = 1d OK* 29.00 degrees C
+0022 SDR Comp 02 25 20 a 09 snum 01 Power Unit = 00 c0 00 00 Enabled
+0023 SDR Comp 02 2b 20 a 09 snum 02 Power Redundancy = 00 c0 01 00 Redundant
+0024 SDR Comp 02 27 20 a 23 snum 03 BMC Watchdog = 00 c0 00 00 OK
+0025 SDR Comp 02 2a 20 a 06 snum 04 Scrty Violation = 00 c0 00 00 OK
+0026 SDR Comp 02 27 20 a 13 snum 07 FP Interrupt = 00 c0 00 00 OK
+0027 SDR Comp 02 2a 20 a 10 snum 09 Event Log Clear = 00 c0 00 00 OK
+0028 SDR Comp 02 28 20 a 2a snum 0a Session Audit = 00 c0 00 00 Activated
+0029 SDR Comp 02 27 20 a 12 snum 0b System Event = 00 c0 00 00 OK
+002a SDR Comp 02 22 20 a 29 snum 1e BB Vbat = 00 c0 00 00 OK*
+002b SDR Comp 02 25 20 a 08 snum 70 PS1 Status = 00 c0 01 00 Present
+002c SDR Comp 02 25 20 a 08 snum 71 PS2 Status = 00 c0 01 00 Present
+002d SDR Comp 02 25 20 a 22 snum 82 ACPI State = 00 c0 01 00 Working
+002e SDR Comp 02 21 20 a 14 snum 84 Button = 00 c0 00 00 OK
+002f SDR Comp 02 26 20 a f3 snum 85 SMI Timeout = 00 c0 01 00 Enabled
+0030 SDR Comp 02 24 20 a c0 snum 87 NMI State = 00 c0 01 00 Enabled
+0031 SDR Comp 02 24 20 a c0 snum 88 SMI State = 00 80 01 00 Enabled
+0032 SDR Comp 02 2b 20 m 07 snum 90 Processor 1 Stat = 00 c0 80 00 OK*
+0033 SDR Comp 02 25 20 a 13 snum a0 PCIe Link0 = 00 c0 00 00 OK
+0034 SDR Comp 02 25 20 a 13 snum a1 PCIe Link1 = 00 c0 00 00 OK
+0035 SDR Comp 02 25 20 a 13 snum a2 PCIe Link2 = 00 c0 00 00 OK
+0036 SDR Comp 02 25 20 a 13 snum a3 PCIe Link3 = 00 c0 00 00 OK
+0037 SDR Comp 02 25 20 a 13 snum a4 PCIe Link4 = 00 c0 00 00 OK
+0038 SDR Comp 02 25 20 a 13 snum a5 PCIe Link5 = 00 c0 00 00 OK
+0039 SDR Comp 02 25 20 a 13 snum a6 PCIe Link6 = 00 c0 00 00 OK
+003a SDR Comp 02 25 20 a 13 snum a7 PCIe Link7 = 00 c0 00 00 OK
+003b SDR Comp 02 25 20 a 13 snum a8 PCIe Link8 = 00 c0 00 00 OK
+003c SDR Comp 02 28 20 m 01 snum c8 CPU1 VRD Temp = 00 c0 00 00 OK*
+003d SDR Comp 02 27 20 a 02 snum d2 CPU1 Vcc OOR = 00 c0 00 00 OK
+003e SDR Comp 02 2a 20 a 07 snum d8 CPU Popul Error = 00 c0 00 00 OK
+003f SDR Comp 02 22 20 a 21 snum e0 DIMM 1A = 00 c0 04 00 Present
+0040 SDR Comp 02 22 20 a 21 snum e1 DIMM 2A = 00 e0 00 00 NotAvailable
+0041 SDR Comp 02 22 20 a 21 snum e2 DIMM 3A = 00 e0 00 00 NotAvailable
+0042 SDR Comp 02 22 20 a 21 snum e3 DIMM 1B = 00 c0 04 00 Present
+0043 SDR Comp 02 22 20 a 21 snum e4 DIMM 2B = 00 e0 00 00 NotAvailable
+0044 SDR Comp 02 22 20 a 21 snum e5 DIMM 3B = 00 e0 00 00 NotAvailable
+0045 SDR Comp 02 26 20 a 0c snum ec Mem A Error = 00 c0 00 00 OK
+0046 SDR Comp 02 26 20 a 0c snum ed Mem B Error = 00 c0 00 00 OK
+0047 SDR Comp 02 29 20 a 25 snum f0 DIMM Spare Enb = 00 e0 00 00 NotAvailable
+0048 SDR Comp 02 2a 20 a 0c snum f1 DIMM Spare Redu = 00 e0 00 00 NotAvailable
+0049 SDR Comp 02 29 c0 a 0d snum 02 SAS Drv 1 Stat = 00 d0 00 8e Ready
+004a SDR Comp 02 29 c0 a 0d snum 03 SAS Drv 2 Stat = 00 d0 00 8e Ready
+004b SDR Comp 02 29 c0 a 0d snum 04 SAS Drv 3 Stat = 00 d0 00 80 Unused
+004c SDR Comp 02 29 c0 a 0d snum 09 SAS Drv 1 Pres = 00 d0 02 80 Present
+004d SDR Comp 02 29 c0 a 0d snum 0a SAS Drv 2 Pres = 00 d0 02 80 Present
+004e SDR Comp 02 29 c0 a 0d snum 0b SAS Drv 3 Pres = 00 d0 00 80 Unused
+004f SDR FRU 11 18 dev: 20 00 80 00 0c 01 Baseboard FRU
+0050 SDR FRU 11 19 dev: 20 02 80 00 15 01 Power Dist FRU
+0051 SDR FRU 11 1b dev: 20 03 80 00 0a 01 Pwr Supply 1 FRU
+0052 SDR FRU 11 1b dev: 20 04 80 00 0a 02 Pwr Supply 2 FRU
+0053 SDR IPMB 12 1b dev: 20 00 bf 07 01 Basbrd Mgmt Ctlr
+0054 SDR IPMB 12 1b dev: c0 00 29 0f 01 SFP HotSwap Ctlr
+0055 SDR OEM c0 09 Intel: 02 02 00 01 70 71
+0056 SDR OEM c0 05 Intel: 06 01
+0057 SDR OEM c0 18 Intel: 0b 01 01 32 14 f0 0a a4 01 96 00 61 00 07 0a 64 05 00 00 00 00
+0058 SDR OEM c0 2c Intel: 0c 01 30 64 64 01 02 01 30 20 32 64 01 90 0d 00 2b 20 30 21 35 22 3a 23 3f 24 43 25 47 26 4c 27 51 28 56 29 5b 2a 60 2b 64
+0059 SDR OEM c0 2c Intel: 0c 02 30 64 64 01 02 01 30 20 32 64 01 90 0d 00 2b 20 30 21 35 22 3a 23 3f 24 43 25 47 26 4c 27 51 28 56 29 5b 2a 60 2b 64
+005a SDR OEM c0 2c Intel: 0c 03 30 64 64 01 02 01 30 20 32 64 01 90 0d 00 2b 20 30 21 35 22 3a 23 3f 24 43 25 47 26 4c 27 51 28 56 29 5b 2a 60 2b 64
+005b SDR OEM c0 15 Intel: 0c 01 64 64 64 01 02 01 00 20 99 64 02 90 01 06 00 11
+005c SDR OEM c0 15 Intel: 0c 02 64 64 64 01 02 01 00 20 99 64 02 90 01 06 00 11
+005d SDR OEM c0 15 Intel: 0c 03 64 64 64 01 02 01 00 20 30 64 02 90 01 02 3c 00
+005e SDR OEM c0 0e Intel: 08 00 00 45 88 45 88 45 88 45 88
+005f SDR OEM c0 16 Intel: 09 00 00 90 33 90 33 90 33 90 33 90 33 90 33 68 42 68 42
+0060 SDR OEM c0 08 Intel: BMC_TAM0 60 01 03 02 20 nrec=4 cfg=02
+0061 SDR OEM c0 31 Intel: BMC_TAM1 60 01 13 00 20 41 01 01 01 23 71 93 41 02 01 02 24 72 94 41 03 01 02 24 72 94 21 04 01 01 23 11 02 05 14 31 29 6f 01 13 23 21 09 0b 14 34
+0062 SDR OEM c0 31 Intel: BMC_TAM2 60 01 23 00 20 71 07 6f 03 13 23 33 43 55 83 11 08 6f 14 21 09 6f 54 64 20 7c 01 72 94 20 7d 01 72 94 11 21 6f 03 53 23 6f 05 15 25 35 85
+0063 SDR OEM c0 17 Intel: BMC_TAM3 60 01 33 00 c0 22 02 00 03 51 22 03 00 03 51 22 04 00 03 51
+0064 SDR OEM c0 0e Intel: SDR File 12
+0065 SDR OEM c0 11 Intel: SDR Package 12
+ SDR IPMI sensor: Power On Hours = 1014 hours
+sensor: completed successfully
diff --git a/test/testipmi.sh b/test/testipmi.sh
new file mode 100755
index 0000000..798705a
--- /dev/null
+++ b/test/testipmi.sh
@@ -0,0 +1,400 @@
+#!/bin/sh
+# testipmi.sh [node_ip]
+# Main test script for ipmiutil functions
+# Other files used:
+# ./ipmievt.sh
+# ./sensor-TIGW1U.txt
+# ./sensor-CG2100.txt
+#
+# If a remote node is specified as the target, it must be confiugred for
+# IPMI LAN and should have the ipmiutil_asy service running.
+#
+outf=/tmp/testipmi.out
+remote=0
+dosol=0
+# default remote node for SOL test
+node=192.168.1.154
+# use canned username and password, edit as needed.
+user=admin
+pswd=password
+mydir=`pwd`
+indir=`dirname $0`
+c1=`echo $indir |cut -c1`
+if [ "$c1" = "/" ]; then
+ testdir=$indir
+else
+ testdir=$mydir/$indir
+fi
+# datadir=/usr/share/ipmiutil
+datadir=/var/lib/ipmiutil
+# sfil is used only to read from with events -p -s below
+# normally, sfil=$datadir/sensor-out.txt
+sfil=${testdir}/sensor-TIGW1U.txt
+sfil2=${testdir}/sensor-CG2100.txt
+evtsh=${testdir}/ipmievt.sh
+tmpc=/tmp/cfg.tmp
+tmpin=/tmp/sol.in
+npass=0
+nfail=0
+# march=`rpmbuild --showrc |grep " _target_cpu" | head -n1 |awk '{print $3}'`
+uarch=`uname -m`
+LANPARAMS=
+os=`uname -s`
+if [ "$os" = "SunOS" ];then
+TAIL="tail -1"
+TAIL2="tail -2"
+else
+TAIL="tail -n1"
+TAIL2="tail -n2"
+fi
+
+errexit() {
+ rv=$1
+ echo "FAIL $rv"
+ nfail=`expr $nfail + 1`
+ echo "## Passed=$npass, Failed=$nfail, see $outf for detailed results"
+ exit $rv
+}
+
+waitready() {
+ i=0
+ while [ 1 ]; do
+ if [ $i -gt 15 ]; then
+ return 1
+ fi
+ echo "wait for ready: loop $i ..."
+ ipmiutil wdt $LANPARAMS
+ if [ $? -eq 0 ]; then
+ return 0
+ else
+ sleep 1
+ fi
+ i=`expr $i + 1`
+ done
+}
+
+runcmd() {
+ # runcmd checks for the tag 'successful' in the output and exits otherwise.
+ CMD="$*"
+ TAG=`echo $CMD |cut -f1-3 -d' '`
+ tmpcmd=/tmp/cmdout.$$
+ echo -n "$TAG ... "
+ echo "# $CMD" > $tmpcmd
+ $CMD >>$tmpcmd 2>&1
+ rv=$?
+ $TAIL $tmpcmd | grep successful >/dev/null
+ success=$?
+ cat $tmpcmd >>$outf
+ if [ $success -ne 0 ]; then
+ if [ $rv -eq 0 ]; then
+ rv=1
+ fi
+ echo "FAIL $rv"
+ echo "=== $CMD FAIL $rv" >>$outf
+ nfail=`expr $nfail + 1`
+ else
+ echo "PASS"
+ echo "=== $CMD PASS" >>$outf
+ npass=`expr $npass + 1`
+ fi
+ return $rv
+}
+
+runcmdr() {
+ # runcmdr checks only the return value for 0, and exits otherwise.
+ CMD="$*"
+ TAG=`echo $CMD |cut -f1-3 -d' '`
+ tmpcmd=/tmp/cmdoutr.$$
+ echo -n "$TAG ... "
+ echo "# $CMD" > $tmpcmd
+ $CMD >>$tmpcmd 2>&1
+ rv=$?
+ cat $tmpcmd >>$outf
+ if [ $rv -ne 0 ]; then
+ echo "FAIL $rv"
+ echo "=== $CMD FAIL $rv" >>$outf
+ nfail=`expr $nfail + 1`
+ else
+ echo "PASS"
+ echo "=== $CMD PASS" >>$outf
+ npass=`expr $npass + 1`
+ fi
+ return $rv
+}
+
+if [ $# -ge 1 ];then
+ node=$1
+ LANPARAMS="-N $node -U $user -P $pswd"
+ remote=1
+ dosol=1
+fi
+
+>$outf
+pushd /tmp
+
+echo "## testipmi.sh $LANPARAMS" | tee -a $outf
+if [ ! -f $sfil ]; then
+ echo "Cannot find required file $sfil"
+ echo "Make sure that $sfil, $sfil2, and $evtsh are present."
+ exit 1
+fi
+if [ ! -f $sfil2 ]; then
+ echo "Cannot find required file $sfil2"
+ echo "Make sure that $sfil, $sfil2, and $evtsh are present."
+ exit 1
+fi
+if [ ! -x $evtsh ]; then
+ echo "Cannot find required file $evtsh"
+ echo "Make sure that $sfil, $sfil2, and $evtsh are present."
+ exit 1
+fi
+
+runcmd "ipmiutil health $LANPARAMS"
+runcmd "ipmiutil health -x $LANPARAMS"
+runcmd "ipmiutil health -c $LANPARAMS"
+runcmd "ipmiutil health -f -g -h -s -c $LANPARAMS"
+
+runcmd "ipmiutil cmd -x $LANPARAMS 00 20 18 01 "
+runcmdr "ipmiutil cmd -q $LANPARAMS 00 20 18 01 "
+
+runcmd "ipmiutil fru -b $LANPARAMS"
+MODEL=`grep "Chassis OEM Field" $outf| cut -f2 -d':'| awk '{ print $1 }'`
+ASSET=`grep "Product Asset Tag" $outf| cut -f2 -d':'| awk '{ print $1 }'`
+runcmd "ipmiutil fru $LANPARAMS"
+runcmd "ipmiutil fru -c $LANPARAMS"
+runcmd "ipmiutil fru -i 00 -m 002000s $LANPARAMS"
+runcmd "ipmiutil fru -a test_asset $LANPARAMS" -V4
+runcmd "ipmiutil fru -a ${ASSET} $LANPARAMS" -V4
+
+runcmd "ipmiutil config $LANPARAMS -s $tmpc"
+
+runcmd "ipmiutil lan -c $LANPARAMS "
+IPADDR=`grep "IP address" $outf| tail -n1|cut -f2 -d'|'| awk '{ print $1 }'`
+if [ "x$IPADDR" = "x0.0.0.0" ]; then
+ # if not already configured, use value from node variable.
+ IPADDR=$node
+fi
+if [ $remote -eq 0 ]; then
+ runcmd "ipmiutil lan -e -I $IPADDR -u $user -p $pswd $LANPARAMS "
+fi
+runcmd "ipmiutil lan $LANPARAMS "
+if [ $remote -eq 0 ]; then
+ # restore previous IPMI LAN settings
+ runcmd "ipmiutil config $LANPARAMS -r $tmpc"
+fi
+
+ipmiutil serial | grep "No serial channel" >/dev/null 2>&1
+if [ $? -ne 0 ]; then
+ runcmd "ipmiutil serial $LANPARAMS"
+ runcmd "ipmiutil serial -c $LANPARAMS"
+fi
+
+tmpsel=/tmp/selout.$$
+runcmd "ipmiutil sel $LANPARAMS"
+runcmd "ipmiutil sel -e $LANPARAMS"
+runcmd "ipmiutil sel -v $LANPARAMS"
+runcmd "ipmiutil sel -l5 $LANPARAMS"
+echo -n "ipmiutil sel -r"
+ipmiutil sel -r -l20 $LANPARAMS >$tmpsel
+if [ $? -ne 0 ]; then
+ echo "... FAIL $rv" |tee -a $outf
+ nfail=`expr $nfail + 1`
+fi
+echo " ... PASS" |tee -a $outf
+npass=`expr $npass + 1`
+runcmd "ipmiutil sel -f $tmpsel $LANPARAMS "
+
+runcmd "ipmiutil sensor $LANPARAMS"
+runcmd "ipmiutil sensor -v $LANPARAMS"
+runcmd "ipmiutil sensor -g temp,fan,voltage $LANPARAMS"
+runcmd "ipmiutil sensor -c $LANPARAMS"
+if [ $remote -eq 0 ]; then
+ runcmd "$evtsh"
+fi
+
+# Test getevt SEL method
+runcmdr "ipmiutil getevt -s $LANPARAMS -t 3 "
+if [ $remote -eq 0 ]; then
+ # if local, also test getevt MessageBuffer method
+ runcmdr "ipmiutil getevt $LANPARAMS -t 3 "
+fi
+
+# Do not run SOL test if no remote server is configured for SOL.
+if [ $dosol -eq 1 ]; then
+ # runcmd "ipmiutil sol -d $LANPARAMS " (do not check success)
+ echo -n "ipmiutil sol -d ... "
+ echo "# ipmiutil sol -d $LANPARAMS " >> $outf
+ ipmiutil sol -d $LANPARAMS >>$outf 2>&1
+ if [ $? -eq -3 ]; then
+ echo "FAIL"
+ echo "=== ipmiutil sol -d FAIL" >>$outf
+ nfail=`expr $nfail + 1`
+ else
+ echo "PASS"
+ echo "=== ipmiutil sol -d PASS" >>$outf
+ npass=`expr $npass + 1`
+ fi
+
+ cat - <<%%% >$tmpin
+
+root
+password
+ls
+pwd
+echo success
+exit
+~.
+%%%
+ runcmd "ipmiutil sol -a $LANPARAMS -i $tmpin"
+fi
+
+
+runcmd "ipmiutil wdt $LANPARAMS"
+runcmd "ipmiutil wdt -e -a0 -t 5 -p 2 $LANPARAMS"
+runcmd "ipmiutil wdt -c $LANPARAMS"
+runcmd "ipmiutil wdt -r $LANPARAMS"
+sleep 5
+runcmd "ipmiutil wdt -d $LANPARAMS"
+runcmd "ipmiutil sel -l5 $LANPARAMS"
+
+runcmdr "ipmiutil discover -a"
+
+CMD="ipmiutil events 18 00 02 02 00 00 00 20 00 04 09 01 6f 44 0f ff"
+echo -n "ipmiutil events (AC Lost)"
+echo "# $CMD" >>$outf
+$CMD >>$outf
+$TAIL2 $outf |grep "AC Lost" >/dev/null
+if [ $? -ne 0 ]; then
+ echo " ... FAIL 1" |tee -a $outf
+ nfail=`expr $nfail + 1`
+fi
+echo " ... PASS" |tee -a $outf
+npass=`expr $npass + 1`
+
+CMD="ievents -p -s $sfil B3 E8 00 0E 0C C7 1B A0 11 08 12 7F 10 90 FF FF 20 20 00 20 02 15 01 41 0F FF"
+echo -n "ievents -p (Redundancy Lost)"
+echo "# $CMD" >>$outf
+$CMD >>$outf
+$TAIL2 $outf |grep "Redundancy Lost" >/dev/null
+if [ $? -ne 0 ]; then
+ echo " ... FAIL 1" |tee -a $outf
+ nfail=`expr $nfail + 1`
+fi
+echo " ... PASS" |tee -a $outf
+npass=`expr $npass + 1`
+
+CMD="ipmiutil events -s $sfil2 -p B5 19 00 15 17 C6 C9 D0 00 02 B2 76 C1 16 FF FF 20 20 10 20 20 00 00 52 1D 20 00 00 00 00 00 00 00 00 00 00 00 00 C1 00 00 00 00 00 00 00 00 00 00"
+echo -n "ipmiutil events -p (Lo Crit)"
+echo "# $CMD" >>$outf
+$CMD >>$outf
+$TAIL2 $outf |grep "Lo Crit thresh" >/dev/null
+if [ $? -ne 0 ]; then
+ echo " ... FAIL 1" |tee -a $outf
+ nfail=`expr $nfail + 1`
+fi
+echo " ... PASS" |tee -a $outf
+npass=`expr $npass + 1`
+
+# The alarms command will fail on systems without an alarm panel.
+echo "MODEL=$MODEL" >> $outf
+case "$MODEL" in
+ TIGW1U) tamok=1
+ ;;
+ TIGH2U) tamok=1
+ ;;
+ TIGI2U) tamok=1
+ ;;
+ TIGPR2U) tamok=1
+ ;;
+ TIGPT1U) tamok=1
+ ;;
+ TSRLT2) tamok=1
+ ;;
+ TSRMT2) tamok=1
+ ;;
+ CG2100) tamok=1
+ ;;
+ *) tamok=0
+ ;;
+esac
+if [ $tamok -eq 1 ]; then
+ picmg=0
+ runcmd "ipmiutil alarms $LANPARAMS"
+ runcmdr "ipmiutil alarms -m1 -n1 $LANPARAMS"
+ runcmdr "ipmiutil alarms -o $LANPARAMS"
+fi
+runcmd "ipmiutil alarms -i10 $LANPARAMS"
+
+# The rackmount servers with TAM are not PICMG,
+# so if the have TAM, skip the PICMG test.
+# otherwise try a PICMG test.
+if [ $tamok -eq 0 ]; then
+ picmg=1
+ CMD="ipmiutil picmg $LANPARAMS properties"
+ echo -n "$CMD"
+ echo "# $CMD" >>$outf
+ $CMD >>$outf
+ rv=$?
+ if [ $rv -eq 193 ]; then
+ echo " ... N/A"
+ picmg=0
+ elif [ $? -ne 0 ]; then
+ echo " ... FAIL $rv" |tee -a $outf
+ nfail=`expr $nfail + 1`
+ else
+ echo " ... PASS" |tee -a $outf
+ npass=`expr $npass + 1`
+ fi
+fi
+
+# The firmware firewall feature is only for PICMG
+if [ $picmg -eq 1 ]; then
+ CMD="ipmiutil firewall $LANPARAMS info"
+ echo -n "$CMD"
+ echo "# $CMD" >>$outf
+ $CMD >>$outf
+ rv=$?
+ if [ $rv -ne 0 ]; then
+ echo " ... FAIL $rv" |tee -a $outf
+ nfail=`expr $nfail + 1`
+ else
+ echo " ... PASS" |tee -a $outf
+ npass=`expr $npass + 1`
+ fi
+fi
+
+if [ "$uarch" = "ia64" ]
+then
+ # Note that ireset -n (NMI) causes a full reset on ia64
+ echo "ia64, so skip ipmiutil reset -n" |tee -a $outf
+else
+ # Use hwreset -n to send an NMI.
+ runcmd "ipmiutil reset -n $LANPARAMS "
+fi
+if [ $remote -eq 1 ]; then
+ # reset if the system is remote
+ runcmd "ipmiutil reset -o $LANPARAMS "
+ # after soft-reboot, could do waitready here instead
+ sleep 80
+ runcmd "ipmiutil reset -r -w $LANPARAMS "
+ sleep 1
+ runcmd "ipmiutil reset -c -w $LANPARAMS "
+ sleep 1
+ runcmd "ipmiutil reset -d -w $LANPARAMS "
+ sleep 1
+ runcmd "ipmiutil reset -w -u $LANPARAMS "
+ # if the system isn't fully down yet, the up request may be ignored.
+ sleep 1
+ runcmd "ipmiutil reset -u $LANPARAMS "
+ # wait for init to complete
+ sleep 80
+ # Should be up now, but some systems take a bit longer for
+ # everything to come back up. So we do this last.
+fi
+
+echo "## Passed=$npass, Failed=$nfail, see $outf for detailed results"
+# remove temp files (tmpcmdr=/tmp/cmdoutr.$$ tmpcmd=/tmp/cmdout.$$)
+rm -f $tmpc $tmpin /tmp/cmdout* /tmp/selout*
+popd
+exit 0
+
diff --git a/test/unittest.cmd b/test/unittest.cmd
new file mode 100644
index 0000000..fcee7da
--- /dev/null
+++ b/test/unittest.cmd
@@ -0,0 +1,125 @@
+@echo off
+REM #!/bin/sh
+REM # unittest.cmd
+REM # Basic unit test for ipmiutil functions
+REM #
+REM # default remote node for SOL test
+set node=192.168.134.52
+set testdir=c:\temp
+set LANPARAMS=-N %node% -U ADMIN -P ADMIN
+REM set LANPARAMS=
+REM # datadir=/usr/share/ipmiutil
+REM # sfil is used only to read from with events -p -s below
+REM # normally, sfil=%datadir%/sensor-out.txt
+set outf=%testdir%\unittest.out
+set sfil=%testdir%\sensor-TIGW1U.txt
+set sfil2=%testdir%\sensor-CG2100.txt
+set tmpc=%testdir%\cfg.tmp
+set tmpin=%testdir%\sol.in
+
+echo "# ipmiutil health %LANPARAMS%" > %outf%
+ipmiutil health %LANPARAMS% >> %outf%
+ findstr /C:"health, completed successfully" %outf%
+
+echo "# ipmiutil cmd %LANPARAMS% -x 00 20 18 01 " >> %outf%
+ipmiutil cmd %LANPARAMS% -x 00 20 18 01 >> %outf%
+ findstr /C:"cmd, completed successfully" %outf%
+
+echo "# ipmiutil fru %LANPARAMS%" >> %outf%
+ipmiutil fru %LANPARAMS% >> %outf%
+ findstr /C:"fru, completed successfully" %outf%
+
+echo "# ipmiutil config %LANPARAMS% -s %tmpc%" >> %outf%
+ipmiutil config %LANPARAMS% -s %tmpc% >> %outf%
+ findstr /C:"config, completed successfully" %outf%
+
+echo "# ipmiutil lan %LANPARAMS% " >> %outf%
+ipmiutil lan %LANPARAMS% >> %outf%
+ findstr /C:"lan, completed successfully" %outf%
+
+echo "# ipmiutil sel %LANPARAMS%" >> %outf%
+ipmiutil sel %LANPARAMS% >> %outf%
+ findstr /C:"sel, completed successfully" %outf%
+
+echo "# ipmiutil sel -e %LANPARAMS%" >> %outf%
+ipmiutil sel -e %LANPARAMS% >> %outf%
+ findstr /C:"sel, completed successfully" %outf%
+
+echo "# ipmiutil sensor %LANPARAMS%" >> %outf%
+ipmiutil sensor %LANPARAMS% >> %outf%
+ findstr /C:"sensor, completed successfully" %outf%
+
+REM # ipmiutil discover -a -b 10.243.42.255 >> %outf%
+echo "# ipmiutil discover -a" >> %outf%
+ipmiutil discover -a >> %outf%
+ findstr /C:"responses" %outf%
+
+REM # Test getevt SEL method
+echo "# ipmiutil getevt -s %LANPARAMS% -t 3 " >> %outf%
+ipmiutil getevt -s %LANPARAMS% -t 3 >> %outf%
+echo "getevt -s errorlevel %errorlevel%" >> %outf%
+REM if errorlevel
+
+REM # if local, also test getevt MessageBuffer method
+echo "# ipmiutil getevt %LANPARAMS% -t 3 " >> %outf%
+ipmiutil getevt %LANPARAMS% -t 3 >> %outf%
+echo "getevt errorlevel %errorlevel%" >> %outf%
+REM if errorlevel
+
+ REM # Use hwreset -n to send an NMI.
+ echo "# ipmiutil reset %LANPARAMS% -n" >> %outf%
+ ipmiutil reset %LANPARAMS% -n >> %outf%
+ findstr /C:"reset, completed successfully" %outf%
+
+REM # Might skip SOL test if no remote server is configured for SOL.
+ echo "# ipmiutil sol -d %LANPARAMS% " >> %outf%
+ ipmiutil sol -d %LANPARAMS% >> %outf%
+
+ echo " " >%tmpin%
+ echo "root" >>%tmpin%
+ echo "password" >>%tmpin%
+ echo "ls" >>%tmpin%
+ echo "pwd" >>%tmpin%
+ echo "exit" >>%tmpin%
+ echo "~." >>%tmpin%
+ echo "# ipmiutil sol -a %LANPARAMS% -i %tmpin%" >> %outf%
+ ipmiutil sol -a %LANPARAMS% -i %tmpin% >> %outf%
+ findstr /C:"sol, completed successfully" %outf%
+
+echo "# ipmiutil events 18 00 02 02 00 00 00 20 00 04 09 01 6f 44 0f ff " >> %outf%
+ipmiutil events 18 00 02 02 00 00 00 20 00 04 09 01 6f 44 0f ff >> %outf%
+ findstr /C:"AC Lost" %outf%
+
+echo "# ievents -p -s %sfil% B3 E8 00 0E 0C C7 1B A0 11 08 12 7F 10 90 FF FF 20 20 00 20 02 15 01 41 0F FF " >> %outf%
+ievents -p -s %sfil% B3 E8 00 0E 0C C7 1B A0 11 08 12 7F 10 90 FF FF 20 20 00 20 02 15 01 41 0F FF >> %outf%
+ findstr /C:"Redundancy Lost" %outf%
+
+echo "# ipmiutil events -s %sfil2% -p B5 19 00 15 17 C6 C9 D0 00 02 B2 76 C1 16 FF FF 20 20 10 20 20 00 00 52 1D 20 00 00 00 00 00 00 00 00 00 00 00 00 C1 00 00 00 00 00 00 00 00 00 00" >> %outf%
+ipmiutil events -s %sfil2% -p B5 19 00 15 17 C6 C9 D0 00 02 B2 76 C1 16 FF FF 20 20 10 20 20 00 00 52 1D 20 00 00 00 00 00 00 00 00 00 00 00 00 C1 00 00 00 00 00 00 00 00 00 00 >> %outf%
+ findstr /C:"Lo Crit thresh" %outf%
+
+echo "# ievents 40 78 02 37 86 41 4e 20 00 04 0c 08 6f 20 ff 04" >> %outf%
+ievents 40 78 02 37 86 41 4e 20 00 04 0c 08 6f 20 ff 04 >> %outf%
+ findstr /C:"DIMM" %outf%
+
+echo "# ipmiutil events -d 40 78 02 37 86 41 4e 20 00 04 0c 08 6f 20 ff 04" >> %outf%
+ipmiutil events -d 40 78 02 37 86 41 4e 20 00 04 0c 08 6f 20 ff 04 >> %outf%
+ findstr /C:"DIMM" %outf%
+
+echo "# ipmiutil wdt %LANPARAMS%" >> %outf%
+ipmiutil wdt %LANPARAMS% >> %outf%
+ findstr /C:"wdt, completed successfully" %outf%
+
+REM # some platforms do not support IPMI serial channels
+ echo "# ipmiutil serial %LANPARAMS%" >> %outf%
+ ipmiutil serial %LANPARAMS% >> %outf%
+ findstr /C:"serial, completed successfully" %outf%
+
+REM # The model can be used to detect if the chassis has an alarm panel.
+REM echo "MODEL=%MODEL%" >> %outf%
+REM # Run it anyway, the alarms command has better detection now.
+
+ echo "# ipmiutil alarms %LANPARAMS%" >> %outf%
+ ipmiutil alarms %LANPARAMS% >> %outf%
+ findstr /C:"alarms, completed successfully" %outf%
+
diff --git a/test/unittest.sh b/test/unittest.sh
new file mode 100755
index 0000000..f1ac9ab
--- /dev/null
+++ b/test/unittest.sh
@@ -0,0 +1,254 @@
+#!/bin/sh
+# unittest.sh [node_ip]
+# Basic unit test for ipmiutil functions
+#
+dosol=0
+doserial=0
+outf=/tmp/unittest.out
+# default remote node for SOL test
+node=192.168.1.154
+mydir=`pwd`
+indir=`dirname $0`
+c1=`echo $indir |cut -c1`
+if [ "$c1" = "/" ]; then
+ testdir=$indir
+else
+ testdir=$mydir/$indir
+fi
+# datadir=/usr/share/ipmiutil
+datadir=/var/lib/ipmiutil
+# sfil is used only to read from with events -p -s below
+# normally, sfil=$datadir/sensor-out.txt
+sfil=${testdir}/sensor-TIGW1U.txt
+sfil2=${testdir}/sensor-CG2100.txt
+tmpc=/tmp/cfg.tmp
+tmpin=/tmp/sol.in
+# march=`rpmbuild --showrc |grep " _target_cpu" | head -n1 |awk '{print $3}'`
+uarch=`uname -m`
+LANPARAMS=
+os=`uname -s`
+if [ "$os" = "SunOS" ];then
+TAIL="tail -1"
+TAIL2="tail -2"
+else
+TAIL="tail -n1"
+TAIL2="tail -n2"
+fi
+
+if [ $# -ge 1 ];then
+ node=$1
+ # use canned username and password, edit as needed.
+ LANPARAMS="-N $node -U admin -P password"
+fi
+
+>$outf
+cd /tmp
+echo "# ipmiutil sel -v $LANPARAMS" |tee -a $outf
+ipmiutil sel -v $LANPARAMS >>$outf 2>&1
+if [ $? -ne 0 ]; then
+ echo "No IPMI support detected"
+ exit 1
+fi
+
+echo "# ipmiutil health $LANPARAMS" |tee -a $outf
+ipmiutil health $LANPARAMS |tee -a $outf
+$TAIL $outf |grep successful >/dev/null
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+echo "# ipmiutil cmd $LANPARAMS -x 00 20 18 01 " |tee -a $outf
+ipmiutil cmd $LANPARAMS -x 00 20 18 01 2>&1 |tee -a $outf
+$TAIL $outf |grep successful >/dev/null
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+echo "# ipmiutil fru $LANPARAMS" |tee -a $outf
+ipmiutil fru $LANPARAMS 2>&1 |tee -a $outf
+$TAIL $outf |grep successful >/dev/null
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+MODEL=`grep "Chassis OEM Field" $outf| cut -f2 -d':'| awk '{ print $1 }'`
+echo "# ipmiutil config $LANPARAMS -s $tmpc" |tee -a $outf
+ipmiutil config $LANPARAMS -s $tmpc 2>&1 |tee -a $outf
+$TAIL $outf |grep successful >/dev/null
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+echo "# ipmiutil lan $LANPARAMS " |tee -a $outf
+ipmiutil lan $LANPARAMS 2>&1 |tee -a $outf
+$TAIL $outf |grep successful >/dev/null
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+echo "# ipmiutil sel $LANPARAMS" |tee -a $outf
+ipmiutil sel $LANPARAMS 2>&1 |tee -a $outf
+$TAIL $outf |grep successful >/dev/null
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+echo "# ipmiutil sel -e $LANPARAMS" |tee -a $outf
+ipmiutil sel -e $LANPARAMS 2>&1 |tee -a $outf
+$TAIL $outf |grep successful >/dev/null
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+echo "# ipmiutil sensor $LANPARAMS" |tee -a $outf
+ipmiutil sensor $LANPARAMS 2>&1 |tee -a $outf
+$TAIL $outf |grep successful >/dev/null
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+# ipmiutil discover -a -b 10.243.42.255 |tee -a $outf
+echo "# ipmiutil discover -a" |tee -a $outf
+ipmiutil discover -a 2>&1 |tee -a $outf
+$TAIL2 $outf |grep responses >/dev/null
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+# Test getevt SEL method
+echo "# ipmiutil getevt -s $LANPARAMS -t 3 " |tee -a $outf
+ipmiutil getevt -s $LANPARAMS -t 3 2>&1 |tee -a $outf
+rv=$?
+# $TAIL $outf |grep successful >/dev/null
+if [ $rv -ne 0 ]; then
+ echo "igetevt error $rv"
+ exit 1
+fi
+
+if [ "x$LANPARAMS" = "x" ]; then
+# if local, also test getevt MessageBuffer method
+echo "# ipmiutil getevt $LANPARAMS -t 3 " |tee -a $outf
+ipmiutil getevt $LANPARAMS -t 3 2>&1 |tee -a $outf
+rv=$?
+# $TAIL $outf |grep successful >/dev/null
+if [ $rv -ne 0 ]; then
+ echo "igetevt error $rv"
+ exit 1
+fi
+fi
+
+if [ "$uarch" = "ia64" ]
+then
+ # Note that ireset -n causes a real reset on ia64 (?)
+ echo "skipping ia64 ipmiutil reset" |tee -a $outf
+else
+ # Use hwreset -n to send an NMI.
+ echo "# ipmiutil reset $LANPARAMS -n" |tee -a $outf
+ ipmiutil reset $LANPARAMS -n 2>&1 |tee -a $outf
+ $TAIL $outf |grep successful >/dev/null
+ if [ $? -ne 0 ]; then
+ exit 1
+ fi
+fi
+
+# Might not do SOL test if no remote server is configured for SOL.
+if [ $dosol -eq 1 ]; then
+ echo "# ipmiutil sol -d -N $node " |tee -a $outf
+ ipmiutil sol -d -N $node 2>&1 |tee -a $outf
+ cat - <<%%% >$tmpin
+
+root
+password
+ls
+pwd
+echo success
+exit
+~.
+%%%
+ echo "# ipmiutil sol -a -N $node -i $tmpin " |tee -a $outf
+ ipmiutil sol -a -N $node -i $tmpin 2>&1 |tee -a $outf
+ $TAIL $outf |grep successful >/dev/null
+ if [ $? -ne 0 ]; then
+ exit 1
+ fi
+fi
+
+echo "# ipmiutil events 18 00 02 02 00 00 00 20 00 04 09 01 6f 44 0f ff " |tee -a $outf
+ipmiutil events 18 00 02 02 00 00 00 20 00 04 09 01 6f 44 0f ff |tee -a $outf
+$TAIL2 $outf |grep "AC Lost" >/dev/null
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+
+echo "# ievents -p -s $sfil B3 E8 00 0E 0C C7 1B A0 11 08 12 7F 10 90 FF FF 20 20 00 20 02 15 01 41 0F FF " |tee -a $outf
+ievents -p -s $sfil B3 E8 00 0E 0C C7 1B A0 11 08 12 7F 10 90 FF FF 20 20 00 20 02 15 01 41 0F FF |tee -a $outf
+$TAIL2 $outf |grep "Redundancy Lost" >/dev/null
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+
+echo "# ipmiutil events -s $sfil2 -p B5 19 00 15 17 C6 C9 D0 00 02 B2 76 C1 16 FF FF 20 20 10 20 20 00 00 52 1D 20 00 00 00 00 00 00 00 00 00 00 00 00 C1 00 00 00 00 00 00 00 00 00 00" |tee -a $outf
+ipmiutil events -s $sfil2 -p B5 19 00 15 17 C6 C9 D0 00 02 B2 76 C1 16 FF FF 20 20 10 20 20 00 00 52 1D 20 00 00 00 00 00 00 00 00 00 00 00 00 C1 00 00 00 00 00 00 00 00 00 00 |tee -a $outf
+$TAIL2 $outf |grep "Lo Crit thresh" >/dev/null
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+
+echo "# ievents 40 78 02 37 86 41 4e 20 00 04 0c 08 6f 20 ff 04" |tee -a $outf
+ievents 40 78 02 37 86 41 4e 20 00 04 0c 08 6f 20 ff 04 |tee -a $outf
+$TAIL2 $outf |grep DIMM >/dev/null
+if [ $? -ne 0 ]; then
+ echo "DIMM event FAIL"
+ exit 1
+fi
+
+echo "# ipmiutil events -d 40 78 02 37 86 41 4e 20 00 04 0c 08 6f 20 ff 04" |tee -a $outf
+ipmiutil events -d 40 78 02 37 86 41 4e 20 00 04 0c 08 6f 20 ff 04 |tee -a $outf
+$TAIL2 $outf |grep DIMM >/dev/null
+if [ $? -ne 0 ]; then
+ echo "DIMM event FAIL"
+ exit 1
+fi
+
+echo "# ipmiutil wdt $LANPARAMS" |tee -a $outf
+ipmiutil wdt $LANPARAMS 2>&1 |tee -a $outf
+$TAIL $outf |grep successful >/dev/null
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+
+if [ $doserial -eq 1 ]; then
+ # some platforms do not support IPMI serial channels
+ echo "# ipmiutil serial $LANPARAMS" |tee -a $outf
+ ipmiutil serial $LANPARAMS 2>&1 |tee -a $outf
+ $TAIL $outf |grep successful >/dev/null
+ if [ $? -ne 0 ]; then
+ exit 1
+ fi
+fi
+
+# The model can be used to detect if the chassis has an alarm panel.
+echo "MODEL=$MODEL" |tee -a $outf
+case "$MODEL" in
+ TIGW1U) tamok=1
+ ;;
+ TIGH2U) tamok=1
+ ;;
+ TIGI2U) tamok=1
+ ;;
+ TIGPR2U) tamok=1
+ ;;
+ TIGPT1U) tamok=1
+ ;;
+ TSRLT2) tamok=1
+ ;;
+ TSRMT2) tamok=1
+ ;;
+ CG2100) tamok=1
+ ;;
+ *) tamok=0
+ ;;
+esac
+# Run it anyway, the alarms command has better detection now.
+tamok=1
+if [ $tamok -eq 1 ]; then
+ echo "# ipmiutil alarms $LANPARAMS" |tee -a $outf
+ ipmiutil alarms $LANPARAMS 2>&1 |tee -a $outf
+ $TAIL $outf |grep successful >/dev/null
+ if [ $? -ne 0 ]; then
+ exit 1
+ fi
+fi
+cd $mydir
+
diff --git a/util/AnsiTerm.cpp b/util/AnsiTerm.cpp
new file mode 100644
index 0000000..be94465
--- /dev/null
+++ b/util/AnsiTerm.cpp
@@ -0,0 +1,1892 @@
+/*
+ * 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.
+ *
+ * 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 <windows.h>
+#include <stdio.h>
+#include <assert.h>
+#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))
+ {
+ 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))
+ {
+ 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)
+{
+ if (m_bPrivateParameters)
+ {
+ for (int index = 0; index < m_ParameterCount; index++)
+ {
+ switch (m_Parameters[index])
+ {
+ case 0:
+ default:
+ assert(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: assert(false); break;
+ }
+ }
+ }
+ return true;
+}
+
+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:
+ assert(false);
+ 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:
+ 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);
+ }
+}
+
+}
diff --git a/util/AnsiTerm.h b/util/AnsiTerm.h
new file mode 100644
index 0000000..13d10f2
--- /dev/null
+++ b/util/AnsiTerm.h
@@ -0,0 +1,316 @@
+/*
+ * 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
+};
diff --git a/util/Makefile.am b/util/Makefile.am
new file mode 100644
index 0000000..3726107
--- /dev/null
+++ b/util/Makefile.am
@@ -0,0 +1,200 @@
+
+localedir = $(datadir)/locale
+INCLUDES = -I..
+OS_CF = @OS_CFLAGS@ @CROSS_CFLAGS@
+OS_LF = @OS_LFLAGS@ @CROSS_LFLAGS@
+AM_CPPFLAGS = $(OS_CF) -DLOCALEDIR=\"$(localedir)\"
+AM_CPPFLAGS += @IA64_CFLAGS@ @GPL_CFLAGS@
+LDADD = $(OS_LF)
+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
+LIBOBJ = ipmicmd.o mem_if.o ipmidir.o imbapi.o ipmimv.o ipmild.o ipmibmc.o ipmilipmi.o subs.o md5.o md2.o $(tmpobj)/ipmilan.o $(tmpobj)/ipmilanplus.o
+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 iekanalyzer.c
+
+
+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 $(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
+SHR_LIB = libipmiutil.so
+SHRLINK = @SHR_LINK@
+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
+
+# 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@
+ mkdir -p $(tmpobj)
+ if [ "x@LANPLUS_SAM@" = "xyes" ]; then \
+ $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilanplus.o -c ipmilanplus.c; \
+ $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilan.o -c ipmilan.c; \
+ ar x @LANPLUS_LIB@ ; \
+ $(AR) cru $(DEV_LIB) $(LIBOBJ) $(LANPLUS_OBJ); \
+ $(RANLIB) $(DEV_LIB); \
+ else \
+ $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilanplus.o -c ipmilanplus.c; \
+ $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilan.o -c ipmilan.c; \
+ $(AR) cru $(DEV_LIB) $(LIBOBJ) ; \
+ $(RANLIB) $(DEV_LIB) ; \
+ fi
+
+$(SHR_LIB): $(CMDMOD:.c=.o) @LANPLUS_LIB@
+ mkdir -p $(tmpobj)
+ if [ "x@LANPLUS_SAM@" = "xyes" ]; then \
+ $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilanplus.o -c ipmilanplus.c; \
+ $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilan.o -c ipmilan.c; \
+ ar x @LANPLUS_LIB@ ; \
+ $(CC) $(LDFLAGS) -shared -o $(SHR_LIB) $(LIBOBJ) $(LANPLUS_OBJ); \
+ else \
+ $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilanplus.o -c ipmilanplus.c; \
+ $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilan.o -c ipmilan.c; \
+ $(CC) $(LDFLAGS) -shared -o $(SHR_LIB) $(LIBOBJ) ; \
+ fi
+
+# To build ipmiutil, need to use METACFLAGS for each .c/.o
+
+idiscover$(EXEEXT): idiscover.c
+ $(CC) $(CFLAGS_SAM) $(LDFLAGS) $(OS_LF) -o idiscover idiscover.c
+
+ipmimv: 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
+
+ipmi_sample: $(DEV_LIB) ipmi_sample.c isensor.c ievents.c
+ $(CC) $(CFLAGS_SAM) -c ipmi_sample.c
+ $(CC) -g -O2 -o ipmi_sample ipmi_sample.o $(DEV_LIB) $(LDFLAGS) $(LDSAM)
+
+ialarms_enc: $(DEV_LIB) ialarms.c oem_intel.c
+ $(CC) $(CFLAGS_SAM) -DTEST_ENC -o ialarms2.o -c ialarms.c
+ $(CC) $(CFLAGS_SAM) -DNO_EVENTS -o oem_intel2.o -c oem_intel.c
+ $(CC) -g -O2 -o ialarms_enc ialarms2.o oem_intel2.o $(DEV_LIB) $(LDFLAGS) $(LDSAM)
+
+ifru_picmg2.o: ifru_picmg.c
+ $(CC) $(CFLAGS_SAM) -o ifru_picmg2.o -c ifru_picmg.c
+
+# 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: $(DEV_LIB) ipmi_sample.c isensor.c ievents.c ifru.c isel.c ifru_picmg2.o
+ $(CC) $(CFLAGS_SAM) -D GET_SENSORS -D GET_FRU -o ipmi_sample2.o -c ipmi_sample.c
+ $(CC) $(CFLAGS_SAM) -o isensor2.o -c isensor.c
+ $(CC) $(CFLAGS_SAM) -o ievents2.o -c ievents.c
+ $(CC) $(CFLAGS_SAM) -o ifru2.o -c ifru.c
+ $(CC) $(CFLAGS_SAM) -o isel2.o -c isel.c
+ $(CC) -g -O2 -o ipmi_sample2 ipmi_sample2.o isensor2.o ievents2.o ifru2.o ifru_picmg2.o isel2.o $(DEV_LIB) $(LDFLAGS) $(LDSAM)
+
+ipmi_sample_evt: $(DEV_LIB) ipmi_sample_evt.c isensor.c ievents.c
+ $(CC) $(CFLAGS_SAM) -o ipmi_sample_evt.o -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 $(DEV_LIB) $(LDFLAGS) $(LDSAM)
+
+ifruset: $(DEV_LIB) ifruset.c ifru_picmg2.o
+ $(CC) $(CFLAGS_SAM) -c ifruset.c
+ $(CC) -g -O2 -o ifruset ifruset.o ifru_picmg2.o $(DEV_LIB) $(LDFLAGS) $(LDADD)
+
+iseltime: $(DEV_LIB) iseltime.c
+ $(CC) $(CFLAGS_SAM) -c iseltime.c
+ $(CC) -g -O2 -o iseltime iseltime.o $(DEV_LIB) $(LDFLAGS) $(LDADD)
+
+ipmi_port$(EXEEXT): ipmi_port.c
+ $(CC) $(CFLAGS_SAM) $(LDFLAGS) -o ipmi_port ipmi_port.c
+
+iconfig: iconfig.c $(DEV_LIB)
+ $(CC) $(CFLAGS_SAM) $(LDFLAGS) -o iconfig iconfig.c $(DEV_LIB) @LANPLUS_CRYPTO@
+
+# @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)
+ if [ "x$(SHRLINK)" != "x" ]; then \
+ @INS_LIB@ cp -f $(SHR_LIB) $(DESTDIR)$(LIBDIR) ; \
+ 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
diff --git a/util/Makefile.am-so b/util/Makefile.am-so
new file mode 100644
index 0000000..97d9c34
--- /dev/null
+++ b/util/Makefile.am-so
@@ -0,0 +1,241 @@
+
+localedir = $(datadir)/locale
+INCLUDES = -I. -I..
+OS_CF = @OS_CFLAGS@ @CROSS_CFLAGS@
+OS_LF = @OS_LFLAGS@ @CROSS_LFLAGS@
+AM_CPPFLAGS = $(OS_CF) -DLOCALEDIR=\"$(localedir)\"
+AM_CPPFLAGS += @IA64_CFLAGS@ @GPL_CFLAGS@
+LDADD = $(OS_LF)
+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@
+
+CMDSRC = ipmicmd.c mem_if.c ipmidir.c imbapi.c ipmimv.c ipmild.c ipmibmc.c ipmilipmi.c subs.c
+CMDSRC += md5.c md2.c ipmilan.c
+CMDSRC += ipmilanplus.c
+# CMDSRC = ipmicmd.c mem_if.c @OS_DRIVERS@
+# am: configure substitutions are not allowed in _SOURCES variables
+CMDOBJ = $(tmpobj)/ipmicmd.o $(tmpobj)/mem_if.o $(tmpobj)/ipmidir.o $(tmpobj)/imbapi.o $(tmpobj)/ipmimv.o $(tmpobj)/ipmild.o $(tmpobj)/ipmibmc.o $(tmpobj)/ipmilipmi.o $(tmpobj)/subs.o $(tmpobj)/md5.o $(tmpobj)/md2.o $(tmpobj)/ipmilan.o $(tmpobj)/ipmilanplus.o
+LIBOBJ = $(CMDOBJ)
+OEMMOD = oem_kontron.c oem_fujitsu.c oem_intel.c oem_sun.c iekanalyzer.c oem_supermicro.c oem_dell.c oem_quanta.c oem_hp.c oem_newisys.c
+
+
+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 $(OEMMOD)
+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+) required by SOL:
+# If ./configure --disable-lanplus
+# AM_CPPFLAGS +=
+# LDADD +=
+# LANPLUS_SRC =
+# 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)
+# LANPLUS_SRC = $(LANPLUS_DIR)/lanplus.c ...
+AM_CPPFLAGS += @LANPLUS_CFLAGS@ -I../lib/lanplus -I../lib/lanplus/inc
+LDADD += @LANPLUS_LIB@ @LANPLUS_CRYPTO@
+LANPLUS_OBJ = $(shell ar t @LANPLUS_LIB@ 2>/dev/null)
+LANPLUS_DIR = ../lib/lanplus
+LANPLUS_SRC = $(LANPLUS_DIR)/lanplus.c $(LANPLUS_DIR)/lanplus_dump.c \
+ $(LANPLUS_DIR)/lanplus_strings.c $(LANPLUS_DIR)/lanplus_crypt.c \
+ $(LANPLUS_DIR)/lanplus_crypt_impl.c $(LANPLUS_DIR)/helper.c \
+ $(LANPLUS_DIR)/ipmi_strings.c
+
+# 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
+DEV_LIB = libipmiutil.a
+EXTRA_PROGRAMS = ipmi_sample ipmi_sample_evt
+TESTPROGS = libimbapi.a iconfig ipmimv ifruset ipmi_sample2 ialarms_enc iseltime
+# 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
+
+lib_LTLIBRARIES = libipmiutil.la
+libipmiutil_la_SOURCES = $(CMDSRC) $(LANPLUS_SRC)
+libipmiutil_la_LDFLAGS = -export-dynamic
+
+# 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
+
+# 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): $(CMDOBJ) @LANPLUS_LIB@
+ mkdir -p $(tmpobj)
+ if [ "x@LANPLUS_SAM@" = "xyes" ]; then \
+ $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilanplus.o -c ipmilanplus.c; \
+ $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilan.o -c ipmilan.c; \
+ ar x @LANPLUS_LIB@ ; \
+ $(AR) cru $(DEV_LIB) $(LIBOBJ) $(LANPLUS_OBJ); \
+ $(RANLIB) $(DEV_LIB); \
+ else \
+ $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilanplus.o -c ipmilanplus.c; \
+ $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilan.o -c ipmilan.c; \
+ $(AR) cru $(DEV_LIB) $(LIBOBJ) ; \
+ $(RANLIB) $(DEV_LIB) ; \
+ fi
+ rm -f $(tmpobj)/ipmilan.o $(tmpobj)/ipmilanplus.o
+
+# To build ipmiutil, need to use METACFLAGS for each .c/.o
+
+idiscover: idiscover.c
+ $(CC) $(OS_CF) $(CFLAGS) $(LDFLAGS) $(OS_LF) -o idiscover idiscover.c
+
+ipmimv: ipmimv.c
+ $(CC) $(OS_CF) $(CFLAGS) $(LDFLAGS) -DTEST_BIN -o ipmimv ipmimv.c
+
+ievents: ievents.c
+ $(CC) $(OS_CF)$(CFLAGS) $(LDFLAGS) -DALONE -o ievents ievents.c
+
+ipmi_sample: $(DEV_LIB) ipmi_sample.c isensor.c ievents.c
+ $(CC) $(CFLAGS_SAM) -c ipmi_sample.c
+ $(CC) -g -O2 -o ipmi_sample ipmi_sample.o $(DEV_LIB) $(LDFLAGS) $(LDSAM)
+
+ialarms_enc: $(DEV_LIB) ialarms.c oem_intel.c
+ $(CC) $(CFLAGS_SAM) -DTEST_ENC -o ialarms2.o -c ialarms.c
+ $(CC) $(CFLAGS_SAM) -DNO_EVENTS -o oem_intel2.o -c oem_intel.c
+ $(CC) -g -O2 -o ialarms_enc ialarms2.o oem_intel2.o $(DEV_LIB) $(LDFLAGS) $(LDSAM)
+
+ifru_picmg2.o: ifru_picmg.c
+ $(CC) $(CFLAGS_SAM) -o ifru_picmg2.o -c ifru_picmg.c
+
+# 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: $(DEV_LIB) ipmi_sample.c isensor.c ievents.c ifru.c isel.c ifru_picmg2.o
+ $(CC) $(CFLAGS_SAM) -D GET_SENSORS -D GET_FRU -o ipmi_sample2.o -c ipmi_sample.c
+ $(CC) $(CFLAGS_SAM) -o isensor2.o -c isensor.c
+ $(CC) $(CFLAGS_SAM) -o ievents2.o -c ievents.c
+ $(CC) $(CFLAGS_SAM) -o ifru2.o -c ifru.c
+ $(CC) $(CFLAGS_SAM) -o isel2.o -c isel.c
+ $(CC) -g -O2 -o ipmi_sample2 ipmi_sample2.o isensor2.o ievents2.o ifru2.o ifru_picmg2.o isel2.o $(DEV_LIB) $(LDFLAGS) $(LDSAM)
+
+ipmi_sample_evt: $(DEV_LIB) ipmi_sample_evt.c isensor.c ievents.c
+ $(CC) $(CFLAGS_SAM) -o ipmi_sample_evt.o -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 $(DEV_LIB) $(LDFLAGS) $(LDSAM)
+
+ifruset: $(DEV_LIB) ifruset.c ifru_picmg2.o
+ $(CC) $(CFLAGS_SAM) -c ifruset.c
+ $(CC) -g -O2 -o ifruset ifruset.o ifru_picmg2.o $(DEV_LIB) $(LDFLAGS) $(LDADD)
+
+iseltime: $(DEV_LIB) iseltime.c
+ $(CC) $(CFLAGS_SAM) -c iseltime.c
+ $(CC) -g -O2 -o iseltime iseltime.o $(DEV_LIB) $(LDFLAGS) $(LDADD)
+
+ipmi_port: ipmi_port.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o ipmi_port ipmi_port.c
+
+#xmlconfig: xmlconfig.c $(DEV_LIB)
+# $(CC) $(CFLAGS) $(LDFLAGS) -o xmlconfig xmlconfig.c libipmiutil.a @LANPLUS_CRYPTO@
+
+iconfig: iconfig.c $(DEV_LIB)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o iconfig iconfig.c $(DEV_LIB) @LANPLUS_CRYPTO@
+
+# @LANPLUS_LIB@ is ../lib/libipmi_lanplus.a
+../lib/libipmi_lanplus.a:
+ cd ../lib; make
+
+ipmiutil_SOURCES = $(METASOURCE)
+
+ipmiutil: $(METASOURCE:.c=.o) $(CMDOBJ) @LANPLUS_LIB@
+ $(CC) $(CFLAGS) $(LDFLAGS) -o ipmiutil $(METASOURCE:.c=.o) $(CMDOBJ) $(LDADD)
+
+$(tmpobj)/ipmicmd.o: ipmicmd.c
+ mkdir -p $(tmpobj)
+ @$(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmicmd.o -c ipmicmd.c
+
+$(tmpobj)/subs.o: subs.c
+ @$(CC) $(CFLAGS_SAMX) -o $(tmpobj)/subs.o -c subs.c
+
+$(tmpobj)/mem_if.o: mem_if.c
+ @$(CC) $(CFLAGS_SAMX) -o $(tmpobj)/mem_if.o -c mem_if.c
+
+$(tmpobj)/ipmidir.o: ipmidir.c
+ @$(CC) $(CFLAGS_SAMX) -o $@ -c ipmidir.c
+
+$(tmpobj)/imbapi.o: imbapi.c
+ @$(CC) $(CFLAGS_SAMX) -o $@ -c imbapi.c
+
+$(tmpobj)/ipmimv.o: ipmimv.c
+ @$(CC) $(CFLAGS_SAMX) -o $@ -c ipmimv.c
+
+$(tmpobj)/ipmild.o: ipmild.c
+ @$(CC) $(CFLAGS_SAMX) -o $@ -c ipmild.c
+
+$(tmpobj)/ipmibmc.o: ipmibmc.c
+ @$(CC) $(CFLAGS_SAMX) -o $@ -c ipmibmc.c
+
+$(tmpobj)/ipmilipmi.o: ipmilipmi.c
+ @$(CC) $(CFLAGS_SAMX) -o $@ -c ipmilipmi.c
+
+$(tmpobj)/ipmilan.o: ipmilan.c
+ @$(CC) $(CFLAGS_SAMX) -o $@ -c ipmilan.c
+
+$(tmpobj)/ipmilanplus.o: ipmilanplus.c
+ @$(CC) $(CFLAGS_SAMX) -o $@ -c ipmilanplus.c
+
+$(tmpobj)/md5.o: md5.c
+ @$(CC) $(CFLAGS_SAMX) -o $@ -c md5.c
+
+$(tmpobj)/md2.o: md2.c
+ @$(CC) $(CFLAGS_SAMX) -o $@ -c md2.c
+
+#%.o: %.c
+# $(CC) -c $(OS_CF) $(CFLAGS) $(AM_CPPFLAGS) -o $@ $<
+
+ievents_SOURCES = ievents.c
+
+idiscover_SOURCES = idiscover.c
+
+ipmi_port_SOURCES = ipmi_port.c
+
+# xmlconfig_SOURCES = xmlconfig.c $(CMDSRC)
+
+EXTRA_DIST = imb_api.h ipmicmd.h ipmidir.h ipmilan.h ipmilanplus.h AnsiTerm.h iekanalyzer.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
+
+all-am: Makefile $(DEV_LIB) $(bin_PROGRAMS) $(sbin_PROGRAMS) $(EXTRA_PROGRAMS)
+
+install-data-am: $(EXTRA_PROGRAMS) $(DEV_LIB)
+ @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)
+
+clean-generic:
+ rm -f $(DEV_LIB) $(EXTRA_PROGRAMS) $(OLDPROGS) $(TESTPROGS)
+ 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 *.so *.la
diff --git a/util/Makefile.in b/util/Makefile.in
new file mode 100644
index 0000000..a8eb9b9
--- /dev/null
+++ b/util/Makefile.in
@@ -0,0 +1,766 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 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@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+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 =
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+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) 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) $(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. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --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@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+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@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GPL_CFLAGS = @GPL_CFLAGS@
+IA64_CFLAGS = @IA64_CFLAGS@
+INIT_DIR = @INIT_DIR@
+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@
+LDFLAGS = @LDFLAGS@
+LD_SAMX = @LD_SAMX@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_DIR = @LIB_DIR@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+OS_CFLAGS = @OS_CFLAGS@
+OS_DRIVERS = @OS_DRIVERS@
+OS_LFLAGS = @OS_LFLAGS@
+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@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHR_LINK = @SHR_LINK@
+STRIP = @STRIP@
+SUBDIR_S = @SUBDIR_S@
+SYSTEMD_DIR = @SYSTEMD_DIR@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+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@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+localedir = $(datadir)/locale
+INCLUDES = -I..
+OS_CF = @OS_CFLAGS@ @CROSS_CFLAGS@
+OS_LF = @OS_LFLAGS@ @CROSS_LFLAGS@
+
+# 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)\" @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)
+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
+LIBOBJ = ipmicmd.o mem_if.o ipmidir.o imbapi.o ipmimv.o ipmild.o ipmibmc.o ipmilipmi.o subs.o md5.o md2.o $(tmpobj)/ipmilan.o $(tmpobj)/ipmilanplus.o
+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 iekanalyzer.c
+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 $(OEMMOD) $(CMDMOD)
+LANPLUS_OBJ = $(shell ar t @LANPLUS_LIB@ 2>/dev/null)
+DEV_LIB = libipmiutil.a
+SHR_LIB = libipmiutil.so
+SHRLINK = @SHR_LINK@
+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 \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign util/Makefile'; \
+ 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
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ || test -f $$p1 \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(sbindir)" || $(mkdir_p) "$(DESTDIR)$(sbindir)"
+ @list='$(sbin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ || test -f $$p1 \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sbin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(sbindir)/$$f"; \
+ done
+
+clean-sbinPROGRAMS:
+ @list='$(sbin_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+
+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)/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_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_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@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@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@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@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@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@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
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+
+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; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ 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; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ 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; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && 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)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$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)
+
+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-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-exec-am: install-binPROGRAMS install-sbinPROGRAMS
+
+install-info: install-info-am
+
+install-man:
+
+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-info-am \
+ uninstall-sbinPROGRAMS
+
+.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-exec install-exec-am install-info \
+ install-info-am install-man 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-info-am 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
+
+# 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@
+ mkdir -p $(tmpobj)
+ if [ "x@LANPLUS_SAM@" = "xyes" ]; then \
+ $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilanplus.o -c ipmilanplus.c; \
+ $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilan.o -c ipmilan.c; \
+ ar x @LANPLUS_LIB@ ; \
+ $(AR) cru $(DEV_LIB) $(LIBOBJ) $(LANPLUS_OBJ); \
+ $(RANLIB) $(DEV_LIB); \
+ else \
+ $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilanplus.o -c ipmilanplus.c; \
+ $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilan.o -c ipmilan.c; \
+ $(AR) cru $(DEV_LIB) $(LIBOBJ) ; \
+ $(RANLIB) $(DEV_LIB) ; \
+ fi
+
+$(SHR_LIB): $(CMDMOD:.c=.o) @LANPLUS_LIB@
+ mkdir -p $(tmpobj)
+ if [ "x@LANPLUS_SAM@" = "xyes" ]; then \
+ $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilanplus.o -c ipmilanplus.c; \
+ $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilan.o -c ipmilan.c; \
+ ar x @LANPLUS_LIB@ ; \
+ $(CC) $(LDFLAGS) -shared -o $(SHR_LIB) $(LIBOBJ) $(LANPLUS_OBJ); \
+ else \
+ $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilanplus.o -c ipmilanplus.c; \
+ $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilan.o -c ipmilan.c; \
+ $(CC) $(LDFLAGS) -shared -o $(SHR_LIB) $(LIBOBJ) ; \
+ fi
+
+# To build ipmiutil, need to use METACFLAGS for each .c/.o
+
+idiscover$(EXEEXT): idiscover.c
+ $(CC) $(CFLAGS_SAM) $(LDFLAGS) $(OS_LF) -o idiscover idiscover.c
+
+ipmimv: 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
+
+ipmi_sample: $(DEV_LIB) ipmi_sample.c isensor.c ievents.c
+ $(CC) $(CFLAGS_SAM) -c ipmi_sample.c
+ $(CC) -g -O2 -o ipmi_sample ipmi_sample.o $(DEV_LIB) $(LDFLAGS) $(LDSAM)
+
+ialarms_enc: $(DEV_LIB) ialarms.c oem_intel.c
+ $(CC) $(CFLAGS_SAM) -DTEST_ENC -o ialarms2.o -c ialarms.c
+ $(CC) $(CFLAGS_SAM) -DNO_EVENTS -o oem_intel2.o -c oem_intel.c
+ $(CC) -g -O2 -o ialarms_enc ialarms2.o oem_intel2.o $(DEV_LIB) $(LDFLAGS) $(LDSAM)
+
+ifru_picmg2.o: ifru_picmg.c
+ $(CC) $(CFLAGS_SAM) -o ifru_picmg2.o -c ifru_picmg.c
+
+# 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: $(DEV_LIB) ipmi_sample.c isensor.c ievents.c ifru.c isel.c ifru_picmg2.o
+ $(CC) $(CFLAGS_SAM) -D GET_SENSORS -D GET_FRU -o ipmi_sample2.o -c ipmi_sample.c
+ $(CC) $(CFLAGS_SAM) -o isensor2.o -c isensor.c
+ $(CC) $(CFLAGS_SAM) -o ievents2.o -c ievents.c
+ $(CC) $(CFLAGS_SAM) -o ifru2.o -c ifru.c
+ $(CC) $(CFLAGS_SAM) -o isel2.o -c isel.c
+ $(CC) -g -O2 -o ipmi_sample2 ipmi_sample2.o isensor2.o ievents2.o ifru2.o ifru_picmg2.o isel2.o $(DEV_LIB) $(LDFLAGS) $(LDSAM)
+
+ipmi_sample_evt: $(DEV_LIB) ipmi_sample_evt.c isensor.c ievents.c
+ $(CC) $(CFLAGS_SAM) -o ipmi_sample_evt.o -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 $(DEV_LIB) $(LDFLAGS) $(LDSAM)
+
+ifruset: $(DEV_LIB) ifruset.c ifru_picmg2.o
+ $(CC) $(CFLAGS_SAM) -c ifruset.c
+ $(CC) -g -O2 -o ifruset ifruset.o ifru_picmg2.o $(DEV_LIB) $(LDFLAGS) $(LDADD)
+
+iseltime: $(DEV_LIB) iseltime.c
+ $(CC) $(CFLAGS_SAM) -c iseltime.c
+ $(CC) -g -O2 -o iseltime iseltime.o $(DEV_LIB) $(LDFLAGS) $(LDADD)
+
+ipmi_port$(EXEEXT): ipmi_port.c
+ $(CC) $(CFLAGS_SAM) $(LDFLAGS) -o ipmi_port ipmi_port.c
+
+iconfig: iconfig.c $(DEV_LIB)
+ $(CC) $(CFLAGS_SAM) $(LDFLAGS) -o iconfig iconfig.c $(DEV_LIB) @LANPLUS_CRYPTO@
+
+# @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)
+ if [ "x$(SHRLINK)" != "x" ]; then \
+ @INS_LIB@ cp -f $(SHR_LIB) $(DESTDIR)$(LIBDIR) ; \
+ 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:
diff --git a/util/Makefile.sample b/util/Makefile.sample
new file mode 100644
index 0000000..2976dd5
--- /dev/null
+++ b/util/Makefile.sample
@@ -0,0 +1,28 @@
+# 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
+
diff --git a/util/ialarms.c b/util/ialarms.c
new file mode 100644
index 0000000..dbbdf0c
--- /dev/null
+++ b/util/ialarms.c
@@ -0,0 +1,689 @@
+/*
+ * 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 <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
+#include "ipmicmd.h"
+#include "oem_intel.h"
+
+/*
+ * Global variables
+ */
+static char * progver = "2.93";
+static char * progname = "ialarms";
+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 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();
+ 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;
+ /* 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) { /* 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 */
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 */
diff --git a/util/iconfig.c b/util/iconfig.c
new file mode 100644
index 0000000..0bb54e9
--- /dev/null
+++ b/util/iconfig.c
@@ -0,0 +1,2680 @@
+/*---------------------------------------------------------------------------
+ * 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 <winsock2.h>
+#include <iphlpapi.h>
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "getopt.h"
+#elif defined(DOS)
+#include <dos.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.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
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <errno.h>
+#endif
+#ifdef SOLARIS
+#include <sys/sockio.h>
+#define SIOCGIFHWADDR SIOCGENADDR
+#define ifr_netmask ifr_ifru.ifru_addr
+#elif defined(BSD)
+#include <sys/sockio.h>
+#define SIOCGIFHWADDR SIOCGIFMAC
+#define ifr_netmask ifr_ifru.ifru_addr
+#elif defined(MACOS)
+#include <sys/sockio.h>
+// #define SIOCGIFHWADDR SIOCGIFMAC
+#define ifr_netmask ifr_ifru.ifru_addr
+#endif
+#include "ipmicmd.h"
+#include "oem_intel.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
+ */
+static char * progver = "2.93";
+static char * progname = "iconfig";
+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 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)
+{
+ 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);
+ 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); 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 <file> -s <file>]\n",
+ progname);
+ printf("where -l Lists BMC configuration parameters\n");
+ printf(" -r Restores BMC configuration from <file>\n");
+ printf(" -s Saves BMC configuration to <file>\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 <psw> specify a user password to set\n");
+ printf(" -L 3 specify lan channel number 3\n");
+ print_lan_opt_usage();
+ 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;
+ 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<rlen; i++) if (LanRecord[i] == 0) break;
+ if (i < rlen) rlen = i;
+ sz = rlen;
+ fignore_err = 1;
+ break;
+ case LAN_FAILOVER: /* Intel LAN Failover */
+ if (is_romley(vend_id,prod_id))
+ ret = lan_failover_intel(0xFF,&LanRecord[0]);
+ else continue; /*skip if not Intel Romley */
+ sz = 1;
+ fignore_err = 1;
+ break;
+ default: /*do nothing*/
+ sz = 0;
+ ret = LAN_ERR_NOTSUPPORT;
+ break;
+ } /*end switch*/
+ if (ret == 0) {
+ fprintf(fd_bmc,"SystemParam %d,%d%c ",j,bset,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,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<sz; n++)
+ {
+ pc = strchr(pk,',');
+ if (pc != NULL) {
+ *pc = 0;
+ bParams[n] = atob(pk);
+ pk = (char *)++pc;
+ } else {
+ bParams[n] = atob(pk);
+ break;
+ }
+ }
+ /* n == number of params, usually 3 */
+ chan = bParams[0];
+ idx = bParams[1];
+ bset = bParams[2];
+ /* get data from value */
+ pc = value;
+ sz = strlen_(value);
+ for (j=0,i=0; i<sz; i+=3)
+ LanRecord[j++] = htoi(&pc[i]);
+ if (fdebug) {
+ printf("Record(%d,%d,%d):",chan,idx,bset);
+ for (i=0; i<j; i++) printf(" %02x",LanRecord[i]);
+ printf("\n");
+ }
+
+ if (strncasecmp(key,"LanParam",8) == 0) {
+ if (idx == 0) continue; /*skip Set in progress*/
+ if (idx == 1 || idx == 17) continue; /*read-only params*/
+ if (idx == 5 && fIPMI20) /*BMC MAC address & IPMI 2.0(not shared)*/
+ if (fdomac == 0) continue; /*skip BMC MAC unless -m */
+ if ((idx == 10) && (chan == gcm_ch)) continue; /*skip Lan3 arp*/
+ if ((vend_id == VENDOR_PEPPERCON) && (idx == 7)) continue;
+ if ((idx == 18 || idx == 19) && (ndest == 0)) continue;
+ if (idx >= 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<j; i++)
+ pc[i+1] = LanRecord[i];
+ rlen = sizeof(rData);
+ ret = ipmi_cmd(SET_PEF_CONFIG, pc,j+1, rData,&rlen, &cc,fdebug);
+ if ((ret == 0) && (cc != 0)) ret = cc;
+ if ((idx == 9) && (bset > 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,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 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 */
diff --git a/util/idcmi.c b/util/idcmi.c
new file mode 100644
index 0000000..1e53ae8
--- /dev/null
+++ b/util/idcmi.c
@@ -0,0 +1,976 @@
+/*
+ * 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 <windows.h>
+#include <stdlib.h>
+#include "getopt.h"
+#else
+#include <sys/types.h>
+#if defined(HPUX)
+/* getopt is defined in stdio.h */
+#elif defined(MACOS)
+/* getopt is defined in unistd.h */
+#include <unistd.h>
+#include <sys/time.h>
+#else
+#include <stdlib.h>
+#include <getopt.h>
+#endif
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+
+#include "ipmicmd.h"
+#include "isensor.h"
+#include "idcmi.h"
+
+static char * progname = "idcmi";
+static char * progver = "2.93";
+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] <function>\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();
+ printf("where <function> 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 <power> Set Power limit\n");
+ printf(" power set_action <action> Set Power limit exception action\n");
+ printf(" (action = no_action | power_off | log_sel)\n");
+ printf(" power set_correction <ms> Set Power limit correction time (in ms)\n");
+ printf(" power set_sample <sec> 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: %d 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 += (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: %d 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 ((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 ((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: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 '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 */
diff --git a/util/idcmi.h b/util/idcmi.h
new file mode 100644
index 0000000..a528831
--- /dev/null
+++ b/util/idcmi.h
@@ -0,0 +1,69 @@
+/*
+ * 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 */
diff --git a/util/idiscover.c b/util/idiscover.c
new file mode 100644
index 0000000..57471e3
--- /dev/null
+++ b/util/idiscover.c
@@ -0,0 +1,1055 @@
+/*
+ * 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
+ */
+/*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 <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <winsock.h>
+#include <io.h>
+#include <time.h>
+#include "getopt.h"
+#define NO_THREADS 1
+typedef unsigned int socklen_t;
+WSADATA lan_ws; /*global for WSA*/
+
+#elif defined(DOS)
+#include <dos.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+#define NO_THREADS 1
+
+#else
+/* Linux, BSD, Solaris */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#if defined(HPUX)
+/* getopt is defined in stdio.h */
+#elif defined(MACOS)
+/* getopt is defined in unistd.h */
+#include <unistd.h>
+#include <sys/sockio.h>
+#ifndef HAVE_CONFIG_H
+typedef unsigned int socklen_t;
+#endif
+#else
+#include <getopt.h>
+#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 <sys/sockio.h>
+#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 MACOS
+#define RAW_DOMAIN AF_INET
+#define RAW_PROTO IPPROTO_RAW
+static char frawok = 0; /*raw not working in FreeBSD*/
+#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 <string.h>
+#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.9";
+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 <ip> beginning IP address (x.x.x.x), required\n");
+ printf(" -e <ip> 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)
+int find_ifname(char *ifname)
+{ return(-1); }
+#else
+#include <ifaddrs.h>
+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;
+ }
+ }
+ 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 (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 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 (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<g_repeat; j++)
+ {
+ /* send ping buffer */
+ _seq = 0;
+ rv = send_probe(&_destaddr,_seq);
+ g_npings++;
+ if (fdebug) printerr("sendto[%d,%d] %s rv = %d\n",
+ g_npings,_seq,_dest_ip,rv);
+ if (rv < 0) { /*try to send again*/
+ rv = send_probe(&_destaddr,++_seq);
+ if (rv < 0) {
+ printerr("sendto[%d,%d] %s error %s\n",
+ g_npings,_seq,_dest_ip,showlasterr());
+ continue;
+ }
+ }
+
+#ifdef NO_THREADS
+ receiveThread(NULL);
+ if (g_recv_status == 0 && !fBroadcastOk) {
+ /* nothing returned, try again */
+ if (fping) {
+ rv = send_poke1(&_destaddr);
+ if (fdebug) printerr("sendto[%d,%d] %s poke rv = %d\n",
+ g_npings,_seq,_dest_ip,rv);
+ }
+ rv = send_probe(&_destaddr,++_seq);
+ if (fdebug) printerr("sendto[%d,%d] %s rv = %d\n",
+ g_npings,_seq,_dest_ip,rv);
+ if (rv >= 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 */
diff --git a/util/iekanalyzer.c b/util/iekanalyzer.c
new file mode 100644
index 0000000..ddeeba8
--- /dev/null
+++ b/util/iekanalyzer.c
@@ -0,0 +1,4131 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#ifdef WIN32
+#include <windows.h>
+#include "getopt.h"
+#else
+#include <sys/types.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 "ipmicmd.h"
+#include "iekanalyzer.h"
+
+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] <oc=filename1> <b1=filename2>... \r\n\
+ frushow <b2=filename> \r\n\
+ summary [match | unmatch | all] <oc=filename1> <b1=filename2>... \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 <xx=frufile> ...");
+ }
+ }
+ }
+ 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> <xx=frufile> [xx=frufile]"
+ );
+ }
+ else{
+ lprintf(LOG_ERR, " ekanalyzer summary [match/ unmatch/ all]"
+ " <xx=frufile> <xx=frufile> [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> <xx=frufile> [xx=frufile]"
+ );
+ }
+ else{
+ lprintf (LOG_ERR, " ekanalyzer summary [match/ unmatch/ all]"
+ " <xx=frufile> <xx=frufile> [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; index<car.module_activation_record_count; index++){
+ memcpy( &cur_desc[index],
+ &list_record[num_file]->data[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> <xx=frufile> [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; list<argc; list++ ){
+ list_head[list] = NULL;
+ list_record[list] = NULL;
+ list_last[list] = NULL;
+ }
+ list=0;
+
+ for ( num_file=0; num_file < argc; num_file++ ){
+ if (file_type[num_file] != CONFIG_FILE){
+ return_value = ipmi_ekanalyzer_fru_file2structure(
+ filename[num_file], &list_head[num_file],
+ &list_record[num_file], &list_last[num_file]);
+ }
+ }
+ /*Get Carrier p2p connectivity record for physical check*/
+ for (num_file=0; num_file < argc; num_file++){
+ if (file_type[num_file] == ON_CARRIER_FRU_FILE ){
+ for ( pcarrier_p2p=list_head[num_file];
+ pcarrier_p2p != NULL ;
+ pcarrier_p2p = pcarrier_p2p->next
+ ){
+ 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_file<argc; num_file++ ){
+ if ( ( file_type[match_pair] != CONFIG_FILE )
+ && ( file_type[num_file] != CONFIG_FILE )
+ ){
+ if ( ( file_type[match_pair] != ON_CARRIER_FRU_FILE )
+ || ( file_type[num_file] != ON_CARRIER_FRU_FILE )
+ ){
+ printf("%s vs %s\n",
+ val2str((uint16_t)file_type[match_pair],
+ ipmi_ekanalyzer_module_type),
+ val2str((uint16_t)file_type[num_file],
+ ipmi_ekanalyzer_module_type));
+ /*Ekeying match between 2 files*/
+ if (verbose>0){
+ 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<record1.guid_count; i++){
+ for( j=0; j < record2.guid_count; j++){
+ if( memcmp (&record1.oem_guid[i], &record2.oem_guid[j],
+ SIZE_OF_GUID )
+ == 0
+ ){
+ result = OK_STATUS;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else{
+ result = OK_STATUS;
+ }
+ if (result == OK_STATUS){
+ if (record1.link_desc[index1].type_ext
+ == record2.link_desc[index2].type_ext
+ ){
+ unsigned char asym[COMPARE_CANDIDATE];
+ int offset = 0;
+
+ asym[offset++] = record1.link_desc[index1].asym_match;
+ asym[offset] = record2.link_desc[index2].asym_match;
+ result = ipmi_ek_compare_asym ( asym );
+ if (result == OK_STATUS){
+ struct fru_picmgext_amc_link_desc_record link[COMPARE_CANDIDATE];
+ int index = 0;
+
+ link[index++] = record1.link_desc[index1];
+ link[index] = record2.link_desc[index2];
+ result = ipmi_ek_compare_number_of_enable_port( link );
+ }
+ else{
+ result = ERROR_STATUS;
+ }
+ }
+ else{
+ result = ERROR_STATUS;
+ }
+ }
+ }
+ else{
+ result = ERROR_STATUS;
+ }
+
+ return result;
+}
+
+/**************************************************************************
+*
+* Function name: ipmi_ek_compare_asym
+*
+* Description: This function compares 2 asymetric match of 2
+* amc link descriptors
+*
+* Restriction: None
+*
+* Input: asym[COMPARE_CANDIDATE]: Contain 2 asymetric match for comparison
+*
+* Output: None
+*
+* Global: None
+*
+* Return: return 0 if both asym. match are matched, otherwise return -1
+*
+***************************************************************************/
+
+static int
+ipmi_ek_compare_asym( unsigned char asym[COMPARE_CANDIDATE] )
+{
+ int return_value = ERROR_STATUS;
+ int first_index = 0;
+ int second_index = 1;
+
+ if ( (asym[first_index] == 0) && (asym[second_index] == 0) ){
+ return_value = OK_STATUS;
+ }
+ else if ( (asym[first_index] & asym[second_index]) == 0 ){
+ return_value = OK_STATUS;
+ }
+ else{
+ return_value = ERROR_STATUS;
+ }
+ return return_value;
+}
+
+/**************************************************************************
+*
+* Function name: ipmi_ek_compare_link_descriptor
+*
+* Description: This function compare number of enble port of Link designator
+*
+* Restriction: None
+*
+* Input: link_designator1: first link designator
+* link_designator2: second link designator
+*
+* Output: None
+*
+* Global: None
+*
+* Return: return 0 if both link are matched, otherwise return -1
+*
+***************************************************************************/
+static int
+ipmi_ek_compare_number_of_enable_port(
+ struct fru_picmgext_amc_link_desc_record link_desc[COMPARE_CANDIDATE] )
+{
+ int amc_port_count = 0;
+ int carrier_port_count = 0;
+ int return_value = ERROR_STATUS;
+ int index = 0;
+
+ if (link_desc[index].port_flag_0){ /*bit 0 indicates port 0*/
+ amc_port_count++;
+ }
+ if (link_desc[index].port_flag_1){ /*bit 1 indicates port 1*/
+ amc_port_count++;
+ }
+ if (link_desc[index].port_flag_2){ /*bit 2 indicates port 2*/
+ amc_port_count++;
+ }
+ if (link_desc[index++].port_flag_3){ /*bit 3 indicates port 3*/
+ amc_port_count++;
+ }
+
+ /*2nd link designator*/
+ if (link_desc[index].port_flag_0){ /*bit 0 indicates port 0*/
+ carrier_port_count++;
+ }
+ if (link_desc[index].port_flag_1){ /*bit 1 indicates port 1*/
+ carrier_port_count++;
+ }
+ if (link_desc[index].port_flag_2){ /*bit 2 indicates port 2*/
+ carrier_port_count++;
+ }
+ if (link_desc[index].port_flag_3){ /*bit 3 indicates port 3*/
+ carrier_port_count++;
+ }
+
+ if(carrier_port_count == amc_port_count){
+
+ return_value = OK_STATUS;
+ }
+ else{
+ return_value = ERROR_STATUS;
+ }
+
+ return return_value;
+}
+
+/**************************************************************************
+*
+* Function name: ipmi_ek_display_link_descriptor
+*
+* Description: Display the link descriptor of an AMC p2p connectivity record
+*
+* Restriction: See AMC.0 or PICMG 3.0 specification for detail about bit masks
+*
+* Input: file_type: module type.
+* rsc_id: resource id
+* char* str: indicates if it is a source (its value= "From") or a
+* destination (its value = "To"). ( it is set to "" if it is not
+* a source nor destination
+* link_desc: AMC link descriptor
+* asym: asymetric match
+*
+* Output: None
+*
+* Global: None
+*
+* Return: None
+*
+***************************************************************************/
+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 )
+{
+ tboolean isOEMtype = FALSE;
+
+ if (file_type == ON_CARRIER_FRU_FILE){
+ printf(" - %s On-Carrier Device ID %d\n", str, (rsc_id & 0x0f) );
+ }
+ else{
+ printf(" - %s %s\n", str,
+ val2str((uint16_t)file_type,ipmi_ekanalyzer_module_type));
+ }
+
+ printf(" - Channel ID %d || ", link_desc.channel_id );
+ printf("%s", link_desc.port_flag_0 ? "Lane 0: enable" : "");
+ printf("%s", link_desc.port_flag_1 ? ", Lane 1: enable" : "");
+ printf("%s", link_desc.port_flag_2 ? ", Lane 2: enable" : "");
+ printf("%s", link_desc.port_flag_3 ? ", Lane 3: enable" : "");
+
+ printf("\n");
+ printf(" - 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(" - Link Type extension: %s\n",
+ val2str (link_desc.type_ext, ipmi_ekanalyzer_extension_PCIE) );
+ printf(" - Link Group ID: %d || ", link_desc.group_id );
+ printf("Link Asym. Match: %s\n",
+ val2str (link_desc.asym_match, ipmi_ekanalyzer_asym_PCIE) );
+ break;
+ case FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET:
+ printf(" - Link Type extension: %s\n",
+ val2str (link_desc.type_ext, ipmi_ekanalyzer_extension_ETHERNET) );
+ printf(" - Link Group ID: %d || ", link_desc.group_id );
+ printf("Link Asym. Match: %s\n",
+ val2str (link_desc.asym_match, ipmi_ekanalyzer_asym_PCIE) );
+ break;
+ case FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE:
+ printf(" - Link Type extension: %s\n",
+ val2str (link_desc.type_ext, ipmi_ekanalyzer_extension_STORAGE) );
+ printf(" - Link Group ID: %d || ", link_desc.group_id );
+ printf("Link Asym. Match: %s\n",
+ val2str (link_desc.asym_match, ipmi_ekanalyzer_asym_STORAGE) );
+ break;
+ default:
+ printf(" - Link Type extension: %i\n", link_desc.type_ext );
+ printf(" - Link Group ID: %d || ", link_desc.group_id );
+ printf("Link Asym. Match: %i\n", link_desc.asym_match);
+ break;
+ }
+ /*return as OEM type if link type indicates OEM*/
+ if ( (link_desc.type >= 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; i<feeds; i++) {
+ unsigned char entries;
+ unsigned long max_ext = 0;
+ unsigned long max_int = 0;
+ max_ext = record->data[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; j<entries; j++) {
+ printf("\tHW: 0x%02x", record->data[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; i<desc_count; i++){
+ unsigned char resource_id;
+ unsigned char channel_count;
+
+ resource_id = record->data[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; j<channel_count; j++){
+ unsigned char loc_channel, rem_channel, rem_resource;
+
+ loc_channel = record->data[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; i<descr_count; i++){
+ unsigned char channel_id, control;
+ unsigned char indirect_cnt, direct_cnt;
+ int j=0;
+
+ channel_id = record->data[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; j<indirect_cnt; j++){
+ unsigned char feature;
+ unsigned char dep_chn_id;
+
+ feature = record->data[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; j<direct_cnt; j++){
+ unsigned char feature, family, accuracy;
+ unsigned long freq, min_freq, max_freq;
+
+ feature = record->data[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: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;
+}
+
+/*end iekanalyzer.c*/
diff --git a/util/iekanalyzer.h b/util/iekanalyzer.h
new file mode 100644
index 0000000..452b935
--- /dev/null
+++ b/util/iekanalyzer.h
@@ -0,0 +1,521 @@
+/*
+ * 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 */
diff --git a/util/ievents.c b/util/ievents.c
new file mode 100644
index 0000000..72c0b24
--- /dev/null
+++ b/util/ievents.c
@@ -0,0 +1,2505 @@
+/*
+ * 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 <stdio.h>
+#ifdef WIN32
+#include <windows.h>
+#include <stdlib.h>
+#include <string.h>
+#elif defined(DOS)
+#include <dos.h>
+#include <stdlib.h>
+#include <string.h>
+#else
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <syslog.h>
+#endif
+#include <time.h>
+
+#include "ipmicmd.h"
+#include "ievents.h"
+
+#define SELprintf printf
+#define SMS_SA 0x41
+#define SMI_SA 0x21
+static char *progver = "2.93";
+static char *progname = "ievents";
+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 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 15
+static struct { /* See Table 36-3, type 0Fh, offset 00h */
+ int code; char *msg;
+ } fwerrs[NFWERRS] = {
+ { 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 27
+static struct { /* See Table 36-3, type 0Fh, offset 01h & 02h */
+ int code; char *msg;
+ } fwstat[NFWSTAT] = {
+ { 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 8
+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" };
+
+#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 OK",
+ /*01*/ "Failed OK",
+ /*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 87
+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"},
+{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, 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 = "SMI Link Lane Fail Over"; break; /*Quanta QSSC_S4R*/
+ 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_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;
+ n = sprintf(desc,"DIMM[%d]",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 strlen_(const char *s) { return((int)strlen(s)); }
+// char * get_iana_str(int vend) { return(""); } *from subs.c*/
+void set_iana(int vend) { return; }
+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 = VENDOR_INTEL; /*assume a default of Intel*/
+ *prod = 0;
+}
+char is_remote(void)
+{ return(1); /* act as if remote with standalone utility */ }
+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
+
+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) 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 (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_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 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;
+
+ 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;
+
+ j = decode_sel_oem(vend,pevt,outbuf,szbuf,fsensdesc,fdebug);
+ if (j == 0) return(0); /*successful, have the description*/
+
+ if (psel->record_type == 0xDC) {
+ /* OEM Record: these are usually Microsoft */
+ char *mfgstr;
+ int mfg;
+ 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 */
+ char *mfgstr;
+ int mfg;
+ 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 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);
+ /* 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 {
+ 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)
+ {
+ 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 Error"; /*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];
+ uchar 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*/
+#ifndef ALONE
+ case 'o': /*specify OEM IANA manufacturer id */
+ if (argc > 1) { /*next argv is IANA number */
+ i = atoi(argv[1]);
+ printf("setting IANA to %d (%s)\n",i,get_iana_str(i));
+ set_iana(i);
+ argc--; argv++;
+ } else {
+ printf("option -%c requires an argument\n",c);
+ rv = ERR_BAD_PARAM;
+ }
+ break;
+#endif
+ 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,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,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 */
diff --git a/util/ievents.h b/util/ievents.h
new file mode 100644
index 0000000..71bc449
--- /dev/null
+++ b/util/ievents.h
@@ -0,0 +1,64 @@
+/*
+ * 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);
+/*
+ * 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*/
diff --git a/util/ifirewall.c b/util/ifirewall.c
new file mode 100644
index 0000000..b92d7d5
--- /dev/null
+++ b/util/ifirewall.c
@@ -0,0 +1,1154 @@
+/*
+ * 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 <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "getopt.h"
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.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 "ipmicmd.h"
+#include "ifirewall.h"
+
+/* global variables */
+static char * progname = "ifirewall";
+static char * progver = "2.93";
+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 (i<n) {
+ printf("%02x", (unsigned char) (invert?~bf[i]:bf[i]));
+ if (++i % 4 == 0)
+ printf(" ");
+ }
+ printf("\n");
+ } else {
+ while (i<n) {
+ lprintf(loglevel, "%02x", (unsigned char) (invert?~bf[i]:bf[i]));
+ if (++i % 4 == 0)
+ lprintf(loglevel, " ");
+ }
+ lprintf(loglevel, "\n");
+ }
+
+}
+
+static int
+ipmi_firewall_parse_args(int argc, char ** argv, struct ipmi_function_params * p)
+{
+ int i;
+
+ if (!p) {
+ lprintf(LOG_ERR, "ipmi_firewall_parse_args: p is NULL");
+ return -1;
+ }
+ for (i=0; i<argc; i++) {
+ if (strncmp(argv[i], "channel", 7) == 0) {
+ if (++i < argc)
+ p->channel = 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; c<sizeof(cmd->subfn_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; l<MAX_LUN; l++) {
+ if (p->lun >= 0 && p->lun != l)
+ continue;
+ bmc->lun[l].support = lun[l];
+ if (lun[l]) {
+ for (n=0; n<MAX_NETFN_PAIR; n++) {
+ int offset = l*MAX_NETFN_PAIR+n;
+ bmc->lun[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; n<MAX_NETFN_PAIR; n++) {
+ p->netfn = 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; n<MAX_NETFN_PAIR; n++) {
+ p->netfn = 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; n<MAX_SUBFN; n++) {
+ printf("sub-function 0x%02x: | %c | %c | %c |\n", n,
+ (!bit_test(cmd->subfn_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; n<MAX_NETFN_PAIR; n++) {
+ p.netfn = n*2;
+ if (bmc_fn_support->lun[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; l<MAX_LUN; l++) {
+ p.lun = l;
+ for (n=0; n<MAX_NETFN; n+=2) {
+ p.netfn = n;
+ for (c=0; c<MAX_COMMAND; c++) {
+ p.command = c;
+ printf("reset lun %d, netfn %d, command %d, subfn\n", l, n, c);
+ memset(enables, 0xff, MAX_SUBFN_BYTES);
+ ret = _set_subfn_enables(intf, &p,
+ &bmc_fn_support->lun[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;
+}
diff --git a/util/ifirewall.h b/util/ifirewall.h
new file mode 100644
index 0000000..14a04f4
--- /dev/null
+++ b/util/ifirewall.h
@@ -0,0 +1,111 @@
+/*
+ * 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_FIREWALL_H
+#define IPMI_FIREWALL_H
+
+#define uint8_t unsigned char
+#define uint16_t unsigned short
+
+// struct ipmi_rq definition was moved to ipmicmd.h
+#define IPMI_NETFN_APP 0x06
+
+#define BMC_GET_NETFN_SUPPORT 0x09
+#define BMC_GET_COMMAND_SUPPORT 0x0A
+#define BMC_GET_COMMAND_SUBFUNCTION_SUPPORT 0x0B
+#define BMC_GET_CONFIGURABLE_COMMANDS 0x0C
+#define BMC_GET_CONFIGURABLE_COMMAND_SUBFUNCTIONS 0x0D
+#define BMC_SET_COMMAND_ENABLES 0x60
+#define BMC_GET_COMMAND_ENABLES 0x61
+#define BMC_SET_COMMAND_SUBFUNCTION_ENABLES 0x62
+#define BMC_GET_COMMAND_SUBFUNCTION_ENABLES 0x63
+#define BMC_OEM_NETFN_IANA_SUPPORT 0x64
+
+#define SET_COMMAND_ENABLE_BYTE (BMC_SET_COMMAND_ENABLES / 8)
+#define SET_COMMAND_ENABLE_BIT (BMC_SET_COMMAND_ENABLES % 8)
+
+#define MAX_LUN 4
+#define MAX_NETFN 64
+#define MAX_NETFN_PAIR (MAX_NETFN/2)
+#define MAX_COMMAND 256
+#define MAX_SUBFN 32
+#define MAX_COMMAND_BYTES (MAX_COMMAND>>3)
+#define MAX_SUBFN_BYTES (MAX_SUBFN>>3)
+
+// support is a bitfield with the following bits set...
+#define BIT_AVAILABLE 0x01
+#define BIT_CONFIGURABLE 0x02
+#define BIT_ENABLED 0x04
+
+struct command_support {
+ unsigned char support;
+ unsigned char version[3];
+ unsigned char subfn_support[MAX_SUBFN_BYTES];
+ unsigned char subfn_config[MAX_SUBFN_BYTES];
+ unsigned char subfn_enable[MAX_SUBFN_BYTES];
+};
+struct lun_netfn_support {
+ unsigned char support;
+ struct command_support command[MAX_COMMAND];
+ unsigned char command_mask[MAX_COMMAND_BYTES];
+ unsigned char config_mask[MAX_COMMAND_BYTES];
+ unsigned char enable_mask[MAX_COMMAND_BYTES];
+};
+struct lun_support {
+ unsigned char support;
+ struct lun_netfn_support netfn[MAX_NETFN_PAIR];
+};
+struct bmc_fn_support {
+ struct lun_support lun[MAX_LUN];
+};
+struct ipmi_function_params {
+ int channel;
+ int lun;
+ int netfn;
+ int command;
+ int subfn;
+ unsigned char force;
+};
+
+#ifdef WIN32
+#define INLINE /*nop*/
+#else
+#define INLINE inline
+#endif
+static INLINE int bit_test(const unsigned char * bf, int n) {
+ return !!(bf[n>>3]&(1<<(n%8)));
+}
+static INLINE void bit_set(unsigned char * bf, int n, int v) {
+ bf[n>>3] = (bf[n>>3] & ~(1<<(n%8))) | ((v?1:0)<<(n%8));
+}
+
+#endif /*IPMI_FIREWALL_H */
diff --git a/util/ifru.c b/util/ifru.c
new file mode 100755
index 0000000..ba834e6
--- /dev/null
+++ b/util/ifru.c
@@ -0,0 +1,2123 @@
+/*
+ * 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 <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+#elif defined(DOS)
+#include <dos.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#if defined(HPUX)
+/* getopt is defined in stdio.h */
+#elif defined(MACOS)
+/* getopt is defined in unistd.h */
+#include <unistd.h>
+#else
+#include <errno.h>
+#endif
+#endif
+#include <time.h>
+
+#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);
+#endif
+
+static char *progname = "ifru";
+static char *progver = "2.93";
+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
+#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[16];
+ 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;
+ 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<len; k++)
+ target[k] = bcd_plus[(s[k] & 0x0f)];
+ target[k] = '\0';
+ } else if (type == STRING_DATA_TYPE_SIX_BIT_ASCII) { /*type 2: 6-bit ASCII*/
+ for (i=j=0; i<slen; i+=3) {
+ u.bits = 0;
+ k = ((slen-i) < 3 ? (slen-i) : 3);
+#if WORDS_BIGENDIAN
+ u.chars[3] = s[i];
+ u.chars[2] = (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, 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, 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; ) {
+ 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++)
+ {
+ 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[25];
+ uchar resp[16];
+ 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;
+ uchar 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;
+ char 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 -NUPREFTVY]\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();
+ 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) || (cc == 0x83)) ; /*do not stop (ARC)*/
+ 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 */
+ fp = fopen(binfile,"w");
+ 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 */
+ fp = fopen(binfile,"r");
+ 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 */
diff --git a/util/ifru.h b/util/ifru.h
new file mode 100644
index 0000000..f3efaf6
--- /dev/null
+++ b/util/ifru.h
@@ -0,0 +1,13 @@
+/*
+ * 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 */
diff --git a/util/ifru_picmg.c b/util/ifru_picmg.c
new file mode 100644
index 0000000..fd6234f
--- /dev/null
+++ b/util/ifru_picmg.c
@@ -0,0 +1,486 @@
+/*
+ * 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 <windows.h>
+#include <stdio.h>
+#include "getopt.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#endif
+#include <time.h>
+
+#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 */
diff --git a/util/ifruset.c b/util/ifruset.c
new file mode 100644
index 0000000..3e0299a
--- /dev/null
+++ b/util/ifruset.c
@@ -0,0 +1,1658 @@
+/*
+ * 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 <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+#elif defined(DOS)
+#include <dos.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.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 <time.h>
+
+#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
+
+static char *progname = "ifruset";
+static char *progver = "2.93";
+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[16];
+ uchar resp[18];
+ int sresp;
+ uchar cc;
+ int sz;
+ char fwords;
+ ushort fruoff = 0;
+ int i;
+ int chunk;
+
+ 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<len; k++)
+ target[k] = bcd_plus[(s[k] & 0x0f)];
+ target[k] = '\0';
+ } else if (type == STRING_DATA_TYPE_SIX_BIT_ASCII) { /*type 2 6-bit ASCII*/
+ for (i=j=0; i<slen; i+=3) {
+ u.bits = 0;
+ k = ((slen-i) < 3 ? (slen-i) : 3);
+#if WORDS_BIGENDIAN
+ u.chars[3] = s[i];
+ u.chars[2] = (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 */
+ sz += frubuf[sz+1] * 8; /* add length of last section */
+ /* 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; ) {
+ 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++)
+ {
+ 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[25];
+ 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 [-bcimx -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");
+ print_lan_opt_usage();
+ 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 */
+ fp = fopen(binfile,"w");
+ 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 */
+ fp = fopen(binfile,"r");
+ 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 */
diff --git a/util/ifwum.c b/util/ifwum.c
new file mode 100644
index 0000000..1e7d547
--- /dev/null
+++ b/util/ifwum.c
@@ -0,0 +1,1697 @@
+/*
+ * ifwum.c
+ * Handle firmware update manager IPMI command functions
+ *
+ * Change history:
+ * 08/20/2010 ARCress - ported from ipmitool/lib/ipmi_fwum.c
+ *
+ *---------------------------------------------------------------------
+ */
+/*
+ * 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.
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#include "getopt.h"
+#elif defined(HPUX)
+/* getopt defined in stdio.h */
+#elif defined(MACOS)
+/* getopt is defined in unistd.h */
+#include <unistd.h>
+#else
+#include <getopt.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#ifdef LINUX
+#include <unistd.h>
+#endif
+#include "ipmicmd.h"
+#include "ifwum.h"
+
+/******************************************************************************
+* HISTORY
+* ===========================================================================
+* 2007-01-11 [FI]
+* - Incremented to version 1.3
+* - Added lan packet size reduction mechanism to workaround fact
+* that lan iface will not return C7 on excessive length
+*
+*****************************************************************************/
+
+extern int verbose; /*see ipmilanplus.c*/
+extern void lprintf(int level, const char * format, ...); /*ipmilanplus.c*/
+// extern int ipmi_sendrecv(struct ipmi_rq * req, uint8_t *rsp, int *rsp_len);
+extern char * get_mfg_str(uchar *rgmfg, int *pmfg); /*ihealth.c*/
+#ifndef HAVE_LANPLUS
+/* define these routines here if no lanplus/helper.c */
+extern uint16_t buf2short(uint8_t * buf); /*ipmilanplus.c*/
+// const char * val2str(uint16_t val, const struct valstr *vs);
+#endif
+
+#define VERSION_MAJ 1
+#define VERSION_MIN 3
+
+/* global variables */
+static char * progname = "ifwum";
+static char * progver = "1.3";
+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;
+
+typedef enum eKFWUM_Task
+{
+ KFWUM_TASK_INFO,
+ KFWUM_TASK_STATUS,
+ KFWUM_TASK_DOWNLOAD,
+ KFWUM_TASK_UPGRADE,
+ KFWUM_TASK_START_UPGRADE,
+ KFWUM_TASK_ROLLBACK,
+ KFWUM_TASK_TRACELOG
+}tKFWUM_Task;
+
+typedef enum eKFWUM_BoardList
+{
+ KFWUM_BOARD_KONTRON_UNKNOWN = 0,
+ KFWUM_BOARD_KONTRON_5002 = 5002,
+}tKFWUM_BoardList;
+
+typedef enum eKFWUM_IanaList
+{
+ KFWUM_IANA_KONTRON = 15000,
+}tKFWUM_IanaList;
+
+typedef struct sKFWUM_BoardInfo
+{
+ tKFWUM_BoardList boardId;
+ tKFWUM_IanaList iana;
+}tKFWUM_BoardInfo;
+
+
+#define KFWUM_STATUS_OK 0
+#define KFWUM_STATUS_ERROR -1
+typedef int tKFWUM_Status;
+//typedef enum eKFWUM_Status
+//{
+// KFWUM_STATUS_OK,
+// KFWUM_STATUS_ERROR
+//}tKFWUM_Status;
+
+typedef enum eKFWUM_DownloadType
+{
+ KFWUM_DOWNLOAD_TYPE_ADDRESS = 0,
+ KFWUM_DOWNLOAD_TYPE_SEQUENCE,
+}tKFWUM_DownloadType;
+
+typedef enum eKFWUM_DownloadBuffferType
+{
+ KFWUM_SMALL_BUFFER_TYPE = 0,
+ KFUMW_BIG_BUFFER_TYPE
+}tKFWUM_DownloadBuffferType;
+
+typedef struct sKFWUM_InFirmwareInfo
+{
+ unsigned long fileSize;
+ unsigned short checksum;
+ unsigned short sumToRemoveFromChecksum;
+ /* Since the checksum is added in the bin
+ after the checksum is calculated, we
+ need to remove the each byte value. This
+ byte will contain the addition of both bytes*/
+ tKFWUM_BoardList boardId;
+ unsigned char deviceId;
+ unsigned char tableVers;
+ unsigned char implRev;
+ unsigned char versMajor;
+ unsigned char versMinor;
+ unsigned char versSubMinor;
+ unsigned char sdrRev;
+ tKFWUM_IanaList iana;
+}tKFWUM_InFirmwareInfo;
+
+typedef struct sKFWUM_SaveFirmwareInfo
+{
+ tKFWUM_DownloadType downloadType;
+ unsigned char bufferSize;
+ unsigned char overheadSize;
+}tKFWUM_SaveFirmwareInfo;
+
+#define KFWUM_SMALL_BUFFER 32 /* Minimum size (IPMB/IOL/old protocol) */
+#define KFWUM_BIG_BUFFER 32 /* Maximum size on KCS interface */
+
+#define KFWUM_OLD_CMD_OVERHEAD 6 /*3 address + 1 size + 1 checksum + 1 command*/
+#define KFWUM_NEW_CMD_OVERHEAD 4 /*1 sequence+ 1 size + 1 checksum + 1 command*/
+#define KFWUM_PAGE_SIZE 256
+
+static unsigned char fileName[512];
+static unsigned char firmBuf[1024*512];
+static tKFWUM_SaveFirmwareInfo saveFirmwareInfo;
+
+static void KfwumOutputHelp(void);
+static int KfwumMain(void * intf, tKFWUM_Task task);
+static tKFWUM_Status KfwumGetFileSize(unsigned char * pFileName,
+ unsigned long * pFileSize);
+static tKFWUM_Status KfwumSetupBuffersFromFile(unsigned char * pFileName,
+ unsigned long fileSize);
+static void KfwumShowProgress( const unsigned char * task,
+ unsigned long current, unsigned long total);
+static unsigned short KfwumCalculateChecksumPadding(unsigned char * pBuffer,
+ unsigned long totalSize);
+
+
+static tKFWUM_Status KfwumGetInfo(void * intf, unsigned char output,
+ unsigned char *pNumBank);
+static tKFWUM_Status KfwumGetDeviceInfo(void * intf,
+ unsigned char output, tKFWUM_BoardInfo * pBoardInfo);
+static tKFWUM_Status KfwumGetStatus(void * intf);
+static tKFWUM_Status KfwumManualRollback(void * intf);
+static tKFWUM_Status KfwumStartFirmwareImage(void * intf,
+ unsigned long length,unsigned short padding);
+static tKFWUM_Status KfwumSaveFirmwareImage(void * intf,
+ unsigned char sequenceNumber, unsigned long address,
+ unsigned char *pFirmBuf, unsigned char * pInBufLength);
+static tKFWUM_Status KfwumFinishFirmwareImage(void * intf,
+ tKFWUM_InFirmwareInfo firmInfo);
+static tKFWUM_Status KfwumUploadFirmware(void * intf,
+ unsigned char * pBuffer, unsigned long totalSize);
+static tKFWUM_Status KfwumStartFirmwareUpgrade(void * intf);
+
+static tKFWUM_Status KfwumGetInfoFromFirmware(unsigned char * pBuf,
+ unsigned long bufSize, tKFWUM_InFirmwareInfo * pInfo);
+static void KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo * pInfo);
+
+static tKFWUM_Status KfwumGetTraceLog(void * intf);
+
+tKFWUM_Status KfwumValidFirmwareForBoard(tKFWUM_BoardInfo boardInfo,
+ tKFWUM_InFirmwareInfo firmInfo);
+static void KfwumOutputInfo(tKFWUM_BoardInfo boardInfo,
+ tKFWUM_InFirmwareInfo firmInfo);
+
+
+/* ipmi_fwum_main - entry point for this ipmitool mode
+ *
+ * @intf: ipmi interface
+ * @arc : number of arguments
+ * @argv : point to argument array
+ *
+ * returns 0 on success
+ * returns -1 on error
+ */
+int ipmi_fwum_main(void * intf, int argc, char ** argv)
+{
+ int rv = ERR_USAGE; /*1*/
+ printf("FWUM extension Version %d.%d\n", VERSION_MAJ, VERSION_MIN);
+ if ((!argc) || ( !strncmp(argv[0], "help", 4)))
+ {
+ KfwumOutputHelp();
+ }
+ else
+ {
+ if (!strncmp(argv[0], "info", 4))
+ {
+ rv = KfwumMain(intf, KFWUM_TASK_INFO);
+ }
+ else if (!strncmp(argv[0], "status", 6))
+ {
+ rv = KfwumMain(intf, KFWUM_TASK_STATUS);
+ }
+ else if (!strncmp(argv[0], "rollback", 8))
+ {
+ rv = KfwumMain(intf, KFWUM_TASK_ROLLBACK);
+ }
+ else if (!strncmp(argv[0], "download", 8))
+ {
+ if((argc >= 2) && (strlen(argv[1]) > 0))
+ {
+ /* There is a file name in the parameters */
+ if(strlen(argv[1]) < 512)
+ {
+ strcpy((char *)fileName, argv[1]);
+ printf("Firmware File Name : %s\n", fileName);
+
+ rv = KfwumMain(intf, KFWUM_TASK_DOWNLOAD);
+ }
+ else
+ {
+ fprintf(stderr,"File name must be smaller than 512 bytes\n");
+ }
+ }
+ else
+ {
+ fprintf(stderr,"A path and a file name must be specified\n");
+ }
+ }
+ else if (!strncmp(argv[0], "upgrade", 7))
+ {
+ if((argc >= 2) && (strlen(argv[1]) > 0))
+ {
+ /* There is a file name in the parameters */
+ if(strlen(argv[1]) < 512)
+ {
+ strcpy((char *)fileName, argv[1]);
+ printf("Upgrading using file name %s\n", fileName);
+ rv = KfwumMain(intf, KFWUM_TASK_UPGRADE);
+ }
+ else
+ {
+ fprintf(stderr,"File name must be smaller than 512 bytes\n");
+ }
+ }
+ else
+ {
+ rv = KfwumMain(intf, KFWUM_TASK_START_UPGRADE);
+ }
+
+ }
+ else if (!strncmp(argv[0], "tracelog", 8))
+ {
+ rv = KfwumMain(intf, KFWUM_TASK_TRACELOG);
+ }
+ else
+ {
+ printf("Invalid KFWUM command: %s\n", argv[0]);
+ }
+ }
+ return rv;
+}
+
+
+static void KfwumOutputHelp(void)
+{
+ printf("KFWUM Commands: info status download upgrade rollback tracelog\n");
+}
+
+
+/****************************************/
+/** private definitions and macros **/
+/****************************************/
+typedef enum eFWUM_CmdId
+{
+ KFWUM_CMD_ID_GET_FIRMWARE_INFO = 0,
+ KFWUM_CMD_ID_KICK_IPMC_WATCHDOG = 1,
+ KFWUM_CMD_ID_GET_LAST_ANSWER = 2,
+ KFWUM_CMD_ID_BOOT_HANDSHAKE = 3,
+ KFWUM_CMD_ID_REPORT_STATUS = 4,
+ KFWUM_CMD_ID_GET_FIRMWARE_STATUS = 7,
+ KFWUM_CMD_ID_START_FIRMWARE_UPDATE = 9,
+ KFWUM_CMD_ID_START_FIRMWARE_IMAGE = 0x0a,
+ KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE = 0x0b,
+ KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE = 0x0c,
+ KFWUM_CMD_ID_READ_FIRMWARE_IMAGE = 0x0d,
+ KFWUM_CMD_ID_MANUAL_ROLLBACK = 0x0e,
+ KFWUM_CMD_ID_GET_TRACE_LOG = 0x0f,
+ KFWUM_CMD_ID_STD_MAX_CMD,
+ KFWUM_CMD_ID_EXTENDED_CMD = 0xC0
+} tKFWUM_CmdId;
+
+
+
+/****************************************/
+/** global/static variables definition **/
+/****************************************/
+
+/****************************************/
+/** functions definition **/
+/****************************************/
+
+/*******************************************************************************
+*
+* Function Name: KfwumMain
+*
+* Description: This function implements the upload of the firware data
+* received as parameters.
+*
+* Restriction: Called only from main
+*
+* Input: unsigned char * pBuffer[] : The buffers
+* unsigned long bufSize : The size of the buffers
+*
+* Output: None
+*
+* Global: none
+*
+* Return: tIFWU_Status (success or failure)
+*
+*******************************************************************************/
+static int KfwumMain(void * intf, tKFWUM_Task task)
+{
+ tKFWUM_Status status = KFWUM_STATUS_OK;
+ tKFWUM_BoardInfo boardInfo;
+ tKFWUM_InFirmwareInfo firmInfo = { 0 };
+ unsigned long fileSize = 0;
+ static unsigned short padding;
+
+ if((status == KFWUM_STATUS_OK) && (task == KFWUM_TASK_INFO))
+ {
+ unsigned char notUsed;
+ if(verbose)
+ {
+ printf("Getting Kontron FWUM Info\n");
+ }
+ status = KfwumGetDeviceInfo(intf, 1, &boardInfo);
+ status = KfwumGetInfo(intf, 1, &notUsed);
+
+ }
+
+
+ if((status == KFWUM_STATUS_OK) && (task == KFWUM_TASK_STATUS))
+ {
+ if(verbose)
+ {
+ printf("Getting Kontron FWUM Status\n");
+ }
+ status = KfwumGetStatus(intf);
+ }
+
+ if( (status == KFWUM_STATUS_OK) && (task == KFWUM_TASK_ROLLBACK) )
+ {
+ status = KfwumManualRollback(intf);
+ }
+
+ if(
+ (status == KFWUM_STATUS_OK) &&
+ (
+ (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_DOWNLOAD)
+ )
+ )
+ {
+ status = KfwumGetFileSize(fileName, &fileSize);
+ if(status == KFWUM_STATUS_OK)
+ {
+ status = KfwumSetupBuffersFromFile(fileName, fileSize);
+ if(status == KFWUM_STATUS_OK)
+ {
+ padding = KfwumCalculateChecksumPadding(firmBuf, fileSize);
+ }
+ }
+ if(status == KFWUM_STATUS_OK)
+ {
+ status = KfwumGetInfoFromFirmware(firmBuf, fileSize, &firmInfo);
+ }
+ if(status == KFWUM_STATUS_OK)
+ {
+ status = KfwumGetDeviceInfo(intf, 0, &boardInfo);
+ }
+
+ if(status == KFWUM_STATUS_OK)
+ {
+ status = KfwumValidFirmwareForBoard(boardInfo,firmInfo);
+ }
+
+ if (status == KFWUM_STATUS_OK)
+ {
+ unsigned char notUsed;
+ KfwumGetInfo(intf, 0, &notUsed);
+ }
+
+ KfwumOutputInfo(boardInfo,firmInfo);
+ }
+
+ if(
+ (status == KFWUM_STATUS_OK) &&
+ (
+ (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_DOWNLOAD)
+ )
+ )
+ {
+ status = KfwumStartFirmwareImage(intf, fileSize, padding);
+ }
+
+
+ if(
+ (status == KFWUM_STATUS_OK) &&
+ (
+ (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_DOWNLOAD)
+ )
+ )
+ {
+ status = KfwumUploadFirmware(intf, firmBuf, fileSize);
+ }
+
+ if(
+ (status == KFWUM_STATUS_OK) &&
+ (
+ (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_DOWNLOAD)
+ )
+ )
+ {
+ status = KfwumFinishFirmwareImage(intf, firmInfo);
+ }
+
+ if(
+ (status == KFWUM_STATUS_OK) &&
+ (
+ (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_DOWNLOAD)
+ )
+ )
+ {
+ status = KfwumGetStatus(intf);
+ }
+
+ if(
+ (status == KFWUM_STATUS_OK) &&
+ (
+ (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_START_UPGRADE)
+ )
+ )
+ {
+ status = KfwumStartFirmwareUpgrade(intf);
+ }
+
+ if((status == KFWUM_STATUS_OK) && (task == KFWUM_TASK_TRACELOG))
+ {
+ status = KfwumGetTraceLog(intf);
+ }
+
+ return(status);
+}
+
+/* KfwumGetFileSize - gets the file size
+ *
+ * @pFileName : filename ptr
+ * @pFileSize : output ptr for filesize
+ *
+ * returns KFWUM_STATUS_OK or KFWUM_STATUS_ERROR
+ */
+static tKFWUM_Status KfwumGetFileSize(unsigned char * pFileName,
+ unsigned long * pFileSize)
+{
+ tKFWUM_Status status = KFWUM_STATUS_ERROR;
+ FILE * pFileHandle;
+
+ pFileHandle = fopen((const char *)pFileName, "rb");
+
+ if(pFileHandle)
+ {
+ if(fseek(pFileHandle, 0L , SEEK_END) == 0)
+ {
+ *pFileSize = ftell(pFileHandle);
+
+ if( *pFileSize != 0)
+ {
+ status = KFWUM_STATUS_OK;
+ }
+ }
+ fclose(pFileHandle);
+ }
+
+ return(status);
+}
+
+/* KfwumSetupBuffersFromFile - small buffers are used to store the file data
+ *
+ * @pFileName : filename ptr
+ * unsigned long : filesize
+ *
+ * returns KFWUM_STATUS_OK or KFWUM_STATUS_ERROR
+ */
+#define MAX_FW_BUFFER_SIZE 1024*16
+static tKFWUM_Status KfwumSetupBuffersFromFile(unsigned char * pFileName,
+ unsigned long fileSize)
+{
+ tKFWUM_Status status = KFWUM_STATUS_OK;
+ FILE * pFileHandle;
+
+ pFileHandle = fopen((const char *)pFileName, "rb");
+
+ if(pFileHandle)
+ {
+ int count = fileSize / MAX_FW_BUFFER_SIZE;
+ int modulus = fileSize % MAX_FW_BUFFER_SIZE;
+ int qty =0;
+
+ rewind(pFileHandle);
+
+ for(qty=0;qty<count;qty++)
+ {
+ KfwumShowProgress((const unsigned char *)"Reading Firmware from File", qty, count );
+ if(fread(&firmBuf[qty*MAX_FW_BUFFER_SIZE], 1, MAX_FW_BUFFER_SIZE ,pFileHandle)
+ == MAX_FW_BUFFER_SIZE)
+ {
+ status = KFWUM_STATUS_OK;
+ }
+ }
+ if( modulus )
+ {
+ if(fread(&firmBuf[qty*MAX_FW_BUFFER_SIZE], 1, modulus, pFileHandle) == modulus)
+ {
+ status = KFWUM_STATUS_OK;
+ }
+ }
+ if(status == KFWUM_STATUS_OK)
+ {
+ KfwumShowProgress((const unsigned char *)"Reading Firmware from File", 100, 100);
+ }
+ fclose(pFileHandle);
+ }
+ return(status);
+}
+
+/* KfwumShowProgress - helper routine to display progress bar
+ *
+ * Converts current/total in percent
+ *
+ * *task : string identifying current operation
+ * current: progress
+ * total : limit
+ */
+#define PROG_LENGTH 42
+void KfwumShowProgress( const unsigned char * task, unsigned long current ,
+ unsigned long total)
+{
+ static unsigned long staticProgress=0xffffffff;
+ unsigned char spaces[PROG_LENGTH + 1];
+ unsigned short hash;
+ float percent = ((float)current/total);
+ unsigned long progress;
+
+ progress = 100*((unsigned long)percent);
+ if(staticProgress == progress)
+ {
+ /* We displayed the same last time.. so don't do it */
+ }
+ else
+ {
+ staticProgress = progress;
+
+
+ printf("%-25s : ",task); /* total 20 bytes */
+
+ hash = ( (unsigned short)percent * PROG_LENGTH );
+ memset(spaces,'#', hash);
+ spaces[ hash ] = '\0';
+ printf("%s", spaces );
+
+ memset(spaces,' ',( PROG_LENGTH - hash ) );
+ spaces[ ( PROG_LENGTH - hash ) ] = '\0';
+ printf("%s", spaces );
+
+
+ printf(" %3ld %%\r",progress); /* total 7 bytes */
+
+ if( progress == 100 )
+ {
+ printf("\n");
+ }
+ fflush(stdout);
+ }
+}
+
+/* KfwumCalculateChecksumPadding
+ *
+ * TBD
+ *
+ */
+static unsigned short KfwumCalculateChecksumPadding(unsigned char * pBuffer,
+ unsigned long totalSize)
+{
+ unsigned short sumOfBytes = 0;
+ unsigned short padding;
+ unsigned long counter;
+
+ for(counter = 0; counter < totalSize; counter ++ )
+ {
+ sumOfBytes += pBuffer[counter];
+ }
+
+ padding = 0 - sumOfBytes;
+ return padding;
+}
+
+/******************************************************************************
+******************************* COMMANDS **************************************
+******************************************************************************/
+#pragma pack(1)
+struct KfwumGetInfoResp {
+ unsigned char protocolRevision;
+ unsigned char controllerDeviceId;
+ struct
+ {
+ unsigned char mode:1;
+ unsigned char seqAdd:1;
+ unsigned char res : 6;
+ } byte;
+ unsigned char firmRev1;
+ unsigned char firmRev2;
+ unsigned char numBank;
+}; // __attribute__ ((packed));
+#pragma pack()
+
+
+/* KfwumGetInfo - Get Firmware Update Manager (FWUM) information
+ *
+ * * intf : IPMI interface
+ * output : when set to non zero, queried information is displayed
+ * pNumBank: output ptr for number of banks
+ */
+static tKFWUM_Status KfwumGetInfo(void * intf, unsigned char output,
+ unsigned char *pNumBank)
+{
+ tKFWUM_Status status = KFWUM_STATUS_OK;
+ static struct KfwumGetInfoResp *pGetInfo;
+ uchar rsp[IPMI_RSPBUF_SIZE];
+ int rsp_len, rv;
+ struct ipmi_rq req;
+ int dtype;
+ uchar bus, sa, lun, mtype;
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
+ req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_INFO;
+ req.msg.data_len = 0;
+
+ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
+ if (rv) {
+ printf("FWUM Firmware Get Info returned %d (0x%02x)\n",rv,rv);
+ status = rv; // KFWUM_STATUS_ERROR
+ }
+
+ if(status == KFWUM_STATUS_OK)
+ {
+ pGetInfo = (struct KfwumGetInfoResp *) rsp;
+ if(output)
+ {
+ printf("\nFWUM info\n");
+ printf("=========\n");
+ printf("Protocol Revision : %02Xh\n",
+ pGetInfo->protocolRevision);
+ printf("Controller Device Id : %02Xh\n",
+ pGetInfo->controllerDeviceId);
+ printf("Firmware Revision : %u.%u%u",
+ pGetInfo->firmRev1, pGetInfo->firmRev2 >> 4,
+ pGetInfo->firmRev2 & 0x0f);
+ if(pGetInfo->byte.mode != 0)
+ {
+ printf(" - DEBUG BUILD\n");
+ }
+ else
+ {
+ printf("\n");
+ }
+ printf("Number Of Memory Bank : %u\n",pGetInfo->numBank);
+ }
+ * pNumBank = pGetInfo->numBank;
+
+ /* Determine wich type of download to use: */
+ /* Old FWUM or Old IPMC fw (data_len < 7) -->
+ Address with small buffer size */
+ if ( (pGetInfo->protocolRevision) <= 0x05 || (rsp_len < 7 ) )
+ {
+ saveFirmwareInfo.downloadType = KFWUM_DOWNLOAD_TYPE_ADDRESS;
+ saveFirmwareInfo.bufferSize = KFWUM_SMALL_BUFFER;
+ saveFirmwareInfo.overheadSize = KFWUM_OLD_CMD_OVERHEAD;
+
+ if(verbose)
+ {
+ printf("Protocol Revision :");
+ printf(" <= 5 detected, adjusting buffers\n");
+ }
+ }
+ else /* Both fw are using the new protocol */
+ {
+ saveFirmwareInfo.downloadType = KFWUM_DOWNLOAD_TYPE_SEQUENCE;
+ saveFirmwareInfo.overheadSize = KFWUM_NEW_CMD_OVERHEAD;
+ /* Buffer size depending on access type (Local or remote) */
+ /* Look if we run remote or locally */
+
+ if(verbose)
+ {
+ printf("Protocol Revision :");
+ printf(" > 5 optimizing buffers\n");
+ }
+
+ ipmi_get_mc(&bus, &sa, &lun, &mtype);
+ dtype = get_driver_type();
+ if(is_remote()) /* covers lan and lanplus */
+ {
+ saveFirmwareInfo.bufferSize = KFWUM_SMALL_BUFFER;
+ if(verbose)
+ {
+ printf("IOL payload size : %d\r\n" ,
+ saveFirmwareInfo.bufferSize);
+ }
+ } else if ( (dtype == DRV_MV) && (sa != IPMI_BMC_SLAVE_ADDR) &&
+ (mtype == ADDR_IPMB) )
+ {
+ saveFirmwareInfo.bufferSize = KFWUM_SMALL_BUFFER;
+ if(verbose)
+ {
+ printf("IPMB payload size : %d\r\n" ,
+ saveFirmwareInfo.bufferSize);
+ }
+ }
+ else
+ {
+ saveFirmwareInfo.bufferSize = KFWUM_BIG_BUFFER;
+ if(verbose)
+ {
+ printf("SMI payload size : %d\r\n",
+ saveFirmwareInfo.bufferSize);
+ }
+ }
+ }
+ }
+ return status;
+}
+
+/* KfwumGetDeviceInfo - Get IPMC/Board information
+ *
+ * * intf : IPMI interface
+ * output : when set to non zero, queried information is displayed
+ * tKFWUM_BoardInfo: output ptr for IPMC/Board information
+ */
+static tKFWUM_Status KfwumGetDeviceInfo(void * intf,
+ unsigned char output, tKFWUM_BoardInfo * pBoardInfo)
+{
+ struct ipm_devid_rsp *pGetDevId;
+ tKFWUM_Status status = KFWUM_STATUS_OK;
+ uchar rsp[IPMI_RSPBUF_SIZE];
+ int rsp_len, rv;
+ struct ipmi_rq req;
+ char *mstr;
+
+ /* Send Get Device Id */
+ if(status == KFWUM_STATUS_OK)
+ {
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_APP;
+ req.msg.cmd = BMC_GET_DEVICE_ID;
+ req.msg.data_len = 0;
+
+ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
+ if (rv) {
+ printf("Error in Get Device Id Command %d (0x%02x)\n",rv,rv);
+ status = rv; // KFWUM_STATUS_ERROR
+ }
+ }
+
+ if(status == KFWUM_STATUS_OK)
+ {
+ pGetDevId = (struct ipm_devid_rsp *) rsp;
+ pBoardInfo->iana = IPM_DEV_MANUFACTURER_ID(pGetDevId->manufacturer_id);
+ pBoardInfo->boardId = buf2short(pGetDevId->product_id);
+ if(output)
+ {
+ mstr = get_mfg_str(pGetDevId->manufacturer_id,NULL);
+ printf("\nIPMC Info\n");
+ printf("=========\n");
+ printf("Manufacturer Id : %u \t%s\n",pBoardInfo->iana,mstr);
+ printf("Board Id : %u\n",pBoardInfo->boardId);
+ printf("Firmware Revision : %u.%u%u",
+ pGetDevId->fw_rev1, pGetDevId->fw_rev2 >> 4,
+ pGetDevId->fw_rev2 & 0x0f);
+ if(
+ (
+ ( pBoardInfo->iana == KFWUM_IANA_KONTRON)
+ &&
+ (pBoardInfo->boardId == KFWUM_BOARD_KONTRON_5002)
+ )
+ )
+ {
+ printf(" SDR %u\n", pGetDevId->aux_fw_rev[0]);
+ }
+ else
+ {
+ printf("\n");
+ }
+ }
+ }
+
+ return status;
+}
+
+#pragma pack(1)
+struct KfwumGetStatusResp {
+ unsigned char bankState;
+ unsigned char firmLengthLSB;
+ unsigned char firmLengthMid;
+ unsigned char firmLengthMSB;
+ unsigned char firmRev1;
+ unsigned char firmRev2;
+ unsigned char firmRev3;
+}; // __attribute__ ((packed));
+#pragma pack()
+
+const struct valstr bankStateValS[] = {
+ { 0x00, "Not programmed" },
+ { 0x01, "New firmware" },
+ { 0x02, "Wait for validation" },
+ { 0x03, "Last Known Good" },
+ { 0x04, "Previous Good" }
+};
+
+/* KfwumGetStatus - Get (and prints) FWUM banks information
+ *
+ * * intf : IPMI interface
+ */
+static tKFWUM_Status KfwumGetStatus(void * intf)
+{
+ tKFWUM_Status status = KFWUM_STATUS_OK;
+ uchar rsp[IPMI_RSPBUF_SIZE];
+ int rsp_len, rv;
+ struct ipmi_rq req;
+ struct KfwumGetStatusResp *pGetStatus;
+ unsigned char numBank;
+ unsigned char counter;
+
+ if(verbose)
+ {
+ printf(" Getting Status!\n");
+ }
+
+ /* Retreive the number of bank */
+ status = KfwumGetInfo(intf, 0, &numBank);
+
+ for(
+ counter = 0;
+ (counter < numBank) && (status == KFWUM_STATUS_OK);
+ counter ++
+ )
+ {
+ /* Retreive the status of each bank */
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
+ req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_STATUS;
+ req.msg.data = &counter;
+ req.msg.data_len = 1;
+
+ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
+ if (rv) {
+ printf("FWUM Firmware Get Status Error %d (0x%02x)\n",rv,rv);
+ status = rv; // KFWUM_STATUS_ERROR
+ }
+
+ if(status == KFWUM_STATUS_OK)
+ {
+ pGetStatus = (struct KfwumGetStatusResp *) rsp;
+ printf("\nBank State %d : %s\n", counter, val2str(
+ pGetStatus->bankState, bankStateValS));
+ if(pGetStatus->bankState)
+ {
+ unsigned long firmLength;
+ firmLength = pGetStatus->firmLengthMSB;
+ firmLength = firmLength << 8;
+ firmLength |= pGetStatus->firmLengthMid;
+ firmLength = firmLength << 8;
+ firmLength |= pGetStatus->firmLengthLSB;
+
+ printf("Firmware Length : %ld bytes\n", firmLength);
+ printf("Firmware Revision : %u.%u%u SDR %u\n",
+ pGetStatus->firmRev1, pGetStatus->firmRev2 >> 4,
+ pGetStatus->firmRev2 & 0x0f, pGetStatus->firmRev3);
+ }
+ }
+ }
+ printf("\n");
+ return status;
+}
+#pragma pack(1)
+struct KfwumManualRollbackReq{
+ unsigned char type;
+}; // __attribute__ ((packed));
+#pragma pack()
+
+
+/* KfwumManualRollback - Ask IPMC to rollback to previous version
+ *
+ * * intf : IPMI interface
+ */
+static tKFWUM_Status KfwumManualRollback(void * intf)
+{
+ tKFWUM_Status status = KFWUM_STATUS_OK;
+ uchar rsp[IPMI_RSPBUF_SIZE];
+ int rsp_len, rv;
+ struct ipmi_rq req;
+ struct KfwumManualRollbackReq thisReq;
+
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
+ req.msg.cmd = KFWUM_CMD_ID_MANUAL_ROLLBACK;
+
+ thisReq.type = 0; /* Wait BMC shutdown */
+
+ req.msg.data = (unsigned char *) &thisReq;
+ req.msg.data_len = 1;
+
+ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
+ if (rv) {
+ printf("Error in FWUM Manual Rollback Command %d (0x%02x)\n",rv,rv);
+ status = rv; // KFWUM_STATUS_ERROR
+ }
+
+ if(status == KFWUM_STATUS_OK)
+ {
+ printf("FWUM Starting Manual Rollback \n");
+ }
+ return status;
+}
+
+#pragma pack(1)
+struct KfwumStartFirmwareDownloadReq{
+ unsigned char lengthLSB;
+ unsigned char lengthMid;
+ unsigned char lengthMSB;
+ unsigned char paddingLSB;
+ unsigned char paddingMSB;
+ unsigned char useSequence;
+}; // __attribute__ ((packed));
+struct KfwumStartFirmwareDownloadResp {
+ unsigned char bank;
+}; // __attribute__ ((packed));
+#pragma pack()
+
+static tKFWUM_Status KfwumStartFirmwareImage(void * intf,
+ unsigned long length,unsigned short padding)
+{
+ tKFWUM_Status status = KFWUM_STATUS_OK;
+ uchar rsp[IPMI_RSPBUF_SIZE];
+ int rsp_len, rv;
+ struct ipmi_rq req;
+ struct KfwumStartFirmwareDownloadResp *pResp;
+ struct KfwumStartFirmwareDownloadReq thisReq;
+
+ thisReq.lengthLSB = (uchar)(length & 0x000000ff);
+ thisReq.lengthMid = (uchar)((length >> 8) & 0x000000ff);
+ thisReq.lengthMSB = (uchar)((length >> 16) & 0x000000ff);
+ thisReq.paddingLSB = padding & 0x00ff;
+ thisReq.paddingMSB = (padding>> 8) & 0x00ff;
+ thisReq.useSequence = 0x01;
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
+ req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_IMAGE;
+ req.msg.data = (unsigned char *) &thisReq;
+
+ /* Look for download type */
+ if ( saveFirmwareInfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS )
+ {
+ req.msg.data_len = 5;
+ }
+ else
+ {
+ req.msg.data_len = 6;
+ }
+
+ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
+ if (rv) {
+ printf("FWUM Firmware Start Firmware Image Download returned %d (0x%02x)\n",rv,rv);
+ status = rv; // KFWUM_STATUS_ERROR
+ }
+
+ if(status == KFWUM_STATUS_OK)
+ {
+ pResp = (struct KfwumStartFirmwareDownloadResp *) rsp;
+ printf("Bank holding new firmware : %d\n", pResp->bank);
+ os_usleep(5,0);
+ }
+ return status;
+}
+
+#pragma pack(1)
+struct KfwumSaveFirmwareAddressReq
+{
+ unsigned char addressLSB;
+ unsigned char addressMid;
+ unsigned char addressMSB;
+ unsigned char numBytes;
+ unsigned char txBuf[KFWUM_SMALL_BUFFER-KFWUM_OLD_CMD_OVERHEAD];
+}; // __attribute__ ((packed));
+
+struct KfwumSaveFirmwareSequenceReq
+{
+ unsigned char sequenceNumber;
+ unsigned char txBuf[KFWUM_BIG_BUFFER];
+}; // __attribute__ ((packed));
+#pragma pack()
+
+
+#define FWUM_SAVE_FIRMWARE_NO_RESPONSE_LIMIT ((unsigned char)6)
+
+static tKFWUM_Status KfwumSaveFirmwareImage(void * intf,
+ unsigned char sequenceNumber, unsigned long address, unsigned char *pFirmBuf,
+ unsigned char * pInBufLength)
+{
+ tKFWUM_Status status = KFWUM_STATUS_OK;
+ uchar rsp[IPMI_RSPBUF_SIZE];
+ int rsp_len, rv;
+ struct ipmi_rq req;
+ unsigned char out = 0;
+ unsigned char retry = 0;
+ unsigned char noResponse = 0 ;
+
+ struct KfwumSaveFirmwareAddressReq addressReq;
+ struct KfwumSaveFirmwareSequenceReq sequenceReq;
+
+ do
+ {
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
+ req.msg.cmd = KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE;
+
+ if (saveFirmwareInfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS )
+ {
+ addressReq.addressLSB = (uchar)(address & 0x000000ff);
+ addressReq.addressMid = (uchar)((address >> 8) & 0x000000ff);
+ addressReq.addressMSB = (uchar)((address >> 16) & 0x000000ff);
+ addressReq.numBytes = (* pInBufLength);
+ memcpy(addressReq.txBuf, pFirmBuf, (* pInBufLength));
+ req.msg.data = (unsigned char *) &addressReq;
+ req.msg.data_len = (* pInBufLength)+4;
+ }
+ else
+ {
+ sequenceReq.sequenceNumber = sequenceNumber;
+ memcpy(sequenceReq.txBuf, pFirmBuf, (* pInBufLength));
+ req.msg.data = (unsigned char *) &sequenceReq;
+ req.msg.data_len = (* pInBufLength)+sizeof(unsigned char); /* + 1 => sequenceNumber*/
+ }
+
+ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
+ if (rv < 0)
+ {
+ printf("Error in FWUM Firmware Save Firmware Image Download Command\n");
+
+ out = 0;
+ status = KFWUM_STATUS_OK;
+
+ /* With IOL, we don't receive "C7" on errors, instead we receive
+ nothing */
+ if(is_remote())
+ {
+ noResponse++;
+
+ if(noResponse < FWUM_SAVE_FIRMWARE_NO_RESPONSE_LIMIT )
+ {
+ (* pInBufLength) -= 1;
+ out = 0;
+ }
+ else
+ {
+ printf("Error, too many commands without response\n");
+ (* pInBufLength) = 0 ;
+ out = 1;
+ }
+ } /* For other interface keep trying */
+ }
+ else if (rv > 0) /*ccode*/
+ {
+ if(rv == 0xc0)
+ {
+ status = KFWUM_STATUS_OK;
+ os_usleep(1,0);
+ }
+ else if(
+ (rv == 0xc7)
+ ||
+ (
+ (rv == 0xC3) &&
+ (sequenceNumber == 0)
+ )
+ )
+ {
+ (* pInBufLength) -= 1;
+ status = KFWUM_STATUS_OK;
+ retry = 1;
+ }
+ else if(rv == 0x82)
+ {
+ /* Double sent, continue */
+ status = KFWUM_STATUS_OK;
+ out = 1;
+ }
+ else if(rv == 0x83)
+ {
+ if(retry == 0)
+ {
+ retry = 1;
+ status = KFWUM_STATUS_OK;
+ }
+ else
+ {
+ status = rv; // KFWUM_STATUS_ERROR
+ out = 1;
+ }
+ }
+ else if(rv == 0xcf) /* Ok if receive duplicated request */
+ {
+ retry = 1;
+ status = KFWUM_STATUS_OK;
+ }
+ else if(rv == 0xC3)
+ {
+ if(retry == 0)
+ {
+ retry = 1;
+ status = KFWUM_STATUS_OK;
+ }
+ else
+ {
+ status = rv; // KFWUM_STATUS_ERROR
+ out = 1;
+ }
+ }
+ else
+ {
+ printf("FWUM Firmware Save Firmware Image Download returned %x\n",
+ rv);
+ status = rv; // KFWUM_STATUS_ERROR
+ out = 1;
+ }
+ }
+ else
+ {
+ out = 1;
+ }
+ }while(out == 0);
+ return status;
+}
+
+#pragma pack(1)
+struct KfwumFinishFirmwareDownloadReq{
+ unsigned char versionMaj;
+ unsigned char versionMinSub;
+ unsigned char versionSdr;
+ unsigned char reserved;
+}; // __attribute__ ((packed));
+#pragma pack()
+static tKFWUM_Status KfwumFinishFirmwareImage(void * intf,
+ tKFWUM_InFirmwareInfo firmInfo)
+{
+ tKFWUM_Status status = KFWUM_STATUS_OK;
+ uchar rsp[IPMI_RSPBUF_SIZE];
+ int rsp_len, rv;
+ struct ipmi_rq req;
+ struct KfwumFinishFirmwareDownloadReq thisReq;
+
+ thisReq.versionMaj = firmInfo.versMajor;
+ thisReq.versionMinSub = ((firmInfo.versMinor <<4) | firmInfo.versSubMinor);
+ thisReq.versionSdr = firmInfo.sdrRev;
+ thisReq.reserved = 0;
+ /* Byte 4 reserved, write 0 */
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
+ req.msg.cmd = KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE;
+ req.msg.data = (unsigned char *) &thisReq;
+ req.msg.data_len = 4;
+
+ do
+ {
+ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
+ }while (rv == 0xc0);
+
+ if (rv < 0)
+ {
+ printf("Error in FWUM Firmware Finish Firmware Image Download Command\n");
+ status = rv; // KFWUM_STATUS_ERROR
+ }
+ else if (rv > 0)
+ {
+ printf("FWUM Firmware Finish Firmware Image Download returned %x\n",
+ rv);
+ status = rv; // KFWUM_STATUS_ERROR
+ }
+
+ return status;
+}
+
+
+#define FWUM_MAX_UPLOAD_RETRY 6
+static tKFWUM_Status KfwumUploadFirmware(void * intf,
+ unsigned char * pBuffer, unsigned long totalSize)
+{
+ tKFWUM_Status status = KFWUM_STATUS_ERROR;
+ unsigned long address = 0x0;
+ unsigned char writeSize;
+ unsigned char oldWriteSize;
+ unsigned long lastAddress = 0;
+ unsigned char sequenceNumber = 0;
+ unsigned char retry = FWUM_MAX_UPLOAD_RETRY;
+ // unsigned char isLengthValid = 1;
+
+ do
+ {
+ writeSize = saveFirmwareInfo.bufferSize - saveFirmwareInfo.overheadSize;
+
+ /* Reach the end */
+ if( address + writeSize > totalSize )
+ {
+ writeSize = (uchar)(totalSize - address);
+ }
+ /* Reach boundary end */
+ else if(((address % KFWUM_PAGE_SIZE) + writeSize) > KFWUM_PAGE_SIZE)
+ {
+ writeSize = (KFWUM_PAGE_SIZE - (uchar)(address % KFWUM_PAGE_SIZE));
+ }
+
+ oldWriteSize = writeSize;
+ status = KfwumSaveFirmwareImage(intf, sequenceNumber, address,
+ &pBuffer[address], &writeSize);
+
+ if((status != KFWUM_STATUS_OK) && (retry-- != 0))
+ {
+ address = lastAddress;
+ status = KFWUM_STATUS_OK;
+ }
+ else if( writeSize == 0 )
+ {
+ status = KFWUM_STATUS_ERROR;
+ }
+ else
+ {
+ if(writeSize != oldWriteSize)
+ {
+ printf("Adjusting length to %d bytes \n", writeSize);
+ saveFirmwareInfo.bufferSize -= (oldWriteSize - writeSize);
+ }
+
+ retry = FWUM_MAX_UPLOAD_RETRY;
+ lastAddress = address;
+ address+= writeSize;
+ }
+
+ if(status == KFWUM_STATUS_OK)
+ {
+ if((address % 1024) == 0)
+ {
+ KfwumShowProgress((const unsigned char *)\
+ "Writing Firmware in Flash",address,totalSize);
+ }
+ sequenceNumber++;
+ }
+
+ }while((status == KFWUM_STATUS_OK) && (address < totalSize ));
+
+ if(status == KFWUM_STATUS_OK)
+ {
+ KfwumShowProgress((const unsigned char *)\
+ "Writing Firmware in Flash", 100 , 100 );
+ }
+
+ return(status);
+}
+
+static tKFWUM_Status KfwumStartFirmwareUpgrade(void * intf)
+{
+ tKFWUM_Status status = KFWUM_STATUS_OK;
+ uchar rsp[IPMI_RSPBUF_SIZE];
+ int rsp_len, rv;
+ struct ipmi_rq req;
+ unsigned char upgType = 0 ; /* Upgrade type, wait BMC shutdown */
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
+ req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_UPDATE;
+ req.msg.data = (unsigned char *) &upgType;
+ req.msg.data_len = 1;
+
+ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
+ if (rv < 0)
+ {
+ printf("Error in FWUM Firmware Start Firmware Upgrade Command\n");
+ status = rv; // KFWUM_STATUS_ERROR
+ }
+ else if (rv > 0)
+ {
+ if(rv == 0xd5)
+ {
+ printf("No firmware available for upgrade. Download Firmware first\n");
+ }
+ else
+ {
+ printf("FWUM Firmware Start Firmware Upgrade returned %x\n",
+ rv);
+ }
+ status = rv; // KFWUM_STATUS_ERROR
+ }
+
+ return status;
+}
+
+#define TRACE_LOG_CHUNK_COUNT 7
+#define TRACE_LOG_CHUNK_SIZE 7
+#define TRACE_LOG_ATT_COUNT 3
+/* String table */
+/* Must match eFWUM_CmdId */
+static const char* CMD_ID_STRING[] = {
+ "GetFwInfo",
+ "KickWatchdog",
+ "GetLastAnswer",
+ "BootHandshake",
+ "ReportStatus",
+ "CtrlIPMBLine",
+ "SetFwState",
+ "GetFwStatus",
+ "GetSpiMemStatus",
+ "StartFwUpdate",
+ "StartFwImage",
+ "SaveFwImage",
+ "FinishFwImage",
+ "ReadFwImage",
+ "ManualRollback",
+ "GetTraceLog" };
+
+static const char* EXT_CMD_ID_STRING[] = {
+ "FwUpgradeLock",
+ "ProcessFwUpg",
+ "ProcessFwRb",
+ "WaitHSAfterUpg",
+ "WaitFirstHSUpg",
+ "FwInfoStateChange" };
+
+
+static const char* CMD_STATE_STRING[] = {
+ "Invalid",
+ "Begin",
+ "Progress",
+ "Completed" };
+
+
+static tKFWUM_Status KfwumGetTraceLog(void * intf)
+{
+ tKFWUM_Status status = KFWUM_STATUS_OK;
+ uchar rsp[IPMI_RSPBUF_SIZE];
+ int rsp_len, rv;
+ struct ipmi_rq req;
+ unsigned char chunkIdx;
+ unsigned char cmdIdx;
+
+ if(verbose)
+ {
+ printf(" Getting Trace Log!\n");
+ }
+
+ for( chunkIdx = 0; (chunkIdx < TRACE_LOG_CHUNK_COUNT) && (status == KFWUM_STATUS_OK); chunkIdx++ )
+ {
+ /* Retreive each log chunk and print it */
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
+ req.msg.cmd = KFWUM_CMD_ID_GET_TRACE_LOG;
+ req.msg.data = &chunkIdx;
+ req.msg.data_len = 1;
+
+ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
+ if (rv) {
+ printf("FWUM Firmware Get Trace Log returned %d (0x%02x)\n",rv,rv);
+ status = rv; // KFWUM_STATUS_ERROR
+ }
+
+ if(status == KFWUM_STATUS_OK)
+ {
+ for (cmdIdx=0; cmdIdx < TRACE_LOG_CHUNK_SIZE; cmdIdx++)
+ {
+ /* Don't diplay commands with an invalid state */
+ if ( (rsp[TRACE_LOG_ATT_COUNT*cmdIdx+1] != 0) &&
+ (rsp[TRACE_LOG_ATT_COUNT*cmdIdx] < KFWUM_CMD_ID_STD_MAX_CMD))
+ {
+ printf(" Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n",
+ CMD_ID_STRING[rsp[TRACE_LOG_ATT_COUNT*cmdIdx]],
+ CMD_STATE_STRING[rsp[TRACE_LOG_ATT_COUNT*cmdIdx+1]],
+ rsp[TRACE_LOG_ATT_COUNT*cmdIdx+2]);
+ }
+ else if ( (rsp[TRACE_LOG_ATT_COUNT*cmdIdx+1] != 0) &&
+ (rsp[TRACE_LOG_ATT_COUNT*cmdIdx] >= KFWUM_CMD_ID_EXTENDED_CMD))
+ {
+ printf(" Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n",
+ EXT_CMD_ID_STRING[rsp[TRACE_LOG_ATT_COUNT*cmdIdx] - KFWUM_CMD_ID_EXTENDED_CMD],
+ CMD_STATE_STRING[rsp[TRACE_LOG_ATT_COUNT*cmdIdx+1]],
+ rsp[TRACE_LOG_ATT_COUNT*cmdIdx+2]);
+ }
+ }
+ }
+ }
+ printf("\n");
+ return status;
+}
+
+
+/*******************************************************************************
+* Function Name: KfwumGetInfoFromFirmware
+*
+* Description: This function retreive from the firmare the following info :
+*
+* o Checksum
+* o File size (expected)
+* o Board Id
+* o Device Id
+*
+* Restriction: None
+*
+* Input: char * fileName - File to get info from
+*
+* Output: pInfo - container that will hold all the informations gattered.
+* see structure for all details
+*
+* Global: None
+*
+* Return: IFWU_SUCCESS - file ok
+* IFWU_ERROR - file error
+*
+*******************************************************************************/
+#define IN_FIRMWARE_INFO_OFFSET_LOCATION 0x5a0
+#define IN_FIRMWARE_INFO_SIZE 20
+#define IN_FIRMWARE_INFO_OFFSET_FILE_SIZE 0
+#define IN_FIRMWARE_INFO_OFFSET_CHECKSUM 4
+#define IN_FIRMWARE_INFO_OFFSET_BOARD_ID 6
+#define IN_FIRMWARE_INFO_OFFSET_DEVICE_ID 8
+#define IN_FIRMWARE_INFO_OFFSET_TABLE_VERSION 9
+#define IN_FIRMWARE_INFO_OFFSET_IMPLEMENT_REV 10
+#define IN_FIRMWARE_INFO_OFFSET_VERSION_MAJOR 11
+#define IN_FIRMWARE_INFO_OFFSET_VERSION_MINSUB 12
+#define IN_FIRMWARE_INFO_OFFSET_SDR_REV 13
+#define IN_FIRMWARE_INFO_OFFSET_IANA0 14
+#define IN_FIRMWARE_INFO_OFFSET_IANA1 15
+#define IN_FIRMWARE_INFO_OFFSET_IANA2 16
+
+#define KWUM_GET_BYTE_AT_OFFSET(pBuffer,os) pBuffer[os]
+
+tKFWUM_Status KfwumGetInfoFromFirmware(unsigned char * pBuf,
+ unsigned long bufSize, tKFWUM_InFirmwareInfo * pInfo)
+{
+ tKFWUM_Status status = KFWUM_STATUS_ERROR;
+
+ if(bufSize >= (IN_FIRMWARE_INFO_OFFSET_LOCATION + IN_FIRMWARE_INFO_SIZE))
+ {
+ unsigned long offset = IN_FIRMWARE_INFO_OFFSET_LOCATION;
+
+ /* Now, fill the structure with read informations */
+ pInfo->checksum = (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+0+IN_FIRMWARE_INFO_OFFSET_CHECKSUM ) << 8;
+ pInfo->checksum |= (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+1+IN_FIRMWARE_INFO_OFFSET_CHECKSUM );
+
+
+ pInfo->sumToRemoveFromChecksum=
+ KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+IN_FIRMWARE_INFO_OFFSET_CHECKSUM);
+
+ pInfo->sumToRemoveFromChecksum+=
+ KWUM_GET_BYTE_AT_OFFSET(pBuf ,
+ offset+IN_FIRMWARE_INFO_OFFSET_CHECKSUM+1);
+
+ pInfo->fileSize =
+ KWUM_GET_BYTE_AT_OFFSET(pBuf ,
+ offset+IN_FIRMWARE_INFO_OFFSET_FILE_SIZE+0) << 24;
+ pInfo->fileSize |=
+ (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+IN_FIRMWARE_INFO_OFFSET_FILE_SIZE+1) << 16;
+ pInfo->fileSize |=
+ (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+IN_FIRMWARE_INFO_OFFSET_FILE_SIZE+2) << 8;
+ pInfo->fileSize |=
+ (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+IN_FIRMWARE_INFO_OFFSET_FILE_SIZE+3);
+
+ pInfo->boardId =
+ KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+IN_FIRMWARE_INFO_OFFSET_BOARD_ID+0) << 8;
+ pInfo->boardId |=
+ KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+IN_FIRMWARE_INFO_OFFSET_BOARD_ID+1);
+
+ pInfo->deviceId =
+ KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+IN_FIRMWARE_INFO_OFFSET_DEVICE_ID);
+
+ pInfo->tableVers =
+ KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+IN_FIRMWARE_INFO_OFFSET_TABLE_VERSION);
+ pInfo->implRev =
+ KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+IN_FIRMWARE_INFO_OFFSET_IMPLEMENT_REV);
+ pInfo->versMajor =
+ (KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+IN_FIRMWARE_INFO_OFFSET_VERSION_MAJOR)) & 0x0f;
+ pInfo->versMinor =
+ (KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+IN_FIRMWARE_INFO_OFFSET_VERSION_MINSUB)>>4) & 0x0f;
+ pInfo->versSubMinor =
+ (KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+IN_FIRMWARE_INFO_OFFSET_VERSION_MINSUB)) & 0x0f;
+ pInfo->sdrRev =
+ KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+IN_FIRMWARE_INFO_OFFSET_SDR_REV);
+ pInfo->iana =
+ KWUM_GET_BYTE_AT_OFFSET(pBuf ,
+ offset+IN_FIRMWARE_INFO_OFFSET_IANA2) << 16;
+ pInfo->iana |=
+ (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+IN_FIRMWARE_INFO_OFFSET_IANA1) << 8;
+ pInfo->iana |=
+ (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
+ offset+IN_FIRMWARE_INFO_OFFSET_IANA0);
+
+ KfwumFixTableVersionForOldFirmware(pInfo);
+
+ status = KFWUM_STATUS_OK;
+ }
+ return(status);
+}
+
+
+void KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo * pInfo)
+{
+ switch(pInfo->boardId)
+ {
+ case KFWUM_BOARD_KONTRON_UNKNOWN:
+ pInfo->tableVers = 0xff;
+ break;
+ default:
+ /* pInfo->tableVers is already set for the right version */
+ break;
+ }
+}
+
+
+tKFWUM_Status KfwumValidFirmwareForBoard(tKFWUM_BoardInfo boardInfo,
+ tKFWUM_InFirmwareInfo firmInfo)
+{
+ tKFWUM_Status status = KFWUM_STATUS_OK;
+
+ if(boardInfo.iana != firmInfo.iana)
+ {
+ printf("Board IANA does not match firmware IANA\n");
+ status = KFWUM_STATUS_ERROR;
+ }
+
+ if(boardInfo.boardId != firmInfo.boardId)
+ {
+ printf("Board IANA does not match firmware IANA\n");
+ status = KFWUM_STATUS_ERROR;
+ }
+
+ if(status == KFWUM_STATUS_ERROR)
+ {
+ printf("Firmware invalid for target board. Download of upgrade aborted\n");
+ }
+ return status;
+}
+
+
+static void KfwumOutputInfo(tKFWUM_BoardInfo boardInfo,
+ tKFWUM_InFirmwareInfo firmInfo)
+{
+ printf("Target Board Id : %u\n",boardInfo.boardId);
+ printf("Target IANA number : %u\n",boardInfo.iana);
+ printf("File Size : %lu bytes\n",firmInfo.fileSize);
+ printf("Firmware Version : %d.%d%d SDR %d\n",firmInfo.versMajor,
+ firmInfo.versMinor, firmInfo.versSubMinor, firmInfo.sdrRev);
+}
+
+#ifdef METACOMMAND
+int i_fwum(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 '?':
+ KfwumOutputHelp();
+ return ERR_USAGE;
+ break;
+ }
+ for (i = 0; i < optind; i++) { argv++; argc--; }
+
+ rc = ipmi_fwum_main(intf, argc, argv);
+
+ ipmi_close_();
+ // show_outcome(progname,rc);
+ return rc;
+}
diff --git a/util/ifwum.h b/util/ifwum.h
new file mode 100644
index 0000000..e6c228c
--- /dev/null
+++ b/util/ifwum.h
@@ -0,0 +1,76 @@
+/*
+ * 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 <inttypes.h>
+// #include <ipmitool/ipmi.h>
+
+#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 */
diff --git a/util/igetevent.c b/util/igetevent.c
new file mode 100644
index 0000000..6e2fe27
--- /dev/null
+++ b/util/igetevent.c
@@ -0,0 +1,1439 @@
+/*
+ * 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 <arcress at users.sourceforge.net>
+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(DOS)
+#include <dos.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include "getopt.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.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>
+#include <unistd.h>
+#endif
+#include <pthread.h>
+#include <sys/utsname.h>
+#endif
+#include <string.h>
+#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
+ */
+static char * progname = "igetevent";
+static char * progver = "2.93";
+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,&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 <signal.h>
+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:or: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 '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();
+ 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 */
diff --git a/util/ihealth.c b/util/ihealth.c
new file mode 100644
index 0000000..6f6f0e1
--- /dev/null
+++ b/util/ihealth.c
@@ -0,0 +1,1153 @@
+/*
+ * 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
+ */
+/*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 <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "getopt.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"
+
+#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(char *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
+ */
+static char * progname = "ihealth";
+static char * progver = "2.93";
+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;
+}
+
+int get_lan_stats(uchar chan)
+{
+ uchar idata[2];
+ uchar rdata[20];
+ int rlen, rv;
+ uchar cc;
+ ushort *rw;
+
+ /* get BMC LAN Statistics */
+ idata[0] = chan;
+ idata[1] = 0x00; /*do not clear stats*/
+ rlen = sizeof(rdata);
+ rv = ipmi_cmd(GET_LAN_STATS, idata,2, rdata,&rlen, &cc, fdebug);
+ if (fdebug) printf("get_lan_stats: rv = %d, cc = %02x\n",rv,cc);
+ if (rv == 0) {
+ if (cc == 0) { /*success, show BMC LAN stats*/
+ rw = (ushort *)&rdata[0];
+ printf("IPMI LAN channel %d statistics: \n",chan);
+ printf(" \tReceived IP Packets %c %d\n",bdelim,rw[0]);
+ printf(" \tRecvd IP Header errors %c %d\n",bdelim,rw[1]);
+ printf(" \tRecvd IP Address errors %c %d\n",bdelim,rw[2]);
+ printf(" \tRecvd IP Fragments %c %d\n",bdelim,rw[3]);
+ printf(" \tTransmitted IP Packets %c %d\n",bdelim,rw[4]);
+ printf(" \tReceived UDP Packets %c %d\n",bdelim,rw[5]);
+ printf(" \tReceived Valid RMCP Pkts %c %d\n",bdelim,rw[6]);
+ printf(" \tReceived UDP Proxy Pkts %c %d\n",bdelim,rw[7]);
+ printf(" \tDropped UDP Proxy Pkts %c %d\n",bdelim,rw[8]);
+ } else if (cc == 0xc1) {
+ printf("IPMI LAN channel %d statistics: not supported\n",chan);
+ }
+ }
+ return(rv);
+}
+
+int get_session_info(uchar idx, int hnd, uchar *rdata, int *len)
+{
+ uchar idata[5];
+ int ilen, rlen, rv;
+ uchar cc;
+
+ ilen = 1;
+ idata[0] = idx;
+ if (idx == 0xFE) {
+ idata[1] = (uchar)hnd;
+ ilen = 2;
+ } else if (idx == 0xFF) {
+ idata[1] = (uchar)(hnd & 0x000000FF);
+ idata[2] = (uchar)((hnd & 0x0000FF00) >> 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 != 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)";
+ 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*/
+ if (prod == 0x0005) prodstr = "(UCS C200)";
+ else prodstr = "";
+ if (fipmilan) lan_ch_restrict = 1; /*fw bug, gets 0xC1 on ipmilan*/
+ 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]);
+ }
+ 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*/
+ 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 1643: prodstr = "(X9SRL)"; break; /*0x066b*/
+ case 1797: prodstr = "(X9DR7)"; break; /*0x0705*/
+ case 43025: prodstr = "(H8DGU)"; break;
+ case 43707: prodstr = "(X8DTH)"; 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;
+ default:
+ prodstr = "";
+ break;
+ } /*end switch(prod)*/
+ 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);
+ if (resp[0] == 60) /*normal*/ i = 1;
+ else {
+ i = 60 / resp[0];
+ hrs = hrs / i;
+ }
+ *val = hrs;
+ }
+ return(rc);
+}
+
+char *decode_selftest(int stat)
+{
+ uchar *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();
+ 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);
+ goto health_end;
+ } 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 */
diff --git a/util/ihpm.c b/util/ihpm.c
new file mode 100644
index 0000000..740ab74
--- /dev/null
+++ b/util/ihpm.c
@@ -0,0 +1,4003 @@
+/*
+ * 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 <windows.h>
+#include <winsock.h>
+#include <stdlib.h>
+#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 <arpa/inet.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <ctype.h> /*for toupper*/
+#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 <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+
+#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++<RETRY_COUNT_MAX))?TRUE:FALSE)
+#else
+#define HPMFWUPG_IS_RETRYABLE(error) FALSE
+#endif
+
+/*
+ * HPM FIRMWARE UPGRADE GENERAL DEFINITIONS
+ */
+
+#define HPMFWUPG_PICMG_IDENTIFIER 0
+#define HPMFWUPG_VERSION_SIZE 6
+#define HPMFWUPG_DESC_STRING_LENGTH 12
+#define HPMFWUPG_DEFAULT_INACCESS_TIMEOUT 60 /* sec */
+#define HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT 60 /* sec */
+#define HPMFWUPG_MD5_SIGNATURE_LENGTH 16
+
+/* Component IDs */
+typedef enum eHpmfwupgComponentId
+{
+ HPMFWUPG_COMPONENT_ID_0 = 0,
+ HPMFWUPG_COMPONENT_ID_1,
+ HPMFWUPG_COMPONENT_ID_2,
+ HPMFWUPG_COMPONENT_ID_3,
+ HPMFWUPG_COMPONENT_ID_4,
+ HPMFWUPG_COMPONENT_ID_5,
+ HPMFWUPG_COMPONENT_ID_6,
+ HPMFWUPG_COMPONENT_ID_7,
+ HPMFWUPG_COMPONENT_ID_MAX
+} tHpmfwupgComponentId;
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgComponentBitMask
+{
+ union
+ {
+ unsigned char byte;
+ struct
+ {
+ #ifdef WORDS_BIGENDIAN
+ unsigned char component7 : 1;
+ unsigned char component6 : 1;
+ unsigned char component5 : 1;
+ unsigned char component4 : 1;
+ unsigned char component3 : 1;
+ unsigned char component2 : 1;
+ unsigned char component1 : 1;
+ unsigned char component0 : 1;
+ #else
+ unsigned char component0 : 1;
+ unsigned char component1 : 1;
+ unsigned char component2 : 1;
+ unsigned char component3 : 1;
+ unsigned char component4 : 1;
+ unsigned char component5 : 1;
+ unsigned char component6 : 1;
+ unsigned char component7 : 1;
+ #endif
+ }ATTRIBUTE_PACKING bitField;
+ }ATTRIBUTE_PACKING ComponentBits;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+
+static const int HPMFWUPG_SUCCESS = 0;
+static const int HPMFWUPG_ERROR = -1;
+/* Upload firmware specific error codes */
+static const int HPMFWUPG_UPLOAD_BLOCK_LENGTH = 1;
+static const int HPMFWUPG_UPLOAD_RETRY = 2;
+
+
+/*
+ * TARGET UPGRADE CAPABILITIES DEFINITIONS
+ */
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetTargetUpgCapabilitiesReq
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetTargetUpgCapabilitiesResp
+{
+ unsigned char picmgId;
+ unsigned char hpmVersion;
+ union
+ {
+ unsigned char byte;
+ struct
+ {
+ #if WORDS_BIGENDIAN
+ unsigned char fwUpgUndesirable : 1;
+ unsigned char autRollbackOverride : 1;
+ unsigned char ipmcDegradedDurinUpg: 1;
+ unsigned char deferActivation : 1;
+ unsigned char servAffectDuringUpg : 1;
+ unsigned char manualRollback : 1;
+ unsigned char autRollback : 1;
+ unsigned char ipmcSelftestCap : 1;
+ #else
+ unsigned char ipmcSelftestCap : 1;
+ unsigned char autRollback : 1;
+ unsigned char manualRollback : 1;
+ unsigned char servAffectDuringUpg : 1;
+ unsigned char deferActivation : 1;
+ unsigned char ipmcDegradedDurinUpg: 1;
+ unsigned char autRollbackOverride : 1;
+ unsigned char fwUpgUndesirable : 1;
+ #endif
+ }ATTRIBUTE_PACKING bitField;
+ }ATTRIBUTE_PACKING GlobalCapabilities;
+ unsigned char upgradeTimeout;
+ unsigned char selftestTimeout;
+ unsigned char rollbackTimeout;
+ unsigned char inaccessTimeout;
+ struct HpmfwupgComponentBitMask componentsPresent;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetTargetUpgCapabilitiesCtx
+{
+ struct HpmfwupgGetTargetUpgCapabilitiesReq req;
+ struct HpmfwupgGetTargetUpgCapabilitiesResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * COMPONENT PROPERTIES DEFINITIONS
+ */
+
+typedef enum eHpmfwupgCompPropertiesSelect
+{
+ HPMFWUPG_COMP_GEN_PROPERTIES = 0,
+ HPMFWUPG_COMP_CURRENT_VERSION,
+ HPMFWUPG_COMP_DESCRIPTION_STRING,
+ HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION,
+ HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION,
+ HPMFWUPG_COMP_RESERVED,
+ HPMFWUPG_COMP_OEM_PROPERTIES = 192
+} tHpmfwupgCompPropertiesSelect;
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetComponentPropertiesReq
+{
+ unsigned char picmgId;
+ unsigned char componentId;
+ unsigned char selector;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetGeneralPropResp
+{
+ unsigned char picmgId;
+ union
+ {
+ unsigned char byte;
+ struct
+ {
+ #if WORDS_BIGENDIAN
+ unsigned char reserved : 2;
+ unsigned char payloadColdReset : 1;
+ unsigned char deferredActivation : 1;
+ unsigned char comparisonSupport : 1;
+ unsigned char preparationSupport : 1;
+ unsigned char rollbackBackup : 2;
+ #else
+ unsigned char rollbackBackup : 2;
+ unsigned char preparationSupport : 1;
+ unsigned char comparisonSupport : 1;
+ unsigned char deferredActivation : 1;
+ unsigned char payloadColdReset : 1;
+ unsigned char reserved : 2;
+ #endif
+ }ATTRIBUTE_PACKING bitfield;
+ }ATTRIBUTE_PACKING GeneralCompProperties;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetCurrentVersionResp
+{
+ unsigned char picmgId;
+ unsigned char currentVersion[HPMFWUPG_VERSION_SIZE];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetDescStringResp
+{
+ unsigned char picmgId;
+ char descString[HPMFWUPG_DESC_STRING_LENGTH];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetRollbackFwVersionResp
+{
+ unsigned char picmgId;
+ unsigned char rollbackFwVersion[HPMFWUPG_VERSION_SIZE];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetDeferredFwVersionResp
+{
+ unsigned char picmgId;
+ unsigned char deferredFwVersion[HPMFWUPG_VERSION_SIZE];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * GetComponentProperties - OEM properties (192)
+ */
+#define HPMFWUPG_OEM_LENGTH 4
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetOemProperties
+{
+ unsigned char picmgId;
+ unsigned char oemRspData[HPMFWUPG_OEM_LENGTH];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetComponentPropertiesResp
+{
+ union
+ {
+ struct HpmfwupgGetGeneralPropResp generalPropResp;
+ struct HpmfwupgGetCurrentVersionResp currentVersionResp;
+ struct HpmfwupgGetDescStringResp descStringResp;
+ struct HpmfwupgGetRollbackFwVersionResp rollbackFwVersionResp;
+ struct HpmfwupgGetDeferredFwVersionResp deferredFwVersionResp;
+ struct HpmfwupgGetOemProperties oemProperties;
+ }ATTRIBUTE_PACKING Response;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetComponentPropertiesCtx
+{
+ struct HpmfwupgGetComponentPropertiesReq req;
+ struct HpmfwupgGetComponentPropertiesResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+
+/*
+ * ABORT UPGRADE DEFINITIONS
+ */
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgAbortUpgradeReq
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgAbortUpgradeResp
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgAbortUpgradeCtx
+{
+ struct HpmfwupgAbortUpgradeReq req;
+ struct HpmfwupgAbortUpgradeResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * UPGRADE ACTIONS DEFINITIONS
+ */
+typedef enum eHpmfwupgUpgradeAction
+{
+ HPMFWUPG_UPGRADE_ACTION_BACKUP = 0,
+ HPMFWUPG_UPGRADE_ACTION_PREPARE,
+ HPMFWUPG_UPGRADE_ACTION_UPGRADE,
+ HPMFWUPG_UPGRADE_ACTION_COMPARE,
+ HPMFWUPG_UPGRADE_ACTION_INVALID = 0xff
+} tHpmfwupgUpgradeAction;
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgInitiateUpgradeActionReq
+{
+ unsigned char picmgId;
+ struct HpmfwupgComponentBitMask componentsMask;
+ unsigned char upgradeAction;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgInitiateUpgradeActionResp
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgInitiateUpgradeActionCtx
+{
+ struct HpmfwupgInitiateUpgradeActionReq req;
+ struct HpmfwupgInitiateUpgradeActionResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * UPLOAD FIRMWARE BLOCK DEFINITIONS
+ */
+
+#define HPMFWUPG_SEND_DATA_COUNT_MAX 256
+#define HPMFWUPG_SEND_DATA_COUNT_KCS 30
+#define HPMFWUPG_SEND_DATA_COUNT_LAN 25
+#define HPMFWUPG_SEND_DATA_COUNT_IPMB 26
+#define HPMFWUPG_SEND_DATA_COUNT_IPMBL 26
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgUploadFirmwareBlockReq
+{
+ unsigned char picmgId;
+ unsigned char blockNumber;
+ unsigned char data[HPMFWUPG_SEND_DATA_COUNT_MAX];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgUploadFirmwareBlockResp
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgUploadFirmwareBlockCtx
+{
+ struct HpmfwupgUploadFirmwareBlockReq req;
+ struct HpmfwupgUploadFirmwareBlockResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+
+/*
+ * FINISH FIRMWARE UPLOAD DEFINITIONS
+ */
+
+#define HPMFWUPG_IMAGE_SIZE_BYTE_COUNT 4
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgFinishFirmwareUploadReq
+{
+ unsigned char picmgId;
+ unsigned char componentId;
+ unsigned char imageLength[HPMFWUPG_IMAGE_SIZE_BYTE_COUNT];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgFinishFirmwareUploadResp
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgFinishFirmwareUploadCtx
+{
+ struct HpmfwupgFinishFirmwareUploadReq req;
+ struct HpmfwupgFinishFirmwareUploadResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * ACTIVATE FW DEFINITIONS
+ */
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgActivateFirmwareReq
+{
+ unsigned char picmgId;
+ unsigned char rollback_override;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgActivateFirmwareResp
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgActivateFirmwareCtx
+{
+ struct HpmfwupgActivateFirmwareReq req;
+ struct HpmfwupgActivateFirmwareResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+
+/*
+ * GET UPGRADE STATUS DEFINITIONS
+ */
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetUpgradeStatusReq
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetUpgradeStatusResp
+{
+ unsigned char picmgId;
+ unsigned char cmdInProcess;
+ unsigned char lastCmdCompCode;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetUpgradeStatusCtx
+{
+ struct HpmfwupgGetUpgradeStatusReq req;
+ struct HpmfwupgGetUpgradeStatusResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * MANUAL FW ROLLBACK DEFINITIONS
+ */
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgManualFirmwareRollbackReq
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgManualFirmwareRollbackResp
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+struct HpmfwupgManualFirmwareRollbackCtx
+{
+ struct HpmfwupgManualFirmwareRollbackReq req;
+ struct HpmfwupgManualFirmwareRollbackResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * QUERY ROLLBACK STATUS DEFINITIONS
+ */
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgQueryRollbackStatusReq
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgQueryRollbackStatusResp
+{
+ unsigned char picmgId;
+ struct HpmfwupgComponentBitMask rollbackComp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgQueryRollbackStatusCtx
+{
+ struct HpmfwupgQueryRollbackStatusReq req;
+ struct HpmfwupgQueryRollbackStatusResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * QUERY SELF TEST RESULT DEFINITIONS
+ */
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgQuerySelftestResultReq
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgQuerySelftestResultResp
+{
+ unsigned char picmgId;
+ unsigned char result1;
+ unsigned char result2;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgQuerySelftestResultCtx
+{
+ struct HpmfwupgQuerySelftestResultReq req;
+ struct HpmfwupgQuerySelftestResultResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+/*
+ * HPM.1 IMAGE DEFINITIONS
+ */
+
+#define HPMFWUPG_HEADER_SIGNATURE_LENGTH 8
+#define HPMFWUPG_MANUFATURER_ID_LENGTH 3
+#define HPMFWUPG_PRODUCT_ID_LENGTH 2
+#define HPMFWUPG_TIME_LENGTH 4
+#define HPMFWUPG_TIMEOUT_LENGTH 1
+#define HPMFWUPG_COMP_REVISION_LENGTH 2
+#define HPMFWUPG_FIRM_REVISION_LENGTH 6
+#define HPMFWUPG_IMAGE_HEADER_VERSION 0
+#define HPMFWUPG_IMAGE_SIGNATURE "PICMGFWU"
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgImageHeader
+{
+ char signature[HPMFWUPG_HEADER_SIGNATURE_LENGTH];
+ unsigned char formatVersion;
+ unsigned char deviceId;
+ unsigned char manId[HPMFWUPG_MANUFATURER_ID_LENGTH];
+ unsigned char prodId[HPMFWUPG_PRODUCT_ID_LENGTH];
+ unsigned char time[HPMFWUPG_TIME_LENGTH];
+ union
+ {
+ struct
+ {
+ #if WORDS_BIGENDIAN
+ unsigned char imageSelfTest : 1;
+ unsigned char autRollback : 1;
+ unsigned char manRollback : 1;
+ unsigned char servAffected : 1;
+ unsigned char reserved : 4;
+ #else
+ unsigned char reserved : 4;
+ unsigned char servAffected : 1;
+ unsigned char manRollback : 1;
+ unsigned char autRollback : 1;
+ unsigned char imageSelfTest : 1;
+ #endif
+ } ATTRIBUTE_PACKING bitField;
+ unsigned char byte;
+ }ATTRIBUTE_PACKING imageCapabilities;
+ struct HpmfwupgComponentBitMask components;
+ unsigned char selfTestTimeout;
+ unsigned char rollbackTimeout;
+ unsigned char inaccessTimeout;
+ unsigned char compRevision[HPMFWUPG_COMP_REVISION_LENGTH];
+ unsigned char firmRevision[HPMFWUPG_FIRM_REVISION_LENGTH];
+ unsigned short oemDataLength;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+
+#define HPMFWUPG_DESCRIPTION_LENGTH 21
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgActionRecord
+{
+ unsigned char actionType;
+ struct HpmfwupgComponentBitMask components;
+ unsigned char checksum;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#define HPMFWUPG_FIRMWARE_SIZE_LENGTH 4
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgFirmwareImage
+{
+ unsigned char version[HPMFWUPG_FIRM_REVISION_LENGTH];
+ char desc[HPMFWUPG_DESCRIPTION_LENGTH];
+ unsigned char length[HPMFWUPG_FIRMWARE_SIZE_LENGTH];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgUpgradeCtx
+{
+ struct HpmfwupgComponentBitMask compUpdateMask;
+ unsigned int imageSize;
+ unsigned char* pImageData;
+ unsigned char componentId;
+ struct HpmfwupgGetTargetUpgCapabilitiesResp targetCap;
+ struct HpmfwupgGetGeneralPropResp genCompProp[HPMFWUPG_COMPONENT_ID_MAX];
+ struct ipm_devid_rsp devId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+typedef enum eHpmfwupgActionType
+{
+ HPMFWUPG_ACTION_BACKUP_COMPONENTS = 0,
+ HPMFWUPG_ACTION_PREPARE_COMPONENTS,
+ HPMFWUPG_ACTION_UPLOAD_FIRMWARE,
+ HPMFWUPG_ACTION_RESERVED = 0xFF
+} tHpmfwupgActionType;
+
+/*
+ * FUNCTIONS PROTOTYPES
+ */
+#define HPMFWUPG_MAJORMINOR_VERSION_SIZE 2
+
+
+#define DEFAULT_COMPONENT_UPLOAD 0x0F
+
+/*
+ * Options added for user to check the version and to view both the FILE and TARGET Version
+ */
+#define VERSIONCHECK_MODE 0x01
+#define VIEW_MODE 0x02
+#define DEBUG_MODE 0x04
+#define FORCE_MODE_ALL 0x08
+#define FORCE_MODE_COMPONENT 0x10
+#define FORCE_MODE (FORCE_MODE_ALL|FORCE_MODE_COMPONENT)
+
+typedef struct _VERSIONINFO
+{
+ unsigned char componentId;
+ unsigned char targetMajor;
+ unsigned char targetMinor;
+ unsigned char targetAux[4];
+ unsigned char rollbackMajor;
+ unsigned char rollbackMinor;
+ unsigned char rollbackAux[4];
+ unsigned char imageMajor;
+ unsigned char imageMinor;
+ unsigned char imageAux[4];
+ unsigned char coldResetRequired;
+ unsigned char rollbackSupported;
+ unsigned char skipUpgrade;
+ char descString[15];
+}VERSIONINFO, *PVERSIONINFO;
+
+VERSIONINFO gVersionInfo[HPMFWUPG_COMPONENT_ID_MAX];
+
+#define TARGET_VER (0x01)
+#define ROLLBACK_VER (0x02)
+#define IMAGE_VER (0x04)
+
+
+
+
+static int HpmfwupgPreUpgradeCheck(void *intf,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx,int componentToUpload,int option);
+static int HpmfwupgUpgrade(void *intf, char* imageFilename, int activate, int,int);
+static int HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgPreparationStage( void *intf,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx, int option);
+static int HpmfwupgUpgradeStage ( void *intf,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx, int compToUpload ,int option);
+static int HpmfwupgActivationStage(void *intf,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgGetTargetUpgCapabilities(void *intf,
+ struct HpmfwupgGetTargetUpgCapabilitiesCtx* pCtx);
+static int HpmfwupgGetComponentProperties(void *intf,
+ struct HpmfwupgGetComponentPropertiesCtx* pCtx);
+static int HpmfwupgQuerySelftestResult(void *intf,
+ struct HpmfwupgQuerySelftestResultCtx* pCtx,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgQueryRollbackStatus(void *intf,
+ struct HpmfwupgQueryRollbackStatusCtx* pCtx,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgAbortUpgrade(void *intf,
+ struct HpmfwupgAbortUpgradeCtx* pCtx);
+static int HpmfwupgInitiateUpgradeAction(void *intf,
+ struct HpmfwupgInitiateUpgradeActionCtx* pCtx,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgUploadFirmwareBlock(void *intf,
+ struct HpmfwupgUploadFirmwareBlockCtx* pCtx,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx, int count ,
+ unsigned int *pOffset, unsigned int *blockLen);
+static int HpmfwupgFinishFirmwareUpload(void *intf,
+ struct HpmfwupgFinishFirmwareUploadCtx* pCtx,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgActivateFirmware(void *intf,
+ struct HpmfwupgActivateFirmwareCtx* pCtx,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgGetUpgradeStatus(void *intf,
+ struct HpmfwupgGetUpgradeStatusCtx* pCtxstruct,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgManualFirmwareRollback(void *intf,
+ struct HpmfwupgManualFirmwareRollbackCtx* pCtx,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static void HpmfwupgPrintUsage(void);
+static unsigned char HpmfwupgCalculateChecksum(unsigned char* pData, unsigned int length);
+static int HpmfwupgGetDeviceId(void *intf, struct ipm_devid_rsp* pGetDevId);
+static int HpmfwupgGetBufferFromFile(char* imageFilename, struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgWaitLongDurationCmd(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx);
+
+static struct ipmi_rs * HpmfwupgSendCmd(void *intf, struct ipmi_rq req,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+
+
+static int HpmFwupgActionUploadFirmware
+(
+ struct HpmfwupgComponentBitMask components,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx,
+ unsigned char** pImagePtr,
+ int componentToUpload,
+ void *intf,
+ int option,
+ int* pFlagColdReset
+);
+
+static char * hpm_decode_cc( uchar cmd, uchar cc )
+{
+ char *pstr;
+ switch(cc) {
+ case 0x80: pstr = "Command in progress"; break;
+ case 0x81: pstr = "HPM not supported"; break;
+ case 0x82: pstr = "Checksum error"; break;
+ case 0x83: pstr = "Firmware mismatch"; break;
+ default: pstr = decode_cc(cmd,cc);
+ }
+ return(pstr);
+}
+
+/****************************************************************************
+*
+* Function Name: HpmGetuserInput
+*
+* Description: This function gets input from user and returns TRUE if its Yes
+* or FALSE if its No
+*
+*****************************************************************************/
+int HpmGetUserInput(char *str)
+{
+ char userInput[2];
+ printf("%s",str);
+ scanf("%s",userInput);
+ if (toupper(userInput[0]) == 'Y')
+ {
+ return 1;
+ }
+ return 0;
+}
+/****************************************************************************
+*
+* Function Name: HpmDisplayLine
+*
+* Description: This is to display the line with the given character.
+*
+*****************************************************************************/
+void HpmDisplayLine(char *s, int n)
+{
+ while (n--) printf ("%c",*s);
+ printf("\n");
+}
+
+/****************************************************************************
+*
+* Function Name: HpmDisplayUpgradeHeader
+*
+* Description: This function the displays the Upgrade header information
+*
+*****************************************************************************/
+void HpmDisplayUpgradeHeader(int option)
+{
+ printf("\n");
+ HpmDisplayLine("-",78 );
+ printf("|ID | Name | Versions | %% |\n");
+ printf("| | | Active | Backup | File | |\n");
+ printf("|---|-----------|-----------------|-----------------|-----------------|------|\n");
+}
+
+/****************************************************************************
+*
+* Function Name: HpmDisplayUpgrade
+*
+* Description: This function displays the progress of the upgrade it prints the "."
+* every 5% of its completion.
+*
+*****************************************************************************/
+void HpmDisplayUpgrade( int skip, unsigned int totalSent,
+ unsigned int displayFWLength,time_t timeElapsed)
+{
+ int percent;
+ static int old_percent=1;
+ if (skip)
+ {
+ printf(" Skip |\n");
+ return;
+ }
+ fflush(stdout);
+
+ percent = (int)((totalSent * 100)/displayFWLength);
+ if (percent != old_percent)
+ {
+ if ( percent == 0 ) printf(" 0 %% |");
+ else if (percent == 100) printf("\b\b\b\b\b\b\b100 %% |\n");
+ else printf("\b\b\b\b\b\b\b%3d %% |", percent);
+ old_percent = percent;
+ }
+
+ if (totalSent== displayFWLength)
+ {
+ /* Display the time taken to complete the upgrade */
+ printf("| | Upload Time: %02d.%02d | Image Size: %05x |\n",
+ timeElapsed/60,timeElapsed%60,totalSent);
+ }
+}
+
+/****************************************************************************
+*
+* Function Name: HpmDisplayVersionHeader
+*
+* Description: This function displays the information about version header
+*
+*****************************************************************************/
+int HpmDisplayVersionHeader(int mode)
+{
+ if ( mode & IMAGE_VER)
+ {
+ HpmDisplayLine("-",71 );
+ printf("|ID | Name | Versions |\n");
+ printf("| | | Active | Backup | File |\n");
+ HpmDisplayLine("-",71 );
+ }
+ else
+ {
+ HpmDisplayLine("-",53 );
+ printf("|ID | Name | Versions |\n");
+ printf("| | | Active | Backup |\n");
+ HpmDisplayLine("-",53 );
+ }
+ return 0;
+}
+
+/****************************************************************************
+*
+* Function Name: HpmDisplayVersion
+*
+* Description: This function displays the version of the image and target
+*
+*****************************************************************************/
+int HpmDisplayVersion(int mode,VERSIONINFO *pVersion)
+{
+ char descString[12];
+ memset(&descString,0x00,12);
+ /*
+ * Added this to ensure that even if the description string
+ * is more than required it does not give problem in displaying it
+ */
+ strncpy(descString,pVersion->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<<componentToUpload & pActionRecord->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<<componentId;
+ }
+ if (option & VIEW_MODE)
+ {
+ HpmDisplayVersion(mode,pVersionInfo);
+ printf("\n");
+ }
+ pImagePtr = pData + firmwareLength;
+ }
+ break;
+ default:
+ lprintf(LOG_NOTICE," Invalid Action type. Cannot continue");
+ rc = HPMFWUPG_ERROR;
+ break;
+ }
+ }
+ }
+ if (option & VIEW_MODE)
+ {
+ HpmDisplayLine("-",71);
+ if (flagColdReset)
+ {
+ fflush(stdout);
+ lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset");
+ }
+ }
+ return rc;
+}
+
+
+/****************************************************************************
+*
+* Function Name: HpmfwupgUpgradeStage
+*
+* Description: This function the upgrade stage of a firmware upgrade
+* procedure as defined in section 3.3 of the IPM Controller
+* Firmware Upgrade Specification version 1.0
+*
+*****************************************************************************/
+int HpmfwupgUpgradeStage(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx,
+ int componentToUpload, int option)
+{
+ struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*)
+ pFwupgCtx->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 <file> - 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 <file> - Upgrade the firmware using a valid HPM.1 image <file>");
+ 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 <file> 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 <file> component x - Upgrade only component <x> from the given <file>");
+ lprintf(LOG_NOTICE," component 0 - BOOT");
+ lprintf(LOG_NOTICE," component 1 - RTK");
+ lprintf(LOG_NOTICE,"upgrade <file> activate - Upgrade the firmware using a valid HPM.1 image <file>");
+ 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 <id> <select> - Get the specified component properties");
+ lprintf(LOG_NOTICE," Valid component <ID> 0-7 ");
+ lprintf(LOG_NOTICE," Properties <select> 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 <filename> */
+ 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 <filename> all */
+ if (strcmp(argv[i],"all") == 0)
+ {
+ option &= ~(VERSIONCHECK_MODE);
+ option &= ~(VIEW_MODE);
+ option |= FORCE_MODE_ALL;
+ }
+ /* hpm upgrade <filename> component <comp Id> */
+ 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 */
+
diff --git a/util/ihpm.h b/util/ihpm.h
new file mode 100644
index 0000000..00d6dc9
--- /dev/null
+++ b/util/ihpm.h
@@ -0,0 +1,117 @@
+/*
+ * 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_HPMFWUPG_H
+#define IPMI_HPMFWUPG_H
+
+#define IPMI_BUF_SIZE 1024
+#ifdef HAVE_LANPLUS
+#include "../lib/lanplus/lanplus_defs.h"
+#else
+#define _IPMI_RS_
+struct ipmi_rs {
+ uint8_t ccode;
+ uint8_t data[IPMI_BUF_SIZE];
+
+ /*
+ * Looks like this is the length of the entire packet, including the RMC
+P
+ * stuff, then modified to be the length of the extra IPMI message data
+ */
+ int data_len;
+
+ struct {
+ uint8_t netfn;
+ uint8_t cmd;
+ uint8_t seq;
+ uint8_t lun;
+ } msg;
+ struct {
+ uint8_t authtype;
+ uint32_t seq;
+ uint32_t id;
+ uint8_t bEncrypted; /* IPMI v2 only */
+ uint8_t bAuthenticated; /* IPMI v2 only */
+ uint8_t payloadtype; /* IPMI v2 only */
+ uint16_t msglen;
+ } session;
+};
+#endif
+
+#define TRUE 1
+#define FALSE 0
+
+#define IPMI_NETFN_APP 0x06
+#define IPMI_NETFN_PICMG 0x2C
+
+#define IPMI_BMC_SLAVE_ADDR 0x20
+
+#define BMC_GET_DEVICE_ID 0x1
+
+#define IPMI_CC_OK 0x00
+#define IPMI_CC_REQ_DATA_INV_LENGTH 0xc7
+
+#define ATTRIBUTE_PACKING /* */
+#define PRAGMA_PACK 1
+
+#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];
+};
+#pragma pack()
+
+typedef struct md5_state_s {
+ uint count[2]; /* message length in bits, lsw first */
+ uint abcd[4]; /* digest buffer */
+ uchar buf[64]; /* accumulate block */
+} md5_state_t;
+
+void md5_init(md5_state_t *pms); /*md5.c*/
+void md5_append(md5_state_t *pms, const uchar *data, int nbytes); /*md5.c*/
+void md5_finish(md5_state_t *pms, uchar digest[16]); /*md5.c*/
+
+void lprintf(int level, const char * format, ...); /*ipmilanplus.c*/
+void set_loglevel(int level);
+char * get_mfg_str(uchar *rgmfg, int *pmfg);
+ushort buf2short(uchar * buf);
+
+int ipmi_hpmfwupg_main(void *, int, char **);
+
+#endif /* IPMI_KFWUM_H */
diff --git a/util/ilan.c b/util/ilan.c
new file mode 100644
index 0000000..a1ed76a
--- /dev/null
+++ b/util/ilan.c
@@ -0,0 +1,5149 @@
+/*---------------------------------------------------------------------------
+ * 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 <winsock2.h>
+#include <iphlpapi.h>
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "getopt.h"
+#elif defined(DOS)
+#include <dos.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+#else
+/* Linux or similar */
+#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
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <errno.h>
+#endif
+#ifdef LINUX
+#include <unistd.h>
+#endif
+#ifdef SOLARIS
+#include <sys/sockio.h>
+#define SIOCGIFHWADDR SIOCGENADDR
+#define ifr_netmask ifr_ifru.ifru_addr
+// #define ifr_hwaddr.sa_data ifr_ifru.ifru_enaddr
+#elif defined(BSD)
+#include <sys/sockio.h>
+#define SIOCGIFHWADDR SIOCGIFMAC
+#define ifr_netmask ifr_ifru.ifru_addr
+// #define ifr_hwaddr.sa_data ifr_ifru.ifru_addr
+#elif defined(MACOS)
+#include <sys/sockio.h>
+#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
+ */
+static char * progver = "2.93";
+static char * progname = "ilan";
+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 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 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 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 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 lan_access = 0x04; /* usu 4=Admin, 3=Operator, 2=User */
+static uchar lan_user = 0x02; /* if -u specified, use user 2 for lan */
+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 lan_ch = LAN_CH;
+static uchar lan_ch_parm = PARM_INIT;
+static uchar gcm_ch = PARM_INIT;
+static uchar vlan_enable = PARM_INIT;
+static uchar failover_enable = PARM_INIT;
+static uchar vlan_prio = 0; /*default = 0*/
+static ushort vlan_id = 0; /*max 12 bits used*/
+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)
+{
+ 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 responseData[MAX_BUFFER_SIZE];
+ int responseLength = MAX_BUFFER_SIZE;
+ int status, i, psw_len;
+ uchar completionCode;
+ char 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 {
+ inputData[0] = (uchar)unum;
+ memset(&inputData[1],0,16);
+ if (uname != NULL)
+ 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; /*user 1 = null user */
+ 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;
+ }
+
+ inputData[0] = (uchar)unum; /*user 1 = null user */
+ inputData[1] = 0x02; /*set password*/
+ psw_len = PSW_LEN; /*=16 change if 20-byte passwords supported */
+ memset(&inputData[2],0,psw_len);
+ if (upswd != NULL)
+ strcpy(&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(&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 | lan_ch; /* = 0x97 */
+ inputData[1] = (uchar)unum; /* user num */
+ inputData[2] = lan_access; /* usu 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)
+{
+ int ret = 0;
+ /* if the user specified a username or password, set it. */
+ if ((fpassword) || (uname != NULL)) {
+ ret = SetPasswd(unum, uname,passwd); /*set username and password*/
+ }
+ return(ret);
+} /*end SetUser()*/
+
+int
+DisableUser(int unum)
+{
+ uchar responseData[MAX_BUFFER_SIZE];
+ int responseLength = MAX_BUFFER_SIZE;
+ int status;
+ uchar completionCode;
+ char inputData[24];
+
+ inputData[0] = 0x80 | lan_ch; /* = 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);
+}
+
+static 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";
+ }
+ 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;
+}
+
+int GetUser(uchar user_num)
+{
+ uchar responseData[MAX_BUFFER_SIZE];
+ int responseLength = MAX_BUFFER_SIZE;
+ int status;
+ uchar completionCode;
+ char inputData[24];
+
+ inputData[0] = 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 ", lan_ch, user_num,
+ pspace2,bdelim);
+ else
+ SELprintf("User Access(chan%d,user%d): %02x %02x %02x %02x : ",
+ lan_ch, 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",
+ lan_ch, user_num, status, completionCode);
+ return(status);
+} /*end GetUser()*/
+
+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;
+}
+
+/*
+ * Set 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 <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <ctype.h>
+#include <sys/stropts.h>
+#include <sys/poll.h>
+#include <sys/dlpi.h>
+
+#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 = 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)
+{
+ 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 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 /* 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);
+ 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 = &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 = &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;
+ int nciphers = 16;
+ char mystr[80];
+ char fpefok = 1;
+ uchar * pc; int sz;
+
+ // 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:P: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 '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");
+ print_lan_opt_usage();
+ 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 = GetDeviceID( &LanRecord);
+ 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;
+ else if (ipmi_maj == 1 && ipmi_min < 5) fIPMI10 = 1;
+ else fIPMI10 = 0; /* >= IPMI 1.5 is ok */
+ if (ipmi_maj >= 2) fIPMI20 = 1;
+ 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 */
+ // fIPMI10 = 1;
+ // ipmi_close_();
+ // exit(1);
+ }
+ 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;
+ 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);
+ 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 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
+ char *pa;
+ 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) pc = "enabled";
+ else pc = "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), pc,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 == 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++) printf("%2d ",pc[i]);
+ } else if (ival == 24) { /*Cipher Suite Privi Levels*/
+ 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];
+ 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) { /*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\n",ret);
+ }
+ for (i = 1; i <= show_users; i++)
+ GetUser((uchar)i);
+
+ 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); /*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++;
+ ret = SetUser(lan_user,myuser,passwordData);
+ 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.\n");
+
+ /* 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);
+ } 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 */
+ 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(&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) {
+ 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 */
diff --git a/util/imb_api.h b/util/imb_api.h
new file mode 100644
index 0000000..56a940c
--- /dev/null
+++ b/util/imb_api.h
@@ -0,0 +1,708 @@
+/*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
+
+#ifndef NULL
+#define NULL 0
+#endif
+#define TRUE 1
+#define FALSE 0
+
+#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
+ // defined(LINUX) | defined(SOLARIS)
+#ifndef _WCHAR_T
+#define _WCHAR_T
+typedef long wchar_t;
+#endif
+#endif
+
+#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;
+typedef wchar_t WCHAR;
+typedef WCHAR *PWCHAR, *PWSTR;
+typedef CONST WCHAR *LPCWSTR, *PCWSTR;
+
+/*
+ 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;
+ PWSTR Buffer;
+} UNICODE_STRING;
+typedef UNICODE_STRING *PUNICODE_STRING;
+#define UNICODE_NULL ((WCHAR)0) /* winnt*/
+#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 <win2000ddk>\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 <sys/types.h>
+#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__ */
diff --git a/util/imbapi.c b/util/imbapi.c
new file mode 100644
index 0000000..cbc8fa1
--- /dev/null
+++ b/util/imbapi.c
@@ -0,0 +1,2594 @@
+/*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 <windows.h>
+#include <stdio.h>
+#define uint unsigned int
+
+#else /* LINUX, SCO_UW, UNIX */
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#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 <stdarg.h>
+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=%d 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=%d 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)
+#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=%d 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=%d 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=%d 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 %x!=%x\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=%d sizeint=%d\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*/
diff --git a/util/ipicmg.c b/util/ipicmg.c
new file mode 100644
index 0000000..c549151
--- /dev/null
+++ b/util/ipicmg.c
@@ -0,0 +1,1911 @@
+/*
+ * 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 <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.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 "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 */
+static char * progname = "ipicmg";
+static char * progver = "2.93";
+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;
+
+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<PICMG_MAX_LINK_PER_CHANNEL;index++){
+ if( rsp_len > (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<PICMG_AMC_MAX_LINK_PER_CHANNEL;index++){
+
+ if( rsp_len > (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: %d\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: %d\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 <FRU-ID> <OPTION>\n");
+ printf(" OPTION:\n");
+ printf(" 0 - Cold Reset\n");
+ printf(" 1 - Warm Reset\n");
+ printf(" 2 - Graceful Reboot\n");
+ printf(" 3 - Issue Diagnostic Interrupt\n");
+ printf(" 4 - Quiesce [AMC only]\n");
+ printf(" 5-255 - Reserved\n");
+
+ rc = -1;
+ }
+
+ }
+
+ /* fru activation command */
+ else if (!strncmp(argv[0], "activate", 8)) {
+ if (argc > 1) {
+ rc = ipmi_picmg_fru_activation(intf, argc-1, &(argv[1]), PICMG_FRU_ACTIVATE);
+ }
+ else {
+ printf("specify the FRU to activate\n");
+ rc = -1;
+ }
+ }
+
+ /* fru deactivation command */
+ else if (!strncmp(argv[0], "deactivate", 10)) {
+ if (argc > 1) {
+ rc = ipmi_picmg_fru_activation(intf, argc-1, &(argv[1]), PICMG_FRU_DEACTIVATE);
+ }else {
+ printf("specify the FRU to deactivate\n");
+ rc = -1;
+ }
+ }
+
+ /* activation policy command */
+ else if (!strncmp(argv[0], "policy", 6)) {
+ if (argc > 1) {
+ if (!strncmp(argv[1], "get", 3)) {
+ if (argc > 2) {
+ rc = ipmi_picmg_fru_activation_policy_get(intf, argc-1, &(argv[2]));
+ } else {
+ printf("usage: get <fruid>\n");
+ }
+ } else if (!strncmp(argv[1], "set", 3)) {
+ if (argc > 4) {
+ rc = ipmi_picmg_fru_activation_policy_set(intf, argc-1, &(argv[2]));
+ } else {
+ printf("usage: set <fruid> <lockmask> <lock>\n");
+ printf(" lockmask: [1] affect the deactivation locked bit\n");
+ printf(" [0] affect the activation locked bit\n");
+ printf(" lock: [1] set/clear deactivation locked\n");
+ printf(" [0] set/clear locked \n");
+ }
+ }
+ else {
+ printf("specify fru\n");
+ rc = -1;
+ }
+ } else {
+ printf("wrong parameters\n");
+ rc = -1;
+ }
+ }
+
+ /* portstate command */
+ else if (!strncmp(argv[0], "portstate", 9)) {
+
+ if (fdebug) printf("PICMG: portstate API");
+
+ if (argc > 1) {
+ if (!strncmp(argv[1], "get", 3)) {
+
+ int iface;
+ int channel;
+
+ if (fdebug) printf("PICMG: get");
+
+ if(!strncmp(argv[1], "getall", 6)) {
+ for(iface=0;iface<=PICMG_EKEY_MAX_INTERFACE;iface++) {
+ for(channel=1;channel<=PICMG_EKEY_MAX_CHANNEL;channel++) {
+ if(!(( iface == FRU_PICMGEXT_DESIGN_IF_FABRIC ) &&
+ ( channel > PICMG_EKEY_MAX_FABRIC_CHANNEL ) ))
+ {
+ rc = ipmi_picmg_portstate_get(intf,iface,(uchar)channel,
+ PICMG_EKEY_MODE_PRINT_ALL);
+ }
+ }
+ }
+ }
+ else if(!strncmp(argv[1], "getgranted", 10)) {
+ for(iface=0;iface<=PICMG_EKEY_MAX_INTERFACE;iface++) {
+ for(channel=1;channel<=PICMG_EKEY_MAX_CHANNEL;channel++) {
+ rc = ipmi_picmg_portstate_get(intf,iface,(uchar)channel,
+ PICMG_EKEY_MODE_PRINT_ENABLED);
+ }
+ }
+ }
+ else if(!strncmp(argv[1], "getdenied", 9)){
+ for(iface=0;iface<=PICMG_EKEY_MAX_INTERFACE;iface++) {
+ for(channel=1;channel<=PICMG_EKEY_MAX_CHANNEL;channel++) {
+ rc = ipmi_picmg_portstate_get(intf,iface,(uchar)channel,
+ PICMG_EKEY_MODE_PRINT_DISABLED);
+ }
+ }
+ }
+ else if (argc > 3){
+ iface = atob(argv[2]);
+ channel = atob(argv[3]);
+ if (fdebug) printf("PICMG: requesting interface %d",iface);
+ if (fdebug) printf("PICMG: requesting channel %d",channel);
+
+ rc = ipmi_picmg_portstate_get(intf,iface,(uchar)channel,
+ PICMG_EKEY_MODE_QUERY );
+ }
+ else {
+ printf("<intf> <chn>|getall|getgranted|getdenied\n");
+ }
+ }
+ else if (!strncmp(argv[1], "set", 3)) {
+ if (argc == 9) {
+ int interfc = strtoul(argv[2], NULL, 0);
+ int channel = strtoul(argv[3], NULL, 0);
+ int port = strtoul(argv[4], NULL, 0);
+ int type = strtoul(argv[5], NULL, 0);
+ int typeext = strtoul(argv[6], NULL, 0);
+ int group = strtoul(argv[7], NULL, 0);
+ int enable = strtoul(argv[8], NULL, 0);
+
+ if (fdebug) printf("PICMG: interface %d",interfc);
+ if (fdebug) printf("PICMG: channel %d",channel);
+ if (fdebug) printf("PICMG: port %d",port);
+ if (fdebug) printf("PICMG: type %d",type);
+ if (fdebug) printf("PICMG: typeext %d",typeext);
+ if (fdebug) printf("PICMG: group %d",group);
+ if (fdebug) printf("PICMG: enable %d",enable);
+
+ rc = ipmi_picmg_portstate_set(intf, interfc,
+ (uchar)channel, (uchar)port, type, typeext ,group ,enable);
+ }
+ else {
+ printf("<intf> <chn> <port> <type> <ext> <group> <1|0>\n");
+ rc = -1;
+ }
+ }
+ }
+ else {
+ printf("<set>|<getall>|<getgranted>|<getdenied>\n");
+ rc = -1;
+ }
+ }
+ /* amc portstate command */
+ else if (!strncmp(argv[0], "amcportstate", 12)) {
+
+ if (fdebug) printf("PICMG: amcportstate API");
+
+ if (argc > 1) {
+ if (!strncmp(argv[1], "get", 3)){
+ int channel;
+ int device;
+
+ if (fdebug) printf("PICMG: get");
+
+ if(!strncmp(argv[1], "getall", 6)){
+ int maxDevice = PICMG_EKEY_AMC_MAX_DEVICE;
+ if( PicmgCardType != PICMG_CARD_TYPE_ATCA ){
+ maxDevice = 0;
+ }
+ for(device=0;device<=maxDevice;device++){
+ for(channel=0;channel<=PICMG_EKEY_AMC_MAX_CHANNEL;channel++){
+ rc = ipmi_picmg_amc_portstate_get(intf,device,(uchar)channel,
+ PICMG_EKEY_MODE_PRINT_ALL);
+ }
+ }
+ }
+ else if(!strncmp(argv[1], "getgranted", 10)){
+ int maxDevice = PICMG_EKEY_AMC_MAX_DEVICE;
+ if( PicmgCardType != PICMG_CARD_TYPE_ATCA ){
+ maxDevice = 0;
+ }
+ for(device=0;device<=maxDevice;device++){
+ for(channel=0;channel<=PICMG_EKEY_AMC_MAX_CHANNEL;channel++){
+ rc = ipmi_picmg_amc_portstate_get(intf,(uchar)device,(uchar)channel,
+ PICMG_EKEY_MODE_PRINT_ENABLED);
+ }
+ }
+ }
+ else if(!strncmp(argv[1], "getdenied", 9)){
+ int maxDevice = PICMG_EKEY_AMC_MAX_DEVICE;
+ if( PicmgCardType != PICMG_CARD_TYPE_ATCA ){
+ maxDevice = 0;
+ }
+ for(device=0;device<=maxDevice;device++){
+ for(channel=0;channel<=PICMG_EKEY_AMC_MAX_CHANNEL;channel++){
+ rc = ipmi_picmg_amc_portstate_get(intf,(uchar)device,(uchar)channel,
+ PICMG_EKEY_MODE_PRINT_DISABLED);
+ }
+ }
+ }
+ else if (argc > 2){
+ channel = atoi(argv[2]);
+ if (argc > 3){
+ device = atoi(argv[3]);
+ }else{
+ device = -1;
+ }
+ if (fdebug) printf("PICMG: requesting device %d",device);
+ if (fdebug) printf("PICMG: requesting channel %d",channel);
+
+ rc = ipmi_picmg_amc_portstate_get(intf,(uchar)device,(uchar)channel,
+ PICMG_EKEY_MODE_QUERY );
+ }
+ else {
+ printf("<chn> <device>|getall|getgranted|getdenied\n");
+ }
+ }
+ else if (!strncmp(argv[1], "set", 3)) {
+ if (argc > 7) {
+ int channel = atoi(argv[2]);
+ int port = atoi(argv[3]);
+ int type = atoi(argv[4]);
+ int typeext = atoi(argv[5]);
+ int group = atoi(argv[6]);
+ int enable = atoi(argv[7]);
+ int device = -1;
+ if(argc > 8){
+ device = atoi(argv[8]);
+ }
+
+ if (fdebug) printf("PICMG: channel %d",channel);
+ if (fdebug) printf("PICMG: portflags %d",port);
+ if (fdebug) printf("PICMG: type %d",type);
+ if (fdebug) printf("PICMG: typeext %d",typeext);
+ if (fdebug) printf("PICMG: group %d",group);
+ if (fdebug) printf("PICMG: enable %d",enable);
+ if (fdebug) printf("PICMG: device %d",device);
+
+ rc = ipmi_picmg_amc_portstate_set(intf, (uchar)channel, (uchar)port, type,
+ typeext, group, enable, device);
+ }
+ else {
+ printf("<chn> <portflags> <type> <ext> <group> <1|0> [<device>]\n");
+ rc = -1;
+ }
+ }
+ }
+ else {
+ printf("<set>|<get>|<getall>|<getgranted>|<getdenied>\n");
+ rc = -1;
+ }
+ }
+ /* ATCA led commands */
+ else if (!strncmp(argv[0], "led", 3)) {
+ if (argc > 1) {
+ if (!strncmp(argv[1], "prop", 4)) {
+ if (argc > 2) {
+ rc = ipmi_picmg_get_led_properties(intf, argc-1, &(argv[2]));
+ }
+ else {
+ printf("led prop <FRU-ID>\n");
+ }
+ }
+ else if (!strncmp(argv[1], "cap", 3)) {
+ if (argc > 3) {
+ rc = ipmi_picmg_get_led_capabilities(intf, argc-1, &(argv[2]));
+ }
+ else {
+ printf("led cap <FRU-ID> <LED-ID>\n");
+ }
+ }
+ else if (!strncmp(argv[1], "get", 3)) {
+ if (argc > 3) {
+ rc = ipmi_picmg_get_led_state(intf, argc-1, &(argv[2]));
+ }
+ else {
+ printf("led get <FRU-ID> <LED-ID>\n");
+ }
+ }
+ else if (!strncmp(argv[1], "set", 3)) {
+ if (argc > 6) {
+ rc = ipmi_picmg_set_led_state(intf, argc-1, &(argv[2]));
+ }
+ else {
+ printf("led set <FRU-ID> <LED-ID> <function> <duration> <color>\n");
+ printf(" <FRU-ID>\n");
+ printf(" <LED-ID> 0: Blue LED\n");
+ printf(" 1: LED 1\n");
+ printf(" 2: LED 2\n");
+ printf(" 3: LED 3\n");
+ printf(" 0x04-0xFE: OEM defined\n");
+ printf(" 0xFF: All LEDs under management control\n");
+ printf(" <function> 0: LED OFF override\n");
+ printf(" 1 - 250: LED blinking override (off duration)\n");
+ printf(" 251: LED Lamp Test\n");
+ printf(" 252: LED restore to local control\n");
+ printf(" 255: LED ON override\n");
+ printf(" <duration> 1 - 127: LED Lamp Test / on duration\n");
+ printf(" <color> 0: reserved\n");
+ printf(" 1: BLUE\n");
+ printf(" 2: RED\n");
+ printf(" 3: GREEN\n");
+ printf(" 4: AMBER\n");
+ printf(" 5: ORANGE\n");
+ printf(" 6: WHITE\n");
+ printf(" 7: reserved\n");
+ printf(" 0xE: do not change\n");
+ printf(" 0xF: use default color\n");
+ }
+ }
+ else {
+ printf("prop | cap | get | set\n");
+ }
+ }
+ }
+ /* power commands */
+ else if (!strncmp(argv[0], "power", 5)) {
+ if (argc > 1) {
+ if (!strncmp(argv[1], "get", 3)) {
+ if (argc > 3) {
+ rc = ipmi_picmg_get_power_level(intf, argc-1, &(argv[2]));
+ }
+ else {
+ printf("power get <FRU-ID> <type>\n");
+ printf(" <type> 0 : steady state powert draw levels\n");
+ printf(" 1 : desired steady state draw levels\n");
+ printf(" 2 : early power draw levels\n");
+ printf(" 3 : desired early levels\n");
+
+ rc = -1;
+ }
+ }
+ else if (!strncmp(argv[1], "set", 3)) {
+ if (argc > 4) {
+ rc = ipmi_picmg_set_power_level(intf, argc-1, &(argv[2]));
+ }
+ else {
+ printf("power set <FRU-ID> <level> <present-desired>\n");
+ printf(" <level> 0 : Power Off\n");
+ printf(" 0x1-0x14 : Power level\n");
+ printf(" 0xFF : do not change\n");
+ printf("\n");
+ printf(" <present-desired> 0: do not change present levels\n");
+ printf(" 1: copy desired to present level\n");
+
+ rc = -1;
+ }
+ }
+ else {
+ printf("<set>|<get>\n");
+ rc = -1;
+ }
+ }
+ else {
+ printf("<set>|<get>\n");
+ rc = -1;
+ }
+ }/* clk commands*/
+ else if (!strncmp(argv[0], "clk", 3)) {
+ if (argc > 1) {
+ if (!strncmp(argv[1], "get", 3)) {
+ int clk_id;
+ int clk_res = -1;
+ int max_res = 15;
+
+ if( PicmgCardType == PICMG_CARD_TYPE_AMC ) {
+ max_res = 0;
+ }
+
+ if(!strncmp(argv[1], "getall", 6)) {
+ if(fdebug) printf("Getting all clock state\n");
+ for(clk_res=0;clk_res<=max_res;clk_res++) {
+ for(clk_id=0;clk_id<=15;clk_id++) {
+ rc = ipmi_picmg_clk_get(intf,clk_id,clk_res,
+ PICMG_EKEY_MODE_PRINT_ALL);
+ }
+ }
+ }
+ else if(!strncmp(argv[1], "getdenied", 6)) {
+ if( fdebug ) { printf("Getting disabled clocks\n") ;}
+ for(clk_res=0;clk_res<=max_res;clk_res++) {
+ for(clk_id=0;clk_id<=15;clk_id++) {
+ rc = ipmi_picmg_clk_get(intf,clk_id,clk_res,
+ PICMG_EKEY_MODE_PRINT_DISABLED);
+ }
+ }
+ }
+ else if(!strncmp(argv[1], "getgranted", 6)) {
+ if( fdebug ) { printf("Getting enabled clocks\n") ;}
+ for(clk_res=0;clk_res<=max_res;clk_res++) {
+ for(clk_id=0;clk_id<=15;clk_id++) {
+ rc = ipmi_picmg_clk_get(intf,clk_id,clk_res,
+ PICMG_EKEY_MODE_PRINT_ENABLED);
+ }
+ }
+ }
+ else if (argc > 2) {
+ clk_id = atoi(argv[2]);
+ if (argc > 3) {
+ clk_res = atoi(argv[3]);
+ }
+
+ rc = ipmi_picmg_clk_get(intf, clk_id, clk_res,
+ PICMG_EKEY_MODE_QUERY );
+ }
+ else {
+ printf("clk get ");
+ printf("<CLK-ID> [<DEV-ID>] |getall|getgranted|getdenied\n");
+ rc = -1;
+ }
+ }
+ else if (!strncmp(argv[1], "set", 3)) {
+ if (argc > 7) {
+ rc = ipmi_picmg_clk_set(intf, argc-1, &(argv[2]));
+ }
+ else {
+ printf("clk set <CLK-ID> <index> <setting> <family> <acc-lvl> <freq> [<DEV-ID>] \n");
+
+ rc = -1;
+ }
+ }
+ else {
+ printf("<set>|<get>|<getall>|<getgranted>|<getdenied>\n");
+ rc = -1;
+ }
+ }
+ else {
+ printf("<set>|<get>|<getall>|<getgranted>|<getdenied>\n");
+ rc = -1;
+ }
+ }
+
+ else if(showProperties == 0 ){
+
+ ipmi_picmg_help();
+ rc = ERR_USAGE;
+ }
+
+do_exit:
+ ipmi_close_();
+ return rc;
+} /*end i_picmg*/
+
+/* end ipicmg.c */
+
diff --git a/util/ipicmg.h b/util/ipicmg.h
new file mode 100644
index 0000000..59fce39
--- /dev/null
+++ b/util/ipicmg.h
@@ -0,0 +1,313 @@
+/*
+ (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;
+
+/* 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",
+ "", "", "", "", "",
+ "", "", "", "", "", "", "", ""
+ }
+};
+
+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
diff --git a/util/ipmi_port.c b/util/ipmi_port.c
new file mode 100644
index 0000000..3dccf6a
--- /dev/null
+++ b/util/ipmi_port.c
@@ -0,0 +1,146 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <signal.h>
+#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 */
diff --git a/util/ipmi_sample.c b/util/ipmi_sample.c
new file mode 100644
index 0000000..ddda7f3
--- /dev/null
+++ b/util/ipmi_sample.c
@@ -0,0 +1,312 @@
+/*
+ * 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 <windows.h>
+#include <stdio.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"
+#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: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 '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();
+ 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 */
diff --git a/util/ipmi_sample.mak b/util/ipmi_sample.mak
new file mode 100644
index 0000000..41860c1
--- /dev/null
+++ b/util/ipmi_sample.mak
@@ -0,0 +1,57 @@
+# 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)
+
+
diff --git a/util/ipmi_sample_evt.c b/util/ipmi_sample_evt.c
new file mode 100644
index 0000000..b51ba24
--- /dev/null
+++ b/util/ipmi_sample_evt.c
@@ -0,0 +1,445 @@
+/*
+ * 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 <windows.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "getopt.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.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"
+
+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 <signal.h>
+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 rlen;
+ uchar ccode;
+ uchar sensor_type;
+
+ fdout = stderr;
+ printf("%s ver %s\n", progname,progver);
+
+ while ( (c = getopt( argc, argv,"m: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 '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();
+ 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*/
+
+ while (ret == 0)
+ { /*wait for bmc message events*/
+ if (fdebug)
+ msgout("%s: Polling every %d sec for a new event after id %x...\n",
+ progname, 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;
+ }
+ 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 */
diff --git a/util/ipmibmc.c b/util/ipmibmc.c
new file mode 100644
index 0000000..e895338
--- /dev/null
+++ b/util/ipmibmc.c
@@ -0,0 +1,231 @@
+/*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 <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stropts.h>
+#include <stddef.h>
+#include <stropts.h>
+#include <iso/stdlib_iso.h>
+
+#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 */
diff --git a/util/ipmicmd.c b/util/ipmicmd.c
new file mode 100644
index 0000000..dd2268b
--- /dev/null
+++ b/util/ipmicmd.c
@@ -0,0 +1,1429 @@
+/*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 <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <fcntl.h>
+#elif defined(EFI)
+// defined (EFI32) || defined (EFI64) || defined(EFIX64)
+#include <bmc.h>
+#include <libdbg.h>
+#else
+/* Linux, Solaris, BSD */
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#ifndef DOS
+#include <sys/ioctl.h>
+#include <termios.h>
+#endif
+#include <stdarg.h>
+#include <errno.h>
+#endif
+
+#include "ipmicmd.h" /* has NCMDS, ipmi_cmd_t */
+
+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
+
+#include "ipmilan2.h" /*includes ipmilan.h also*/
+#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;
+char log_name[60] = {'\0'}; /*log_name global*/
+char *gnode = "localhost"; /* used for IPMI LAN, specified with option -N */
+char *guser = NULL;
+char *gpswd = NULL;
+char gnodename[SZGNODE] = {0}; /*the node name returned after a connection */
+int gcipher_suite = 3; /*used in ipmilanplus.c*/
+int gshutdown = 0;
+int fauth_type_set = 0;
+int gauth_type = IPMI_SESSION_AUTHTYPE_MD5; /*if 0, use any: MD5, MD2, etc.*/
+int gpriv_level = IPMI_PRIV_LEVEL_USER; /*or IPMI_PRIV_LEVEL_ADMIN */
+int gaddr_len = 0;
+uchar gaddr[128]; /* sizeof(struct sockaddr_storage) = 128 */
+ /* struct sockaddr_in/_in6 gaddr; _in6=28, _in=16 bytes */
+uchar my_devid[20] = {0,0,0,0,0,0,0,0}; /*saved devid, only needs 16 bytes*/
+char fdebug = 0;
+
+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;
+ 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" },
+
+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);
+}
+
+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);
+}
+
+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;
+ gauth_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,guser,gpswd,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. */
+ rc = ipmi_open_lan2(gnode,guser,gpswd,fdebugcmd);
+ fDriverTyp = DRV_LAN2;
+ }
+ } 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<sdata && sz< IPMI_REQBUF_SIZE); sz++ )
+ ReqMsg.Data[sz] = pdata[sz];
+ sz = *sresp; /* note that sresp must be pre-set */
+ memset(presp, 0, sz);
+ for ( i =0 ; i < BMC_MAX_RETRIES; i++)
+ {
+ *sresp = sz; /* retries may need to re-init *sresp */
+ if((status =ProcessTimedMessage(&ReqMsg, &RespMsg,TIMEOUT_EFI)) == 0) {
+ *sresp = RespMsg.Len;
+ for( sz=0 ; sz<RespMsg.Len && sz<IPMI_RSPBUF_SIZE ; sz++ )
+ presp[sz] = RespMsg.Data[sz];
+ *pcc = RespMsg.CompCode;
+ break;
+ }
+ if (fdebugcmd) // only gets here if error
+ fprintf(fpdbg,"ipmi_cmd_efi: ProcessTimedMessage error status=%x\n",
+ (uint)status);
+ }
+ return(status);
+}
+#endif
+
+/*
+ * ipmi_cmdraw()
+ *
+ * This routine can be used to invoke IPMI commands that are not
+ * already pre-defined in the ipmi_cmds array.
+ * It invokes whichever driver-specific routine is needed (ia, mv, etc.).
+ * Parameters:
+ * uchar cmd (input): IPMI Command
+ * uchar netfn (input): IPMI NetFunction
+ * uchar sa (input): IPMI Slave Address of the MC
+ * uchar bus (input): BUS of the MC
+ * uchar lun (input): IPMI LUN
+ * uchar *pdata (input): pointer to ipmi data
+ * int sdata (input): size of ipmi data
+ * uchar *presp (output): pointer to response data buffer
+ * int *sresp (input/output): on input, size of response buffer,
+ * on output, length of response data
+ * uchar *cc (output): completion code
+ * char fdebugcmd(input): flag =1 if debug output desired
+ */
+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)
+{
+ int rc = 0;
+ ushort icmd;
+
+ 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 == ERR_NO_DRV && !fipmi_lan) fprintf(fperr, "%s", msg_no_drv);
+ else if (rc != 0) fprintf(fperr,"ipmi_open error = %d\n", 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\n", 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 */
+ 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;
+ rv = ipmi_cmdraw_mc(req->msg.cmd, req->msg.netfn,
+ 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 <curses.h>
+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,gnode);
+ if (user != NULL) strcpy(user,guser);
+ if (pswd != NULL) strcpy(pswd,gpswd);
+ if (auth != NULL) *auth = gauth_type;
+ if (priv != NULL) *priv = gpriv_level;
+ if (cipher != NULL) *cipher = gcipher_suite;
+ if (addr != NULL && gaddr_len != 0) memcpy(addr,gaddr,gaddr_len);
+ if (addr_len != NULL) *addr_len = gaddr_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) { gnode = strdup_(node); fipmi_lan = 1; }
+ if (user != NULL) guser = strdup_(user);
+ if (pswd != NULL) gpswd = strdup_(pswd);
+ if (auth > 0 && auth <= 5) gauth_type = auth;
+ else rv = ERR_BAD_PARAM;
+ if (priv > 0 && priv <= 5) gpriv_level = priv;
+ else rv = ERR_BAD_PARAM;
+ if (cipher >= 0 && cipher <= 17) gcipher_suite = cipher;
+ else rv = ERR_BAD_PARAM;
+ if ((addr != NULL) && (addr_len > 15) && (addr_len <= sizeof(gaddr))) {
+ memcpy(gaddr,addr,addr_len);
+ gaddr_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;
+ size_t len;
+ static int fset_dtype = 0;
+ uchar sa;
+
+ switch(c)
+ {
+ 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) gauth_type = i;
+ fauth_type_set = 1;
+ break;
+ case 'V': /* priv level */
+ i = atoi(popt);
+ if (i > 0 && i <= 5) gpriv_level = i;
+ break;
+ case 'J':
+ i = atoi(popt);
+ if (i >= 0 && i <= 17) gcipher_suite = i;
+ else printf("-J cipher suite %d > 17, defaults to %d\n",
+ i,gcipher_suite);
+ if (fset_dtype == 0) i = set_driver_type("lan2");
+ break;
+ case 'N': gnode = popt; /* nodename */
+ fipmi_lan = 1;
+ break;
+ case 'U':
+ guser = strdup_(popt); /*remote username */
+ if (!guser) perror("strdup_");
+ else { /* Hide username from 'ps' */
+ memset(popt, ' ', strlen(popt));
+ }
+ break;
+ case 'R':
+ case 'P':
+ gpswd = strdup_(popt); /*remote password */
+ if (!gpswd) perror("strdup_");
+ else { /* Hide password from 'ps' */
+ len = strlen(popt);
+ memset(popt, ' ', len);
+ if (len > PSW_MAX) gpswd[PSW_MAX] = '\0';
+ }
+ break;
+ case 'E': /* get password from IPMI_PASSWORD environment var */
+ gpswd = getenv("IPMI_PASSWORD");
+ if (gpswd == NULL) perror("getenv(IPMI_PASSWORD)");
+ else {
+ if (strlen(gpswd) > PSW_MAX) gpswd[PSW_MAX] = '\0';
+ if (fdebugcmd) printf("using IPMI_PASSWORD\n");
+ }
+ break;
+ case 'Y': /* prompt for remote password */
+ gpswd = getline_wipe("Enter IPMI LAN Password: ");
+ if (gpswd != NULL) {
+ if (strlen(gpswd) > PSW_MAX) gpswd[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(void)
+{
+#if defined(EFI) | defined(DOS)
+ return;
+#else
+ 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);
+}
+
+extern int lasterr; /*defined in ipmilan.c */
+extern void show_LastError(char *tag, int err);
+
+void show_outcome(char *prog, int ret)
+{
+ if (prog == NULL) prog = "";
+ if (ret == -1 && lasterr != 0) show_LastError(prog,lasterr);
+ printf("%s%c %s\n",prog,bcomma,decode_rv(ret));
+}
+
+/* end ipmicmd.c */
diff --git a/util/ipmicmd.h b/util/ipmicmd.h
new file mode 100644
index 0000000..b65e949
--- /dev/null
+++ b/util/ipmicmd.h
@@ -0,0 +1,543 @@
+/*M*
+// PVCS:
+// $Workfile: ipmicmd.h $
+// $Revision: 1.0 $
+// $Modtime: 22 Jul 2002 08:51:14 $
+// $Author: arcress $
+//
+// 10/24/02 arcress - made cmd param ushort to be more unique
+//
+ *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 the copyright holder 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.
+ *----------------------------------------------------------------------*/
+
+#define uchar unsigned char
+#define uint32 unsigned int
+#define uint64 unsigned long
+// #ifdef __USE_MISC
+/* Can use compatibility names for C types. (from sys/types.h) */
+// typedef unsigned long int ulong;
+// typedef unsigned short int ushort;
+// typedef unsigned int uint;
+// #else
+#ifndef ushort
+#define ushort unsigned short
+#define ulong unsigned long
+#define uint unsigned int
+#endif
+
+#ifdef WIN32
+#define snprintf _snprintf
+#define SockType SOCKET
+#define SockInvalid INVALID_SOCKET
+#else
+#define SockType int
+#define SockInvalid -1
+#endif
+
+// Other IPMI values
+#define PUBLIC_BUS 0
+#define PRIVATE_BUS 0x03
+#define BMC_SA 0x20
+#define BMC_LUN 0
+#define SMS_LUN 2
+#define HSC_SA 0xC0
+#define ME_SA 0x2C
+#define ME_BUS 0x06
+
+#define ADDR_SMI 1
+#define ADDR_IPMB 2
+
+#define ACCESS_OK 0
+#define IPMI_REQBUF_SIZE 255
+#define IPMI_RSPBUF_SIZE 250 // was 80, then 1024, see MAX_BUFFER_SIZE
+#define IPMI_LANBUF_SIZE 200 // see RS_LEN_MAX for IPMI LAN
+
+// IPMI NetFn types, see Table 5-1
+#define NETFN_CHAS 0x00 // chassis
+#define NETFN_BRIDGE 0x02 // bridge
+#define NETFN_SEVT 0x04 // sensor/event
+#define NETFN_APP 0x06 // application
+#define NETFN_FW 0x08 // firmware
+#define NETFN_STOR 0x0a // storage
+#define NETFN_TRANS 0x0c // transport
+#define NETFN_SOL 0x34 // serial-over-lan (in IPMI 2.0, use TRANS)
+#define NETFN_PICMG 0x2c // for ATCA PICMG systems
+
+#ifndef IMBAPI_H__
+// special IMB defines, duplicates if imb_api.h
+#define MAX_BUFFER_SIZE 255
+#define MAX_SDR_SIZE 128
+#define GET_DEVICE_ID (0x01 | (NETFN_APP << 8))
+#define WRITE_READ_I2C (0x52 | (NETFN_APP << 8)) /*=MASTER_WRITE_READ*/
+#endif
+
+#define PSW_MAX 20 /* IPMI Passwords max = 16 or 20 bytes*/
+/* IPMI Commands, see Table 38-8, combined CMD and NETFN in unsigned short */
+#define CMDMASK 0xff /* mask to leave only the command part */
+#define WATCHDOG_RESET (0x22 | (NETFN_APP << 8))
+#define WATCHDOG_SET (0x24 | (NETFN_APP << 8))
+#define WATCHDOG_GET (0x25 | (NETFN_APP << 8))
+#define GET_SYSTEM_GUID (0x37 | (NETFN_APP << 8))
+#define SET_CHANNEL_ACC (0x40 | (NETFN_APP << 8))
+#define GET_CHANNEL_ACC (0x41 | (NETFN_APP << 8))
+#define GET_CHANNEL_INFO (0x42 | (NETFN_APP << 8))
+#define SET_USER_ACCESS (0x43 | (NETFN_APP << 8))
+#define GET_USER_ACCESS (0x44 | (NETFN_APP << 8))
+#define SET_USER_NAME (0x45 | (NETFN_APP << 8))
+#define GET_USER_NAME (0x46 | (NETFN_APP << 8))
+#define SET_USER_PASSWORD (0x47 | (NETFN_APP << 8))
+#define MASTER_WRITE_READ (0x52 | (NETFN_APP << 8))
+// #define SET_PEF_ENABLE 0xA1 /* NETFN_APP (old) */
+#define CHASSIS_STATUS 0x01 /* NETFN_CHAS (=00) */
+#define CHASSIS_CTL 0x02 /* NETFN_CHAS (=00) */
+#define CHASSIS_IDENTIFY 0x04 /* NETFN_CHAS (=00) */
+#define SET_BOOT_OPTIONS 0x08 /* NETFN_CHAS (=00) */
+#define GET_BOOT_OPTIONS 0x09 /* NETFN_CHAS (=00) */
+#define GET_POWERON_HOURS 0x0F /* NETFN_CHAS (=00) */
+#define GET_PEF_CONFIG (0x13 | (NETFN_SEVT << 8))
+#define SET_PEF_CONFIG (0x12 | (NETFN_SEVT << 8))
+#define GET_DEVSDR_INFO (0x20 | (NETFN_SEVT << 8))
+#define GET_DEVICE_SDR (0x21 | (NETFN_SEVT << 8))
+#define RESERVE_DEVSDR_REP (0x22 | (NETFN_SEVT << 8))
+#define SET_SEVT_ENABLE (0x28 | (NETFN_SEVT << 8))
+#define GET_SEVT_ENABLE (0x29 | (NETFN_SEVT << 8))
+#define REARM_SENSOR (0x2A | (NETFN_SEVT << 8))
+#define GET_FRU_INV_AREA (0x10 | (NETFN_STOR << 8))
+#define READ_FRU_DATA (0x11 | (NETFN_STOR << 8))
+#define WRITE_FRU_DATA (0x12 | (NETFN_STOR << 8))
+
+#define GET_SENSOR_READING_FACTORS (0x23 | (NETFN_SEVT << 8))
+#define SET_SENSOR_HYSTERESIS (0x24 | (NETFN_SEVT << 8))
+#define GET_SENSOR_HYSTERESIS (0x25 | (NETFN_SEVT << 8))
+#define SET_SENSOR_THRESHOLD (0x26 | (NETFN_SEVT << 8))
+#define GET_SENSOR_THRESHOLD (0x27 | (NETFN_SEVT << 8))
+#define GET_SENSOR_EVT_ENABLE (0x29 | (NETFN_SEVT << 8))
+#define REARM_SENSOR_EVENTS (0x2A | (NETFN_SEVT << 8))
+#define GET_SENSOR_EVT_STATUS (0x2B | (NETFN_SEVT << 8))
+#define GET_SENSOR_READING (0x2D | (NETFN_SEVT << 8))
+#define GET_SENSOR_TYPE (0x2F | (NETFN_SEVT << 8))
+
+#define SET_LAN_CONFIG (0x01 | (NETFN_TRANS << 8))
+#define GET_LAN_CONFIG (0x02 | (NETFN_TRANS << 8))
+#define GET_LAN_STATS (0x04 | (NETFN_TRANS << 8))
+#define SET_SER_CONFIG (0x10 | (NETFN_TRANS << 8))
+#define GET_SER_CONFIG (0x11 | (NETFN_TRANS << 8))
+#define SET_SER_MUX (0x12 | (NETFN_TRANS << 8))
+#define GET_SEL_INFO (0x40 | (NETFN_STOR << 8))
+#define GET_SEL_ALLOCATION_INFO (0x41 | (NETFN_STOR << 8))
+#define RESERVE_SEL (0x42 | (NETFN_STOR << 8))
+#define GET_SEL_ENTRY (0x43 | (NETFN_STOR << 8))
+#define CLEAR_SEL (0x47 | (NETFN_STOR << 8))
+#define GET_SEL_TIME (0x48 | (NETFN_STOR << 8))
+#define GET_SDR_REPINFO (0x20 | (NETFN_STOR << 8))
+#define RESERVE_SDR_REP (0x22 | (NETFN_STOR << 8))
+#define GET_SDR (0x23 | (NETFN_STOR << 8))
+#define ACTIVATE_SOL1 (0x01 | (NETFN_SOL << 8))
+#define SET_SOL_CONFIG (0x03 | (NETFN_SOL << 8))
+#define GET_SOL_CONFIG (0x04 | (NETFN_SOL << 8))
+#define ACTIVATE_SOL2 (0x20 | (NETFN_TRANS << 8))
+#define SET_SOL_CONFIG2 (0x21 | (NETFN_TRANS << 8))
+#define GET_SOL_CONFIG2 (0x22 | (NETFN_TRANS << 8))
+#define READ_EVENT_MSGBUF (0x35 | (NETFN_APP << 8))
+#define GET_EVENT_RECEIVER (0x01 | (NETFN_SEVT << 8))
+#define SMS_OS_REQUEST 0x10 /*(0x10 | (NETFN_APP << 8)) */
+#define CMD_GET_SESSION_INFO 0x3D /* NETFN_APP */
+#define CMD_SET_SYSTEM_INFO 0x58 /* NETFN_APP */
+#define CMD_GET_SYSTEM_INFO 0x59 /* NETFN_APP */
+/*
+ Other commands used for IPMI LAN:
+ GET_CHAN_AUTH (0x38 | (NETFN_APP << 8))
+ GET_SESS_CHAL (0x39 | (NETFN_APP << 8))
+ ACT_SESSION (0x3A | (NETFN_APP << 8))
+ SET_SESS_PRIV (0x3B | (NETFN_APP << 8))
+ CLOSE_SESSION (0x3C | (NETFN_APP << 8))
+ */
+
+#define IPMB_CLEAR_MSGF 0x30
+#define IPMB_GET_MESSAGE 0x33
+#define IPMB_SEND_MESSAGE 0x34
+
+#define PICMG_SLAVE_BUS 0x40
+/* commands under NETFN_PICMG */
+#define PICMG_GET_PROPERTIES 0x00
+#define PICMG_GET_LED_PROPERTIES 0x05
+#define PICMG_SET_LED_STATE 0x07
+#define PICMG_GET_LED_STATE 0x08
+#define PICMG_ID 0x00
+
+/* structure used by ipmi_cmd(), not used by ipmi_cmdraw */
+#define NCMDS 62
+typedef struct {
+ ushort cmdtyp;
+ uchar sa;
+ uchar bus;
+ uchar netfn;
+ uchar lun;
+ uchar len; /*length of request data (FYI, but not used here) */
+ uchar rslen; /*length of response data expected (not including ccode) */
+} ipmi_cmd_t;
+
+struct valstr {
+ ushort val;
+ const char * str;
+};
+
+struct oemvalstr {
+ uint oem;
+ ushort val;
+ const char * str;
+};
+
+/* IPMI driver types returned by get_driver_type() */
+#define NDRIVERS 15
+#define DRV_UNKNOWN 0
+#define DRV_IMB 1
+#define DRV_VA 2
+#define DRV_MV 3
+#define DRV_GNU 4
+#define DRV_LD 5 /*LANDesk*/
+#define DRV_LAN 6 /*IPMI LAN 1.5*/
+#define DRV_KCS 7 /*direct KCS*/
+#define DRV_SMB 8 /*direct SMBus/SSIF*/
+#define DRV_LAN2 9 /*LANplus, IPMI LAN 2.0*/
+#define DRV_MS 10 /*Microsoft ipmidrv.sys*/
+#define DRV_BMC 11 /*Solaris 10 bmc */
+#define DRV_SMC 12 /*SuperMicro Computer LAN mode*/
+#define DRV_LIPMI 13 /*Solaris 8/9 lipmi */
+#define DRV_LAN2I 14 /*LANplus with Intel OEM */
+#define DRV_EFI 15 /*Intel EFI, ipmi.efi*/
+#define DRV_IBM 16 /*LAN with IBM OEM mode*/
+#define DRV_HP 17 /*LANplus with HP OEM mode*/
+
+/* Event severity codes, used in ievents.c and oem*.c */
+#define SEV_INFO 0
+#define SEV_MIN 1
+#define SEV_MAJ 2
+#define SEV_CRIT 3
+
+/* Errors returned by ipmiutil functions, lan, etc, see decode_rv() */
+#define ERR_BAD_LENGTH -24 /*length < MIN */
+#define ERR_BAD_FORMAT -23 /*bad format*/
+#define ERR_USAGE -22 /*usage/help requested*/
+#define ERR_NOT_FOUND -21 /*requested item not found*/
+#define ERR_FILE_OPEN -20 /*cannot open file*/
+#define LAN_ERR_DROPPED -19 /*Remote BMC dropped the connection*/
+#define ERR_NOT_ALLOWED -18 /*access not allowed*/
+#define ERR_BAD_PARAM -17 /*invalid parameter*/
+#define ERR_NO_DRV -16 /*cannot open IPMI driver*/
+#define LAN_ERR_V2 -15 /*BMC only supports IPMI 2.0*/
+#define LAN_ERR_V1 -14 /*BMC only supports IPMI 1.x*/
+#define LAN_ERR_OTHER -13
+#define LAN_ERR_PING -12 /*error with ping*/
+#define LAN_ERR_HOSTNAME -11 /*error resolving hostname*/
+#define LAN_ERR_TOO_SHORT -10 /*recv data too short */
+#define LAN_ERR_NOTSUPPORT -9 /*slave address != 0x20, not supported now */
+#define LAN_ERR_INVPARAM -8 /*null pointers, etc. */
+#define LAN_ERR_BADLENGTH -7 /*length > MAX */
+#define LAN_ERR_TIMEOUT -6 /*timeout signal(SIGALRM) recvd */
+#define LAN_ERR_ABORT -5 /*abort signal(SIGINT) recvd */
+#define LAN_ERR_CONNECT -4 /*problem connecting to BMC*/
+#define LAN_ERR_RECV_FAIL -3 /*receive failed, usually no response*/
+#define LAN_ERR_SEND_FAIL -2 /*send failed */
+#define ERR_BMC_MSG -504 /*error getting message from BMC*/
+ /* see ipmidir.h: ERGETTINGIPMIMESSAGE -504 */
+
+/* values used to request AUTHTYPE */
+#define IPMI_SESSION_AUTHTYPE_NONE 0x00
+#define IPMI_SESSION_AUTHTYPE_MD2 0x01
+#define IPMI_SESSION_AUTHTYPE_MD5 0x02
+#define IPMI_SESSION_AUTHTYPE_PASSWORD 0x04
+#define IPMI_SESSION_AUTHTYPE_OEM 0x05
+#define AUTHTYPE_INIT 0xFF /*initial value, not set*/
+/* mask values used for AUTHTYPE support */
+#define IPMI_MASK_AUTHTYPE_NONE 0x01
+#define IPMI_MASK_AUTHTYPE_MD2 0x02
+#define IPMI_MASK_AUTHTYPE_MD5 0x04
+#define IPMI_MASK_AUTHTYPE_PASSWORD 0x10
+#define IPMI_MASK_AUTHTYPE_OEM 0x20
+
+#define IPMI_PRIV_LEVEL_OEM 0x05
+#define IPMI_PRIV_LEVEL_ADMIN 0x04
+#define IPMI_PRIV_LEVEL_OPERATOR 0x03
+#define IPMI_PRIV_LEVEL_USER 0x02
+#define IPMI_PRIV_LEVEL_CALLBACK 0x01
+
+#define VENDOR_INTEL 0x000157 /*=343.*/
+#define VENDOR_KONTRON 0x003A98 /*=15000*/
+#define VENDOR_NSC 0x000322
+#define VENDOR_LMC 0x000878
+#define VENDOR_TYAN 0x0019FD
+#define VENDOR_NEC 0x000077
+#define VENDOR_SUPERMICRO 0x002A7C /*=10876.*/
+#define VENDOR_PEPPERCON 0x0028C5 /*used in SuperMicro AOC-SIMSO*/
+#define VENDOR_FUJITSU 0x002880 /*Fujitsu-Siemens*/
+#define VENDOR_MICROSOFT 0x000137 /* 311. */
+#define VENDOR_SUN 0x00002A
+#define VENDOR_DELL 0x0002A2
+#define VENDOR_HP 0x00000B
+#define VENDOR_IBM 0x000002
+#define VENDOR_SUPERMICROX 0x00B980 /*=47488. used for Winbond/SuperMicro */
+#define VENDOR_MAGNUM 5593 /* Magnum Technologies, also SuperMicro */
+#define VENDOR_QUANTA 7244
+#define VENDOR_XYRATEX 1993
+#define VENDOR_NEWISYS 9237
+#define VENDOR_CISCO 5771 /*=0x168B*/
+
+#define PRODUCT_QUANTA_S99Q 21401
+#define PRODUCT_QUANTA_QSSC_S4R 64 /*0x0040*/
+
+#define URNLOOPS 1000 /* default is 300 ms, Urbanna needs 1000 ms */
+#define LOG_MSG_LENGTH 1024 /*max len of log message*/
+#define SZGNODE 80 /* max len of a nodename */
+
+#define BDELIM '|' /*delimeter for canonical output*/
+#define BCOMMA ',' /*delimeter for CSV output*/
+#define BCOLON ':' /*delimeter some output with colons*/
+#define BCOMMENT '#' /*delimeter '#' used for comments */
+
+#ifndef LOG_WARN
+#define LOG_EMERG 0 // system is unusable
+#define LOG_ALERT 1 // action must be taken immediately
+#define LOG_CRIT 2 // critical conditions
+#define LOG_ERR 3 // error conditions
+#define LOG_WARN 4 // warning conditions
+#define LOG_NOTICE 5 // normal but significant condition
+#define LOG_INFO 6 // informational
+#define LOG_DEBUG 7 // debug-level messages
+#endif
+
+#ifndef _IPMI_RQ_
+#define _IPMI_RQ_ 1
+/* structure used in ipmi_sendrecv, maps to ipmitool syntax. */
+struct ipmi_rq {
+ struct {
+ uchar netfn:6;
+ uchar lun:2;
+ uchar cmd;
+ uchar target_cmd;
+ ushort data_len;
+ uchar *data;
+ } msg;
+};
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* ------------------------ SUBROUTINES ------------------------- */
+
+/*
+ * ipmi_cmd
+ * ushort cmd (input): (netfn << 8) + command
+ * uchar *pdata (input): pointer to ipmi data
+ * int sdata (input): size of ipmi data
+ * uchar *presp (output): pointer to response data buffer
+ * int *sresp (input/output): on input, size of response buffer,
+ * on output, length of response data
+ * uchar *cc (output): completion code
+ * char fdebugcmd(input): flag =1 if debug output desired
+ * returns 0 if successful, <0 if error
+ */
+int ipmi_cmd(ushort cmd, uchar *pdata, int sdata, uchar *presp,
+ int *sresp, uchar *pcc, char fdebugcmd);
+/*
+ * ipmi_cmdraw
+ * uchar cmd (input): IPMI Command
+ * uchar netfn (input): IPMI NetFunction
+ * uchar sa (input): IPMI Slave Address of the MC
+ * uchar bus (input): BUS of the MC
+ * uchar lun (input): IPMI LUN
+ * uchar *pdata (input): pointer to ipmi data
+ * int sdata (input): size of ipmi data
+ * uchar *presp (output): pointer to response data buffer
+ * int *sresp (input/output): on input, size of response buffer,
+ * on output, length of response data
+ * uchar *cc (output): completion code
+ * char fdebugcmd(input): flag =1 if debug output desired
+ * returns 0 if successful, <0 if error
+ */
+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);
+/*
+ * ipmi_close_
+ * Called to close an IPMI session.
+ * returns 0 if successful, <0 if error
+ */
+int ipmi_close_(void);
+int ipmi_close(void); /*ditto*/
+/*-----------------------------------------------------------------*
+ * These externals are conditionally compiled in ipmicmd.c
+ ipmi_cmdraw_ia() Intel IMB driver, /dev/imb
+ ipmi_cmdraw_mv() MontaVista OpenIPMI driver
+ ipmi_cmdraw_va() VALinux driver
+ ipmi_cmdraw_ld() LANDesk driver
+ ipmi_cmdraw_direct() Direct/Driverless KCS or SSIF
+ ipmi_cmdraw_lan() IPMI LAN
+ ipmi_cmdraw_lan2() IPMI LANplus (RMCP+ in IPMI 2.0)
+ *-----------------------------------------------------------------*/
+
+/*
+ * parse_lan_options
+ * Parse the IPMI LAN options from the command-line getopt.
+ * int c (input): command-line option from getopt, one of:
+ case 'F': force driver type
+ case 'T': auth type
+ case 'V': priv level
+ case 'J': cipher suite
+ case 'N': nodename
+ case 'U': username
+ case 'R': remote password
+ case 'P': remote password
+ case 'E': get password from IPMI_PASSWORD environment var
+ case 'Y': prompt for remote password
+ case 'Z': set local MC address
+ * char *optarg (input): command-line argument from getopt
+ * char fdebug (input): show debug messages if =1, default=0
+ */
+void parse_lan_options(int c, char *optarg, char fdebug);
+/*
+ * set_lan_options
+ * Use this routine to set the lan options 'gnode','guser','gpswd', etc.
+ * This would only be required before opening a new session.
+ * char *node (input): IP address or nodename of remote node's IPMI LAN
+ * char *user (input): IPMI LAN username
+ * char *pswd (input): IPMI LAN password
+ * int auth (input): IPMI LAN authentication type (1 - 5)
+ * IPMI_SESSION_AUTHTYPE_NONE 0x00
+ * IPMI_SESSION_AUTHTYPE_MD2 0x01
+ * IPMI_SESSION_AUTHTYPE_MD5 0x02
+ * IPMI_SESSION_AUTHTYPE_PASSWORD 0x04
+ * IPMI_SESSION_AUTHTYPE_OEM 0x05
+ * int priv (input): IPMI LAN privilege level (1 - 5)
+ * IPMI_PRIV_LEVEL_CALLBACK 0x01
+ * IPMI_PRIV_LEVEL_USER 0x02
+ * IPMI_PRIV_LEVEL_OPERATOR 0x03
+ * IPMI_PRIV_LEVEL_ADMIN 0x04
+ * IPMI_PRIV_LEVEL_OEM 0x05
+ * int cipher (input): IPMI LAN cipher suite (0 thru 17, default is 3)
+ * See table 22-19 in the IPMIv2 spec.
+ * void *addr (input): Socket Address to use (SOCKADDR_T *) if not NULL
+ * This is only used in itsol.c because it has an
+ * existing socket open. Default is NULL for this.
+ * int addr_len (input): length of Address buffer (128 if ipv6, 16 if ipv4)
+ * returns 0 if successful, <0 if error
+ */
+int set_lan_options(char *node, char *user, char *pswd, int auth, int priv,
+ int cipher, void *addr, int addr_len);
+int get_lan_options(char *node, char *user, char *pswd, int *auth, int *priv,
+ int *cipher, void *addr, int *addr_len);
+void print_lan_opt_usage(void);
+int ipmi_getdeviceid(uchar *presp, int sresp, char fdebugcmd);
+/* int ipmi_open(void); * embedded in ipmi_cmd() */
+int ipmi_getpicmg(uchar *presp, int sresp, char fdebug);
+char *show_driver_type(int idx);
+int set_driver_type(char *tag);
+int get_driver_type(void);
+int nodeislocal(char *nodename);
+/* These *_mc routines are used to manage changing the mc.
+ * The local mc (mymc) may be changed via -Z, and
+ * the remote mc (mc) may be changed with -m. */
+void ipmi_set_mc(uchar bus, uchar sa, uchar lun, uchar type);
+void ipmi_get_mc(uchar *bus, uchar *sa, uchar *lun, uchar *type);
+void ipmi_restore_mc(void);
+void ipmi_set_mymc(uchar bus, uchar sa, uchar lun, uchar type);
+void ipmi_get_mymc(uchar *bus, uchar *sa, uchar *lun, uchar *type);
+/* ipmi_cmdraw_mc and ipmi_cmd_mc are used in cases where the mc may
+ * have been changed via ipmi_set_mc. */
+int ipmi_cmdraw_mc(uchar cmd, uchar netfn,
+ uchar *pdata, int sdata, uchar *presp,
+ int *sresp, uchar *pcc, char fdebugcmd);
+int ipmi_cmd_mc(ushort icmd, uchar *pdata, int sdata, uchar *presp,
+ int *sresp, uchar *pcc, char fdebugcmd);
+/* ipmi_sendrecv is a wrapper for ipmi_cmdraw which maps to ipmitool syntax */
+int ipmi_sendrecv(struct ipmi_rq * req, uchar *rsp, int *rsp_len);
+
+/* other common subroutines */
+char * decode_rv(int rv); /*ipmicmd.c*/
+char * decode_cc(ushort icmd, int cc);
+void dump_buf(char *tag,uchar *pbuf,int sz, char fshowascii);
+int get_lan_channel(uchar chstart, uchar *chan);
+void show_fru_picmg(uchar *pdata, int dlen); /* ifru_picmg.c*/
+/* show_outcome outputs the meaning of the return code. */
+void show_outcome(char *prog, int ret);
+/* these log routines are primarily for the isol debug log */
+FILE *open_log(char *mname);
+void close_log(void);
+void flush_log(void);
+void print_log( char *pattn, ... );
+void dump_log(FILE *fp,char *tag,uchar *pbuf,int sz, char fshowascii);
+void logmsg( char *pname, char *pattn, ... );
+
+#ifdef WIN32
+/* Implement the Linux strncasecmp for Windows. */
+int strncasecmp(const char *s1, const char *s2, int n);
+#endif
+const char *val2str(ushort val, const struct valstr *vs); /*ipmilanplus.c*/
+const char * oemval2str(ushort oem, uchar val, const struct oemvalstr *vs);
+void set_debug(void); /*used only by oem_sun.c*/
+void set_iana(int iana); /*ipmicmd.c*/
+void set_mfgid(uchar *devid, int len);
+void get_mfgid(int *pvend, int *pprod);
+void get_devid_ver(uchar *bmaj, uchar *bmin, uchar *iver);
+
+char *get_nodename(void);
+char is_remote(void);
+void show_devid(uchar b1, uchar b2, uchar i1, uchar i2);
+int set_max_kcs_loops(int ms); /* ipmicmd.c, calls ipmidir.c if ok */
+
+/* These common subroutines are in subs.c */
+int str_icmp(char *s1, char *s2); /*used internally in ipmicmd.c*/
+char * strdup_(const char *instr); /*wrapper for strdup, supports WIN32*/
+int strlen_(const char *s);
+uchar htoi(char *inhex);
+void os_usleep(int s, int u);
+char *get_iana_str(int mfg); /*subs.c*/
+int get_errno(void); /*subs.c*/
+const char * buf2str(uchar * buf, int len); /*subs.c*/
+int str2uchar(char *str_in, uchar *uchr_out);
+uchar atob(char *str_in); /* calls str2uchar*/
+void atoip(uchar *array,char *instr);
+int get_system_info(uchar parm, char *pbuf, int *szbuf); /*subs.c*/
+int set_system_info(uchar parm, uchar *pbuf, int szbuf); /*subs.c*/
+int ipmi_reserved_user(int vend, int userid); /*subs.c*/
+
+/* from mem_if.c */
+int get_BiosVersion(char *str);
+
+/* see isensor.h for SDR cache routines */
+/* see ievents.h for sensor_type_desc, sel_opts, decode_sel routines */
+
+#ifdef __cplusplus
+}
+#endif
+/* end ipmicmd.h */
diff --git a/util/ipmidir.c b/util/ipmidir.c
new file mode 100644
index 0000000..4865bc0
--- /dev/null
+++ b/util/ipmidir.c
@@ -0,0 +1,1513 @@
+/************************************************
+ *
+ * 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(STUB_IO)
+/* May stub out direct io. For instance, PPC does not support <sys/io.h> */
+#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)
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h> // for ProcessSendMessage timeout
+#include <string.h>
+#include <errno.h>
+#ifdef DOS
+#include <dos.h>
+#else
+#include <sys/mman.h>
+#endif
+
+#include "imb_api.h"
+#include "ipmicmd.h"
+#include "ipmidir.h"
+/* No special includes for 64-bit are needed. */
+
+#if defined(LINUX)
+#include <sys/io.h>
+#elif defined(BSD) || defined(MACOS)
+// #include <machine/cpufunc.h>
+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)
+#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;
+ if (sa == 0x20 && mybase != 0) { /*valid*/
+ kcsBaseAddress = mybase;
+ kcs_inc = inc;
+ }
+ }
+ BMC_base = mybase;
+ DBGP("smbios: Driver=%d(%s), sa=%02x, Base=0x%04x, Spacing=%d\n",
+ g_DriverType,BmcDesc(g_DriverType),sa,mybase,inc);
+ }
+ }
+
+#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);
+ }
+ }
+ DBGP("open_direct: status=%d, %s drv, ipmi=%d\n",
+ status,BmcDesc(g_DriverType),g_ipmiVersion);
+
+ /* set lock for driverless interface */
+ i = set_lock_dir();
+ return status;
+}
+
+int ipmi_close_direct(void)
+{
+ int status = 0;
+#if defined(BSD) || defined(MACOS)
+ 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; i<j; i++) DBGP("%02x ",p_reqMsg->Data[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; i<j; i++) DBGP("%02x ",p_respMsg->Data[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;
+ ifstr = "KCS";
+ if (sa == BMC_SA && mybase != 0) { /*valid*/
+ kcsBaseAddress = mybase;
+ kcs_inc = inc;
+ }
+ }
+ BMC_base = mybase;
+ 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");
+ g_DriverType = DRV_KCS;
+ BMC_base = kcsBaseAddress;
+ DBGP("Continuing with KCS on Default Port 0x%04x\n",kcsBaseAddress);
+ }
+#if defined(BSD) || defined(MACOS)
+ 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 */
diff --git a/util/ipmidir.h b/util/ipmidir.h
new file mode 100644
index 0000000..079c6b6
--- /dev/null
+++ b/util/ipmidir.h
@@ -0,0 +1,301 @@
+/***********************************************
+ * 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_
diff --git a/util/ipmilan.c b/util/ipmilan.c
new file mode 100644
index 0000000..64b6425
--- /dev/null
+++ b/util/ipmilan.c
@@ -0,0 +1,2430 @@
+/*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 <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <time.h>
+#include <signal.h>
+
+//#define HAVE_IPV6 1
+#ifdef HAVE_IPV6
+#include <winsock2.h>
+//#include <ws2tcpip.h>
+//#include <tpipv6.h>
+#else
+#include <winsock.h>
+#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 <dos.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#undef HAVE_LANPLUS
+
+#else /* Linux */
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#define RECV_MSG_FLAGS MSG_WAITALL
+#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 */
+extern char gnodename[]; /* from ipmicmd.c */
+extern char *gnode; /* from ipmicmd.c */
+extern char *guser; /* from ipmicmd.c */
+extern char *gpswd; /* from ipmicmd.c */
+extern int fauth_type_set; /* 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, 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] = "";
+#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.*/
+#else
+int econnrefused = ECONNREFUSED; /*=111. from Linux asm/errno.h */
+#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, SockType *sfd, SOCKADDR_T *daddr,
+ int *daddr_len, int foutput);
+int open_sockfd(char *node, 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", RMCP_PRI_RMCP_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) {
+ s = socket(res0->ai_family, res0->ai_socktype, res0->ai_protocol);
+ if (s == SockInvalid) continue;
+ else _sockfd = s;
+ /* valid protocols are IPPROTO_UDP, IPPROTO_IPV6 */
+ if (res0->ai_protocol == IPPROTO_TCP) continue; /*IPMI != TCP*/
+ 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(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());
+#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;
+ // uchar buf_rs[4];
+ // uchar *cmd_rs;
+
+ 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(uint *h, uchar *net, int n)
+{
+ uint v;
+ v = (net[1] << 8) | net[0];
+ if (n == 2) { *h = v; return; }
+ v |= (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 %d\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,gauth_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 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;
+ }
+ }
+ /* 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)gauth_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,&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, 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 ((gshutdown==0) || 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, &(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);
+ 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)gauth_type;
+ priv_level = (uchar)gpriv_level;
+ 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 (!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 */
+ 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(gnode, guser, gpswd, 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, gpswd, 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, gpswd, 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,gauth_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;
+ int fdoauth = 1;
+ uchar *pdata;
+ int itry;
+ int flags;
+ int rv = -1;
+
+ phdr = &ipmi_hdr;
+ rsp->data = rsdata;
+ fdoauth = 0;
+ 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 */
+
diff --git a/util/ipmilan.h b/util/ipmilan.h
new file mode 100644
index 0000000..9e92e55
--- /dev/null
+++ b/util/ipmilan.h
@@ -0,0 +1,83 @@
+/***********************************************
+ * 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 ipmi_open_lan(char *node, 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_
diff --git a/util/ipmilan2.c b/util/ipmilan2.c
new file mode 100644
index 0000000..0ff2fac
--- /dev/null
+++ b/util/ipmilan2.c
@@ -0,0 +1,68 @@
+/*
+ * 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 <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+#if defined(LINUX) || defined(BSD)
+#include <sys/time.h>
+#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 */
diff --git a/util/ipmilan2.h b/util/ipmilan2.h
new file mode 100644
index 0000000..aaa5318
--- /dev/null
+++ b/util/ipmilan2.h
@@ -0,0 +1,62 @@
+/***********************************************
+ * ipmilan2.h
+ *
+ * Definitions and data structures for the
+ * IPMI 2.0 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 IPMILAN2_H_
+#define IPMILAN2_H_
+
+#include "ipmilan.h"
+
+#define IPMI_AUTH_RAKP_NONE 0x00
+#define IPMI_INTEGRITY_NONE 0x00
+#define IPMI_CRYPT_NONE 0x00
+
+int ipmi_open_lan2(char *node, char *user, char *pswd, int fdebugcmd);
+int ipmi_close_lan2(char *node);
+int ipmi_cmd_lan2(char *node, ushort cmd, uchar *pdata, int sdata,
+ uchar *presp, int *sresp, uchar *pcc, char fdebugcmd);
+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 ipmicmd_lan2(char *node, uchar cmd, uchar netfn, uchar lun, uchar sa,
+ uchar *pdata, int sdata, uchar *presp, int *sresp,
+ uchar *pcc, char fdebugcmd);
+int ipmi_cmd_ipmb2(uchar cmd, uchar netfn, uchar sa, uchar bus, uchar lun,
+ uchar *pdata, int sdata, uchar *presp,
+ int *sresp, uchar *pcc, char fdebugcmd);
+
+
+#endif // IPMILAN2_H_
diff --git a/util/ipmilanplus.c b/util/ipmilanplus.c
new file mode 100644
index 0000000..771c7e7
--- /dev/null
+++ b/util/ipmilanplus.c
@@ -0,0 +1,790 @@
+/*
+ * 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 <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+#if defined(LINUX) || defined(BSD) || defined(MACOS)
+#include <sys/time.h>
+#endif
+
+// #define DEBUG 1
+int verbose = 0;
+char fdbglog = 0;
+
+#ifndef HAVE_LANPLUS
+#ifdef WIN32
+#include <windows.h>
+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)
+{ 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 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 gshutdown; /* from ipmicmd.c */
+extern int gcipher_suite; /*from ipmicmd.c, see table 22-19 IPMI 2.0 spec*/
+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 <windows.h>
+#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)gauth_type;
+ intf->session->privlvl = (uchar)gpriv_level;
+ intf->session->cipher_suite_id = (uchar)gcipher_suite;
+ 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",
+ gauth_type,gpriv_level,gcipher_suite, 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,guser,gpswd,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 */
diff --git a/util/ipmilanplus.h b/util/ipmilanplus.h
new file mode 100644
index 0000000..0003cf0
--- /dev/null
+++ b/util/ipmilanplus.h
@@ -0,0 +1,64 @@
+/*
+ * 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 <windows.h>
+#include <winsock.h>
+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 <arpa/inet.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#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 */
diff --git a/util/ipmild.c b/util/ipmild.c
new file mode 100644
index 0000000..5ad54f2
--- /dev/null
+++ b/util/ipmild.c
@@ -0,0 +1,250 @@
+/*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 <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#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 TEST
+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
+
diff --git a/util/ipmilipmi.c b/util/ipmilipmi.c
new file mode 100644
index 0000000..89fa12e
--- /dev/null
+++ b/util/ipmilipmi.c
@@ -0,0 +1,182 @@
+/*M*
+// $Workfile: ipmilipmi.c $
+// $Revision: 0.1 $
+// $Modtime: 18 Oct 2010 15:20:14 $
+// $Author: arcress at users.sourceforge.net $
+//
+// This implements support for the /dev/lipmi interface from
+// the Solaris 8 & 9 LIPMI driver.
+//
+// 10/18/10 ARC - created
+ *M*/
+/*----------------------------------------------------------------------*
+The BSD License
+
+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.
+ *----------------------------------------------------------------------*/
+
+#ifdef SOLARIS
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stropts.h>
+
+#include "ipmicmd.h" /* for uchar, NCMDS */
+
+#define MAX_SEND_SIZE 34
+#define MAX_RECV_SIZE 33 /*TODO: compare with RECV_MAX_PAYLOAD_SIZE */
+#define IOCTL_IPMI_KCS_ACTION 0x01
+/* I_STR should be defined in stropts.h */
+
+extern ipmi_cmd_t ipmi_cmds[NCMDS];
+static int ipmi_fd = -1;
+static char *pdev = "/dev/lipmi";
+
+#ifndef _SYS_STROPTS_H
+/* see sys/stropts.h, sys/lipmi/lipmi_intf.h*/
+typedef struct strioctl {
+ int ic_cmd;
+ int ic_timout;
+ int ic_len;
+ char *ic_dp;
+} strioctl_t;
+#endif
+
+typedef struct bmc_req {
+ uchar fn;
+ uchar lun;
+ uchar cmd;
+ uchar datalength;
+ uchar data[MAX_SEND_SIZE];
+} bmc_req_t;
+
+typedef struct bmc_rsp {
+ uchar fn;
+ uchar lun;
+ uchar cmd;
+ uchar ccode;
+ uchar datalength;
+ uchar data[MAX_RECV_SIZE];
+} bmc_rsp_t;
+
+typedef struct lipmi_reqrsp { /*TODO: see sys/lipmi/lipmi_intf.h*/
+ bmc_req_t req;
+ bmc_rsp_t rsp;
+} lipmi_reqrsp_t;
+
+
+int ipmi_open_lipmi(char fdebugcmd)
+{
+ int rc = -1;
+
+ if (ipmi_fd != -1) return(0);
+ ipmi_fd = open(pdev, O_RDWR);
+ if (ipmi_fd < 0) {
+ if (fdebugcmd) printf("ipmi_open_lipmi: cannot open %s, errno=%d\n",
+ pdev,errno);
+ return(rc);
+ }
+ rc = 0;
+ if (fdebugcmd) printf("ipmi_open_lipmi: successfully opened\n");
+ return(rc);
+}
+
+int ipmi_close_lipmi(void)
+{
+ int rc = 0;
+ if (ipmi_fd != -1) {
+ close(ipmi_fd);
+ ipmi_fd = -1;
+ }
+ return(rc);
+}
+
+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)
+{
+ int rv = -1;
+ struct strioctl istr;
+ static struct lipmi_reqrsp reqrsp;
+ int len;
+ uchar cc;
+
+ if (ipmi_fd == -1) return -1;
+
+ memset(&reqrsp, 0, sizeof(reqrsp));
+ reqrsp.req.fn = netfn;
+ reqrsp.req.lun = lun;
+ reqrsp.req.cmd = cmd;
+ reqrsp.req.datalength = sdata;
+ memcpy(reqrsp.req.data, pdata, sdata);
+ reqrsp.rsp.datalength = MAX_RECV_SIZE;
+
+ istr.ic_cmd = IOCTL_IPMI_KCS_ACTION;
+ istr.ic_timout = 0;
+ istr.ic_dp = (char *)&reqrsp;
+ istr.ic_len = sizeof(struct lipmi_reqrsp);
+
+ rv = ioctl(ipmi_fd, I_STR, &istr);
+ if (rv < 0) {
+ perror("LIPMI IOCTL: I_STR");
+ return rv;
+ }
+
+ cc = reqrsp.rsp.ccode;
+ len = reqrsp.rsp.datalength;
+ *pcc = cc;
+ *sresp = len;
+ if (cc == 0 && len > 0)
+ memcpy(presp, reqrsp.rsp.data, len);
+ return(rv);
+}
+
+int ipmi_cmd_lipmi(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_lipmi: Unknown command %x\n",cmd);
+ return(-1);
+ }
+ if (cmd >= CMDMASK) cmd = cmd & CMDMASK; /* unmask it */
+ rc = ipmi_cmdraw_lipmi(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 ipmilipmi.c */
diff --git a/util/ipmims.cpp b/util/ipmims.cpp
new file mode 100644
index 0000000..2ba0611
--- /dev/null
+++ b/util/ipmims.cpp
@@ -0,0 +1,638 @@
+/*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 <arcress at users.sourceforge.net>
+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 <windows.h>
+#include <stdio.h>
+#include <iostream> //deprecated iostream.h
+#include <Objbase.h> //ole32.lib
+#include <comutil.h>
+#include <Wbemcli.h>
+
+#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 */
diff --git a/util/ipmimv.c b/util/ipmimv.c
new file mode 100644
index 0000000..06b1baf
--- /dev/null
+++ b/util/ipmimv.c
@@ -0,0 +1,784 @@
+/*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)
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#if defined(MACOS)
+#include <sys/time.h>
+#else
+#include <sys/poll.h>
+#endif
+#ifdef SCO_UW
+#include <sys/ioccom.h>
+#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(BSD) || defined(MACOS)
+#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(BSD) || defined(MACOS)
+#pragma pack()
+/* 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 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);
+ }
+ }
+
+ 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
diff --git a/util/ipmiutil.c b/util/ipmiutil.c
new file mode 100644
index 0000000..4094cab
--- /dev/null
+++ b/util/ipmiutil.c
@@ -0,0 +1,229 @@
+/***********************************************
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "ipmicmd.h"
+#include "ipmiutil.h"
+
+static char *progname = "ipmiutil";
+static char *progver = "2.93";
+// static char fdebug = 0;
+/*int ipmiutil(int argc, char **argv); */
+
+#define NSUBCMDS 28
+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 and PEF table"},
+ { 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" },
+ { 27, "wdt", i_wdt, "show/set/reset the watchdog timer" }
+ };
+
+static char usagemsg[] = "Usage: ipmiutil <command> [other options]\n"
+ " where <command> 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; i++)
+ printf("\t%s\t%s\n",subcmds[i].tag,subcmds[i].desc);
+ printf(" common IPMI LAN options:\n");
+ print_lan_opt_usage();
+ printf("%s", helpmsg);
+}
+
+#ifdef DOS
+int i_discover(int argc, char **argv)
+{
+ printf("The discover function is not supported in DOS.\n");
+ return(1);
+}
+#endif
+
+#ifdef WIN32
+int __cdecl
+#else
+int
+#endif
+main(int argc, char **argv)
+{
+ int ret = 1;
+ int i;
+ char *psubcmd = "";
+
+ printf("%s ver %s\n", progname,progver);
+ if (argc < 2) {
+ show_usage();
+ ret = ERR_USAGE;
+ goto do_exit;
+ }
+#ifdef TEST_LOOP
+ /* special subcommand processing loop for testing */
+#ifdef WIN32
+ while ( !(( _kbhit() ) && (_getch() == 'q')) )
+#else
+ while ( 1 )
+#endif
+ {
+ for (i = 0; i < NSUBCMDS; i++)
+ {
+ if (strcmp(argv[1],subcmds[i].tag) == 0) {
+ psubcmd = argv[1];
+ argc--;
+ argv++;
+ ret = subcmds[i].rtn(argc,argv);
+
+ argc++; argv--; /*requeue the same subcmd*/
+ os_usleep( 1, 0 ); /*sleep 1 sec*/
+ break;
+ }
+ }
+ }
+#else
+ for (i = 0; i < NSUBCMDS; i++)
+ {
+ if (strcmp(argv[1],subcmds[i].tag) == 0) {
+ psubcmd = argv[1];
+ argc--;
+ argv++;
+ ret = subcmds[i].rtn(argc,argv);
+ break;
+ }
+ }
+#endif
+ if (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);
+}
+
+/*end ipmiutil.c*/
diff --git a/util/ipmiutil.h b/util/ipmiutil.h
new file mode 100644
index 0000000..39b5ecb
--- /dev/null
+++ b/util/ipmiutil.h
@@ -0,0 +1,66 @@
+/***********************************************
+ * 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);
+
+#endif // IPMIUTIL_H_
diff --git a/util/ipmiutil.mak b/util/ipmiutil.mak
new file mode 100644
index 0000000..83a23c1
--- /dev/null
+++ b/util/ipmiutil.mak
@@ -0,0 +1,424 @@
+# This makefile will build the ipmiutil util directory
+#
+# 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) $(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 $(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_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)\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_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.c
+ $(CC) /c $(CFLAGS_SAM) ipmi_sample.c
+ $(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)
diff --git a/util/ipmiutil2-64.mak b/util/ipmiutil2-64.mak
new file mode 100644
index 0000000..6289e06
--- /dev/null
+++ b/util/ipmiutil2-64.mak
@@ -0,0 +1,425 @@
+# 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_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)\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_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)
diff --git a/util/ipmiutil2.mak b/util/ipmiutil2.mak
new file mode 100644
index 0000000..8ed0155
--- /dev/null
+++ b/util/ipmiutil2.mak
@@ -0,0 +1,425 @@
+# 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_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)\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_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)
diff --git a/util/ipmiutil64.mak b/util/ipmiutil64.mak
new file mode 100644
index 0000000..4c7b315
--- /dev/null
+++ b/util/ipmiutil64.mak
@@ -0,0 +1,423 @@
+# 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"
+
+#MARCH=IX86
+MARCH=X64
+# 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) $(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_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_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)\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_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)
diff --git a/util/ipmiutillib.def b/util/ipmiutillib.def
new file mode 100644
index 0000000..57f3dc1
--- /dev/null
+++ b/util/ipmiutillib.def
@@ -0,0 +1,31 @@
+LIBRARY ipmiutillib
+EXPORTS
+ ipmi_cmd
+ ipmi_cmdraw
+ ipmi_close_
+ ipmi_set_mc
+ ipmi_get_mc
+ ipmi_restore_mc
+ ipmi_cmd_mc
+ ipmi_cmdraw_mc
+ parse_lan_options
+ print_lan_opt_usage
+ set_lan_options
+ get_lan_options
+ set_max_kcs_loops
+ get_driver_type
+ set_driver_type
+ get_nodename
+ nodeislocal
+ is_remote
+ ipmi_getdeviceid
+ show_devid
+ show_outcome
+ dump_buf
+ decode_rv
+ decode_cc
+ str_icmp
+ strdup_
+ htoi
+ os_usleep
+ write_syslog
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 */
diff --git a/util/isel.c b/util/isel.c
new file mode 100644
index 0000000..c974b24
--- /dev/null
+++ b/util/isel.c
@@ -0,0 +1,884 @@
+/*
+ * 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 <arcress at users.sourceforge.net>
+ *
+ * 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 <stdio.h>
+#ifdef WIN32
+#include <windows.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+#elif defined(DOS)
+#include <dos.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+#else
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <syslog.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 <time.h>
+
+#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
+
+static char *progname = "isel";
+static char *progver = "2.93";
+#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;
+
+ printf("%s: version %s\n",progname,progver);
+ while ((c = getopt(argc,argv,"a:b:cdef:h:l:m:nprs:uwvx: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*/
+ break;
+ case 'h': faddsel = 1; /*undocumented option, to prevent misuse*/
+ addhex = optarg; /*string of 16 hex characters, no spaces*/
+ 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 '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] [-NUPREFTVY]\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();
+ 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);
+ 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;
+ buf[0] = 0;
+ buf[1] = 0;
+ if (addstr != NULL) { /*ASCII text string*/
+ 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 (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;
+ }
+
+ 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 -c\n",
+ vfree);
+ } else if ((vfree/vsize) < ((vtotal * 20)/100)) {
+ printf("WARNING: free space is low (=%d), need to clear with -c\n",
+ vfree);
+ }
+ }
+ }
+do_exit:
+ free_sdr_cache(sdrs);
+ ipmi_close_();
+ // show_outcome(progname,ret);
+ return(ret);
+}
+
+/* end isel.c */
diff --git a/util/iseltime.c b/util/iseltime.c
new file mode 100644
index 0000000..2562202
--- /dev/null
+++ b/util/iseltime.c
@@ -0,0 +1,260 @@
+/*
+ * 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
+ */
+/*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 <windows.h>
+#include <stdio.h>
+#include "getopt.h"
+#elif defined(EFI)
+ // EFI: defined (EFI32) || defined (EFI64) || defined(EFIX64)
+ #ifndef NULL
+ #define NULL 0
+ #endif
+ #include <types.h>
+ #include <libdbg.h>
+ #include <unistd.h>
+ #include <errno.h>
+#elif defined(DOS)
+ #include <dos.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include "getopt.h"
+#else
+/* Linux, Solaris, BSD */
+#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 <time.h>
+#include <string.h>
+#include "ipmicmd.h"
+
+#define GET_SELTIME 0x48
+#define SET_SELTIME 0x49
+/*
+ * Global variables
+ */
+static char * progver = "2.93";
+static char * progname = "iseltime";
+static char fdebug = 0;
+static char fset = 0;
+static uchar ipmi_maj = 0;
+static uchar ipmi_min = 0;
+
+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)
+{
+ char buf[TIMESTR_SZ];
+ int bufsz = TIMESTR_SZ;
+ time_t t;
+
+ strcpy(buf,"00/00/00 00:00:00");
+ t = utc2local(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;
+ 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();
+ 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
+ }
+
+ rv = get_sel_time(&timebuf[0],4);
+ if (rv != 0) {
+ printf("get_sel_time error: ret = %x\n",rv);
+ ipmi_close_();
+ exit(1);
+ }
+ time(&ltime2);
+ printf("Current System time: "); show_time(ltime2);
+ ltime1 = timebuf[0] + (timebuf[1] << 8) + (timebuf[2] << 16) +
+ (timebuf[3] << 24);
+ printf("Current SEL time: "); show_time(ltime1);
+
+ // if (fdebug) ltime3 = utc2local(ltime1);
+
+ if (fset == 1) {
+ /* get current time */
+ time(&ltime2);
+ 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);
+ }
+ }
+ }
+#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 */
diff --git a/util/isensor.c b/util/isensor.c
new file mode 100644
index 0000000..ac93411
--- /dev/null
+++ b/util/isensor.c
@@ -0,0 +1,3680 @@
+/*
+ * isensor.c
+ *
+ * This tool reads the SDR records to return sensor information.
+ * It can use either the Intel /dev/imb driver or VALinux /dev/ipmikcs.
+ *
+ * Author: arcress at users.sourceforge.net
+ * Copyright (c) 2002-2006 Intel Corporation.
+ * Copyright (c) 2009 Kontron America, Inc.
+ *
+ * 07/25/02 Andy Cress created
+ * 10/09/02 Andy Cress v1.1 added decodeValue(RawToFloat) routine
+ * 10/11/02 Andy Cress v1.2 added expon routine
+ * 10/30/02 Andy Cress v1.3 added SDR types 08 & 14
+ * 12/04/02 Andy Cress v1.4 changed dstatus descriptions
+ * 01/29/03 Andy Cress v1.5 added MV OpenIPMI driver support
+ * Hannes Schulz <schulz@schwaar.com>
+ * 1) correct raw readings to floatval
+ * 2) allow extra SDR bytes returned from HP netserver 1000r
+ * Guo Min <guo.min@intel.com>
+ * add -l option for simpler list display
+ * 02/25/03 Andy Cress v1.6 misc cleanup
+ * 05/02/03 Andy Cress v1.7 add PowerOnHours
+ * 07/28/03 Andy Cress v1.8 added -t option for threshold values,
+ * added sample Discovery routine (unfinished),
+ * added ipmi_getdeviceid for completeness.
+ * 09/05/03 Andy Cress v1.9 show SDR OEM subtypes,
+ * fix GetSDR multi-part get for OEM SDRs
+ * stop if SDR Repository is empty
+ * 09/23/03 Andy Cress v1.10 Add options to set thresholds
+ * 10/14/03 Andy Cress v1.11 Fixed sdr offset for ShowThreshold values
+ * 01/15/04 Andy Cress v1.12 Fixed SetThreshold to set hysteresis,
+ * Fixed sens_cap testing in ShowThresh(Full)
+ * 01/30/04 Andy Cress v1.13 Changed field display order, added header,
+ * check for sdr sz below min, added WIN32.
+ * 02/19/04 Andy Cress v1.14 Added SDR type 3 parsing for mBMC
+ * 02/27/04 Andy Cress v1.15 Added check for superuser, more mBMC logic
+ * 03/11/04 Andy Cress v1.16 Added & removed private mBMC code for set
+ * thresholds due to licensing issues
+ * 04/13/04 Andy Cress v1.17 Added -r to show raw SDRs also
+ * 05/05/04 Andy Cress v1.18 call ipmi_close before exit,
+ * fix sresp in GetSDR for WIN32.
+ * 07/07/04 Andy Cress v1.19 Added -a to reArm sensor,
+ * show debug raw reading values only in hex
+ * 08/18/04 Andy Cress v1.20 Added decoding for DIMM status
+ * 11/01/04 Andy Cress v1.21 add -N / -R for remote nodes,
+ * added -U for remote username
+ * 11/19/04 Andy Cress v1.22 added more decoding for compact reading types,
+ * added -w option to wrap thresholds
+ * 11/24/04 ARCress v1.23 added sens_type to display output
+ * 12/10/04 ARCress v1.24 added support for device sdrs also,
+ * fixed sens_cap byte,
+ * 01/10/05 ARCress v1.25 change ShowThresh order, highest to lowest,
+ * change signed exponent type in RawToFloat
+ * 01/13/05 ARCress v1.26 added time display if fwrap
+ * 01/28/05 ARCress v1.27 mod for Power Redundancy SDR status
+ * 02/15/05 ARCress v1.28 added FloatToRaw for -h/-l threshold set funcs,
+ * always take -n sensor_num as hex (like displayed)
+ * 03/07/05 ARCress v1.29 added "LAN Leash Lost" decoding in decode_comp_
+ * added -v to show max/min & hysteresis.
+ * 03/22/05 ARCress v1.30 added OEM subtype 0x60 for BMC TAM
+ * 03/26/05 ARCress v1.31 added battery type to decode_comp_reading
+ * 04/21/05 ARCress v1.32 added error message if -n sensor_num not found,
+ * added more decoding for Power Redund sensor
+ * 06/20/05 ARCress v1.33 if GetSDRRepository cc=0xc1 switch fdevsdrs mode,
+ * also detect fdevsdrs better for ATCA.
+ * 07/28/05 ARCress v1.34 check for Reading init state,
+ * add extra byte to decode_comp_reading()
+ * 09/12/05 ARCress v1.35 don't check superuser for fipmi_lan
+ * 01/26/06 ARCress v1.36 added -i option to only show one sensor index
+ * 03/14/06 ARCress v1.37 added -p option to save persistent thresholds
+ * 04/06/06 ARCress v1.38 show auto/manual rearm
+ * 07/17/06 ARCress v1.39 add -V, add -L, handle RepInfo rc=0xc1
+ * 11/28/06 ARCress v1.46 added -c -m for ATCA child MCs
+ * 08/15/07 ARCress v1.58 filter display if -n sensor_num
+ * 08/29/07 ARCress v1.59 fixed Battery sensor interpretation
+ * 10/31/07 ARCress v2.3 retry GetSDR if cc=0xC5 (lost reservationID)
+ * 01/14/08 ARCress v2.6 add -u param for setting unique thresholds,
+ * always show float when setting thresholds,
+ * fixup in decoding Proc,PS Comp readings
+ * 01/25/08 ARCress v2.7 allow float input with -u thresholds,
+ * add -p persist logic for -u thresholds.
+ */
+/*M*
+Copyright (c) 2002-2006 Intel Corporation.
+Copyright (c) 2009 Kontron America, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ a.. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ b.. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ c.. Neither the name of Intel nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *M*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h> // for: double pow(double x, double y);
+#include <string.h>
+#include <time.h>
+#ifdef WIN32
+#include <windows.h>
+#include "getopt.h"
+#elif defined(DOS)
+#include <dos.h>
+#include "getopt.h"
+#else
+#include <sys/stat.h>
+#if defined(HPUX)
+/* getopt is defined in stdio.h */
+#elif defined(MACOS)
+/* getopt is defined in unistd.h */
+#include <unistd.h>
+#else
+#include <getopt.h>
+#endif
+#endif
+#if defined(LINUX)
+#include <unistd.h>
+#include <sys/types.h>
+#endif
+#include "ipmicmd.h"
+#include "isensor.h"
+
+#define PICMG_CHILD 1 /* show child MCs if -b */
+#define MIN_SDR_SZ 8
+#define SZCHUNK 16 /* SDR chunksize was 8, now 16 */
+#define INIT_SNUM 0xff
+#define N_SGRP 16
+#define THR_EMPTY 999
+
+extern 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); /*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_hp(uchar *sdr,uchar *reading,char *pstring,
+ int slen); /*see oem_hp.c*/
+extern int decode_sensor_dell(uchar *sdr,uchar *reading,char *pstring,
+ int slen); /*see oem_dell.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_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
+ ************************/
+static char *progname = "isensor";
+static char *progver = "2.93";
+#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 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 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 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 82
+#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 ",
+/*22 ACPI*/ "Working",
+/*23 ACPI*/ "Sleeping", /*D2/S2*/
+/*24 ACPI*/ "On",
+/* 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*/ " _ "
+};
+
+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) {
+ 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 */
+ }
+ /* 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;
+ uchar 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);
+ 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);
+ }
+
+ 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*/
+ 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;
+ int asz = 0;
+ int i, len;
+ uchar *sdr;
+ ushort recid;
+
+ if (pcache == NULL) return(num);
+ for (i = 0; asz < sz_sdrs; i++)
+ {
+ sdr = &pcache[asz];
+ len = sdr[4] + 5;
+ recid = sdr[0] + (sdr[1] << 8);
+ asz += len;
+ if (fdebug) printf("SDR[%x] len=%d i=%d\n", recid,len,i);
+ }
+ 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,&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];
+ 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*/
+ if (id == 0) { rv = 0; break; }
+ 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; }
+ }
+ if (rv == 0) memcpy(psdr,sdr,len);
+ return(rv);
+}
+
+uchar
+bitnum(ushort value)
+{
+ uchar ret = 0;
+ int i;
+ /* returns the highest bit number number set in this word. */
+ /* Bit numbers are 1-based in this routine, 0 means no bits set. */
+ /* scan 15 bits (0x7FFF). */
+ for (i = 0; i < 15; i++) {
+ if (value & 0x01) ret = i+1; /*was ret++;*/
+ value = (value >> 1);
+ }
+ return(ret);
+}
+
+static double
+expon(int x, int y)
+{
+ double res;
+ int i;
+ /* compute exponent: x to the power y */
+ res = 1;
+ if (y > 0) {
+ for (i = 0; i < y; i++) res = res * x;
+ } else if (y < 0) {
+ for (i = 0; i > y; i--) res = res / x;
+ } /* else if if (y == 0) do nothing, res=1 */
+ return(res);
+}
+
+double
+RawToFloat(uchar raw, uchar *psdr)
+{
+ double floatval;
+ int m, b, a;
+ uchar ax;
+ int rx, b_exp;
+ SDR01REC *sdr;
+ int signval;
+
+ sdr = (SDR01REC *)psdr;
+ floatval = (double)raw; /*default*/
+
+ // if (raw == 0xff) floatval = 0; else
+ if (sdr->rectype == 0x01) { /* SDR rectype == full */
+ if (fdebug)
+ printf("units=%x base=%d mod=%d (raw=%x, nom_rd=%x)\n",
+ sdr->sens_units,sdr->sens_base,sdr->sens_mod,
+ raw, sdr->nom_reading);
+ m = sdr->m + ((sdr->m_t & 0xc0) << 2);
+ b = sdr->b + ((sdr->b_a & 0xc0) << 2);
+ if (b & 0x0200) b = (b - 0x0400); /*negative*/
+ if (m & 0x0200) m = (m - 0x0400); /*negative*/
+ rx = (sdr->rx_bx & 0xf0) >> 4;
+ if (rx & 0x08) rx = (rx - 0x10); /*negative, fix sign w ARM compilers*/
+ a = (sdr->b_a & 0x3f) + ((sdr->a_ax & 0xf0) << 2);
+ ax = (sdr->a_ax & 0x0c) >> 2;
+ b_exp = (sdr->rx_bx & 0x0f);
+ if (b_exp & 0x08) b_exp = (b_exp - 0x10); /*negative*/
+ //b_exp |= 0xf0; /* negative 8-bit */
+ if ((sdr->sens_units & 0xc0) == 0) { /*unsigned*/
+ floatval = (double)raw;
+ } else { /*signed*/
+ if (raw & 0x80) signval = (raw - 0x100);
+ else signval = raw;
+ floatval = (double)signval;
+ }
+ floatval *= (double) m;
+#ifdef MATH_OK
+ floatval += (b * pow (10,b_exp));
+ floatval *= pow (10,rx);
+#else
+ floatval += (b * expon (10,b_exp));
+ floatval *= expon (10,rx);
+#endif
+ if (fdebug)
+ printf("decode1: m=%d b=%d b_exp=%x rx=%d, a=%d ax=%d l=%x, floatval=%f\n",
+ m,b,b_exp,rx,a,ax,sdr->linear,floatval);
+ switch(sdr->linear) {
+ case 0: /*linear*/
+ break;
+ case 7: /*invert 1/x*/
+ /* skip if zero to avoid dividing by zero */
+ if (raw != 0) floatval = 1 / floatval;
+ break;
+ case 1: /*ln*/
+ case 2: /*log10, log2, e, exp10, exp2, */
+ case 3: /*log2*/
+ case 4: /*e*/
+ case 5: /*exp10*/
+ case 6: /*exp2*/
+ case 8: /*sqr(x)*/
+ case 9: /*cube(x)*/
+ case 10: /*sqrt(x)*/
+ case 11: /*cube-1(x)*/
+ default:
+ if (fdebug) printf("linear mode %x not implemented\n",sdr->linear);
+ break;
+ } /*end-switch linear*/
+ }
+
+#ifdef NOT_LINEAR
+ /* else if (sdr->linear != 7) */
+ {
+ double be, re;
+ rc = GetSensorType(sdr->sens_num,&stype,&rtype);
+ if (fdebug)
+ printf("decode: rc=%x, stype=%x, rtype=%x\n",rc,stype,rtype);
+ if (rc != 0) return(floatval);
+
+ /* GetSensorReadingFactors */
+ rc = GetSensorReadingFactors(sdr->sens_num,raw,&m,&b,&b_exp,&r,&a);
+ if (rc == 0) {
+ // floatval = ((m * raw) + (b * be)) * re;
+ }
+ if (fdebug) printf("decode: rc=%x, floatval=%f\n",rc,floatval);
+ }
+#endif
+
+ return(floatval);
+}
+
+#define IpmiAnalogDataFormatUnsigned 0
+#define IpmiAnalogDataFormat1Compl 1
+#define IpmiAnalogDataFormat2Compl 2
+
+uchar
+FloatToRaw(double val, uchar *psdr, int rounding)
+{
+ double cval;
+ int lowraw, highraw, raw, maxraw, minraw, next_raw;
+ int analog_dfmt;
+
+ analog_dfmt = (psdr[20] >> 6) & 0x03;
+ switch( analog_dfmt )
+ {
+ case IpmiAnalogDataFormat1Compl:
+ lowraw = -127;
+ highraw = 127;
+ minraw = -127;
+ maxraw = 127;
+ next_raw = 0;
+ break;
+ case IpmiAnalogDataFormat2Compl:
+ lowraw = -128;
+ highraw = 127;
+ minraw = -128;
+ maxraw = 127;
+ next_raw = 0;
+ break;
+ case IpmiAnalogDataFormatUnsigned:
+ default:
+ lowraw = 0;
+ highraw = 255;
+ minraw = 0;
+ maxraw = 255;
+ next_raw = 128;
+ break;
+ }
+
+ /* do a binary search for the right nth root value */
+ do {
+ raw = next_raw;
+ cval = RawToFloat( (uchar)raw, psdr );
+ if ( cval < val ) {
+ next_raw = ((highraw - raw) / 2) + raw;
+ lowraw = raw;
+ } else {
+ next_raw = ((raw - lowraw) / 2) + lowraw;
+ highraw = raw;
+ }
+ } while ( raw != next_raw );
+
+ /* Do rounding to get the final value */
+ switch( rounding ) {
+ case 0: /* Round Normal = Round to nearest value */
+ if ( val > cval ) {
+ if ( raw < maxraw ) {
+ double nval;
+ nval = RawToFloat((uchar)(raw+1),psdr);
+ nval = cval + ((nval - cval) / 2.0);
+ if ( val >= nval ) raw++;
+ }
+ } else {
+ if ( raw > minraw ) {
+ double pval;
+ pval = RawToFloat((uchar)(raw-1),psdr);
+ pval = pval + ((cval - pval) / 2.0);
+ if ( val < pval ) raw--;
+ }
+ }
+ break;
+ case 1: /*Round Down*/
+ if ((val < cval) && (raw > minraw )) raw--;
+ break;
+ case 2: /*Round Up*/
+ if ((val > cval) && (raw < maxraw)) raw++;
+ break;
+ }
+ if ( analog_dfmt == IpmiAnalogDataFormat1Compl )
+ if ( raw < 0 ) raw -= 1;
+ return((uchar)raw);
+} /*end FloatToRaw()*/
+
+static int fill_thresholds(double *thrf, uchar *sdr)
+{
+ int rv = 0;
+ uchar *vals;
+ uchar bits;
+
+ // snum = sdr[7];
+ bits = sdr[19]; /*which are settable*/
+ vals = &sdr[36];
+ if (fdebug)
+ printf("fill_thresholds: bits=%02x, values: %f>=%f>=%f, %f<=%f<=%f\n",
+ bits, thrf[0],thrf[1],thrf[2], thrf[3],thrf[4],thrf[5]);
+ if (thrf[0] == THR_EMPTY) {
+ if ((bits & 0x01) != 0) { /*lo-noncrit*/
+ thrf[0] = RawToFloat(vals[5],sdr);
+ rv++;
+ } else thrf[0] = 0;
+ }
+ if (thrf[1] == THR_EMPTY) {
+ if ((bits & 0x02) != 0) { /*lo-crit*/
+ thrf[1] = RawToFloat(vals[4],sdr);
+ rv++;
+ } else thrf[1] = 0;
+ }
+ if (thrf[2] == THR_EMPTY) {
+ if ((bits & 0x04) != 0) { /*lo-unrec*/
+ thrf[2] = RawToFloat(vals[3],sdr);
+ rv++;
+ } else thrf[2] = 0;
+ }
+ if (thrf[3] == THR_EMPTY) {
+ if ((bits & 0x08) != 0) { /*hi-noncrit*/
+ thrf[3] = RawToFloat(vals[2],sdr);
+ rv++;
+ } else thrf[3] = 0;
+ }
+ if (thrf[4] == THR_EMPTY) {
+ if ((bits & 0x10) != 0) { /*hi-crit*/
+ thrf[4] = RawToFloat(vals[1],sdr);
+ rv++;
+ } else thrf[4] = 0;
+ }
+ if (thrf[5] == THR_EMPTY) {
+ if ((bits & 0x20) != 0) { /*hi-unrec*/
+ thrf[5] = RawToFloat(vals[0],sdr);
+ rv++;
+ } else thrf[5] = 0;
+ }
+ if (fdebug)
+ printf("fill_thresholds: after rv=%d values: %f>=%f>=%f, %f<=%f<=%f\n",
+ rv,thrf[0],thrf[1],thrf[2], thrf[3],thrf[4],thrf[5]);
+ return(rv);
+}
+
+char *
+decode_itype(uchar itype)
+{
+ char *retstr;
+ int i;
+ /* Decode the Interrupt Type from Entity Assoc records */
+
+ retstr = tmpstr;
+ if (itype <= 0x0f) sprintf(retstr,"IRQ_%d",itype);
+ else if (itype <= 0x13) {
+ strcpy(retstr,"PCI-A");
+ for (i=0x10;i<itype;i++) retstr[4]++;
+ }
+ else if (itype == 0x14) strcpy(retstr,"SMI");
+ else if (itype == 0x15) strcpy(retstr,"SCI");
+ else if (itype >= 0x20 && itype <= 0x5f)
+ sprintf(retstr,"SysInt_%d",itype-0x20);
+ else if (itype == 0x60) strcpy(retstr,"ACPI/PnP");
+ else if (itype == 0xFF) strcpy(retstr,"NoInt");
+ else strcpy(retstr,"Invalid");
+ return(retstr);
+}
+
+int decode_oem_sensor(uchar *sdr,uchar *reading,char *pstring,int slen)
+{
+ int rv = -1;
+#ifdef METACOMMAND
+ switch(vend_id) {
+ case VENDOR_INTEL:
+ rv = decode_sensor_intel(sdr, reading, pstring, slen);
+ break;
+ case VENDOR_KONTRON:
+ rv = decode_sensor_kontron(sdr, reading, pstring, slen);
+ break;
+ case VENDOR_FUJITSU:
+ rv = decode_sensor_fujitsu(sdr,reading,pstring,slen);
+ break;
+ case VENDOR_SUN:
+ rv = decode_sensor_sun(sdr, reading, pstring, slen);
+ break;
+ case VENDOR_MAGNUM:
+ case VENDOR_SUPERMICRO:
+ case VENDOR_SUPERMICROX:
+ rv = decode_sensor_supermicro(sdr, reading, pstring, slen);
+ 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;
+ 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*/
+}
+
+/*
+ * 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) { /* 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 HSC slot status*/
+ }
+ 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 13: istr = 21; break; /*Off*/
+ case 12: istr = 24; break; /*On*/
+ 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 (reading == 0) istr = 0; /*OK*/
+ else istr = 12; /*Faulty*/
+ 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;
+ case 0x60: /* SCSI 1 Term Flt */
+ case 0x61: /* SCSI 2 Term Flt */
+ 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;
+ default:
+ if (fdebug)
+ printf("sensor[%x] type %02x not decoded, reading = %04x\n",
+ num,type,reading);
+ istr = STR_OTHER; /* other " - " */
+ }
+ 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) {
+ printf("raw SDR: ");
+ for (i = 0; i < len; i++)
+ printf("%02x ",sdr[i]);
+ printf("\n");
+ }
+ 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);
+ printf("Bad SDR Length, please apply the correct FRU/SDR diskette\n");
+ return;
+ }
+ sens_cap = sdr[11]; /*sdr01->sens_capab*/
+ 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 */
+ if ((sdr01->sens_capab & 0x40) == 0) brearm = 'm'; /*manual rearm*/
+ else brearm = 'a'; /*automatic rearm*/
+ if (fdebug) printf("entity %d.%d, idlen=%d sizeof=%d 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 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) {
+ strncpy(rdgstr,oem_string,sizeof(rdgstr));
+ } 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(&ltime);
+ if (fsimple)
+ printf("%c %s",bdelim,ctime(&ltime)); /*ctime has '\n' */
+ else
+ printf("at %s",ctime(&ltime)); /*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);
+ printf("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=%d, 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(&ltime);
+ if (fsimple)
+ printf("%c %s",bdelim,ctime(&ltime)); /*ctime has '\n' */
+ else
+ printf("at %s",ctime(&ltime)); /*ctime has '\n' */
+ }
+ break;
+ case 0x03: /* Event-only sensor record, treat like Compact SDR */
+ sdr02 = (SDR02REC *)sdr;
+ ioff = 17;
+ if (ioff > len) {
+ printf("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=%d, 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=%d, 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);
+ if (resp[0] == 0) /*avoid div-by-zero*/ i = 1;
+ else if (resp[0] == 60) /*normal*/ 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 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,"r");
+ if (fp == NULL) {
+ ret = get_LastError();
+ printf("Cannot open file %s, error %d\n",binfile,ret);
+ return(ret);
+ }
+#ifndef WIN32
+ {
+ 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
+ // len = nsdrs * SDR_SZ; /*estimate max size for n sdrs*/
+ sz_sdrs = len;
+ pbuf = malloc(len);
+ if (fdebug) printf("restore: malloc(%d) pbuf=%p\n",len,pbuf);
+ if (pbuf == NULL) {
+ ret = -1;
+ fclose(fp);
+ return(ret);
+ }
+ /*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*/
+ }
+ 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;
+ 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: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 't': fshowthr = 1; break;
+ case 'v': fshowthr = 1; sens_verbose = 1; break;
+ case 'p': fsavethresh = 1; break;
+ case 'q': fshowthr = 2; fwrap = 1; break;
+ case 'r': frawsdr = 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 '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 '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 -NUPREFTVY]\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 ids\n");
+ printf(" -j file Jump-start SDR cache from a binary file\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\n");
+ print_lan_opt_usage();
+ 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);
+ 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 (prod_id == 0x003E || fRomley) /*Urbanna NSN2U,CG2100*/
+ set_max_kcs_loops(URNLOOPS); /*longer KCS timeout*/
+ } 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) {
+ uchar *pbuf = NULL;
+ FILE *fp;
+ int len;
+ ret = get_sdr_cache(&pbuf);
+ if (ret == 0) {
+ fp = fopen(binfile,"w");
+ if (fp == NULL) {
+ ret = get_LastError();
+ printf("Cannot open file %s, 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);
+ }
+ 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) fjumpstart = 0; /* use normal method if error*/
+ 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;
+ while (recid != 0xffff)
+ {
+ if (fjumpstart) {
+ ret = find_sdr_next(sdrdata,psdrcache,recid);
+ if (ret != 0) { ret = 0; break; } /*end of sdrs*/
+ recnext = sdrdata[0] + (sdrdata[1] << 8); /*same as recid*/
+ 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 */
+ printf("%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);
+ }
+ } 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 */
+ }
+ } /*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) {
+ printf("%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 (fshowidx) {
+ /* if we have already read the last in the range, done. */
+ if (recid >= sensor_idxN) break; // recnext = 0xffff; // break;
+ }
+ if (fjumpstart) recid = recnext;
+ else {
+ if (recnext == recid) recid = 0xffff; /*break;*/
+ else recid = recnext;
+ }
+ } /*end while recid*/
+ if (fdoloop && (nloops > 1)) {
+ printf("\n"); /* output an empty separator line */
+ os_usleep(1,0); /*delay 1 sec between loops*/
+ }
+ } /*end for nloops*/
+
+ if (npass > 1) { /* npass==2 for PICMG */
+ /* Switch fdevsdrs from Device to Repository */
+ if (fdevsdrs == 0) fdevsdrs = 1;
+ else fdevsdrs = 0;
+ fDoReserve = 1; /* get a new SDR Reservation ID */
+ }
+ } /*end for npass*/
+
+ if ((fshowidx == 0) && (fshowgrp == 0)) {
+ /* use local rv, errors are ignored for POH */
+ rv = ShowPowerOnHours();
+ }
+
+ if (frearm != 0) {
+ ret = RearmSensor((uchar)frearm);
+ printf("RearmSensor(0x%02x) ret = %d\n",frearm,ret);
+ }
+
+ if (fsetthresh != 0) {
+ uchar tdata[7];
+ if (fsetfound == 0) {
+ printf("Did not find sensor number %02x.\nPlease enter the sensor number parameter in hex, as it is displayed above.\n",sensor_num);
+ }
+ ret = GetSensorThresholds(sensor_num,tdata);
+ if (ret != 0) goto do_exit;
+#ifdef TEST
+ printf("thresh(%02x): %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ sensor_num, sensor_num, tdata[0], tdata[1], tdata[2],
+ tdata[3], tdata[4], tdata[5], tdata[6]);
+ printf(" set(%02x): %02x %02x \n",
+ sensor_num,sensor_lo,sensor_hi);
+#endif
+ if (fsetthresh == 3 || fsetthresh == 4) {
+ /* apply unique sensor thresholds */
+ pset = &sensor_thr[0];
+ } else pset = NULL; /* use just hi/lo */
+ ret = SetSensorThresholds(sensor_num,sensor_hi,sensor_lo,tdata,pset);
+ printf("SetSensorThreshold[%02x] to lo=%02x(%4.3f) hi=%02x(%4.3f), ret = %d\n",
+ sensor_num,sensor_lo,sensor_lo_f,sensor_hi,sensor_hi_f,ret);
+ if (fsavethresh && ret == 0) {
+ recid = fsetfound;
+ rv = SaveThreshold(recid,sensor_num,sensor_lo,sensor_hi,pset);
+ if (rv == 0)
+ printf("Saved thresholds for sensor %02x\n",sensor_num);
+ }
+ fsetthresh = 0; /*only set threshold once*/
+ }
+
+do_exit:
+ if (fjumpstart) free_sdr_cache(psdrcache); /* does nothing if ==NULL*/
+ /* show_outcome(progname,ret); *handled in ipmiutil.c*/
+ ipmi_close_();
+ return(ret);
+}
+
+/* end isensor.c */
diff --git a/util/isensor.h b/util/isensor.h
new file mode 100644
index 0000000..8927b6e
--- /dev/null
+++ b/util/isensor.h
@@ -0,0 +1,176 @@
+/*
+ * 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;
+ uchar ev_type;
+ 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);
+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 */
diff --git a/util/iserial.c b/util/iserial.c
new file mode 100644
index 0000000..ce00ed3
--- /dev/null
+++ b/util/iserial.c
@@ -0,0 +1,1592 @@
+/*
+ * 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 <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "getopt.h"
+#elif defined(DOS)
+#include <dos.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.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
+#include <string.h>
+#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
+ */
+static char * progver = "2.93";
+static char * progname = "iserial";
+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();
+ 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) {
+ /* Apparently this always shows 0x01 even if System. */
+ 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: <ESC>( and <ESC>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 */
diff --git a/util/isol.c b/util/isol.c
new file mode 100644
index 0000000..381668e
--- /dev/null
+++ b/util/isol.c
@@ -0,0 +1,1347 @@
+/*
+ * 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 <dos.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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 <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <winsock.h>
+#include <io.h>
+#include "getopt.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <termios.h>
+#include <unistd.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 <time.h>
+#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
+ */
+static char * progver = "2.93";
+static char * progname = "isol";
+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 *)&ltime1);
+
+ 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 *)&ltime2);
+ 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();
+}
+
+#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: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 '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_SUPERMICRO:
+ 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
+ * Using globals: gnode,guser,gpswd, gauth_type, gpriv_level
+ */
+ 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 */
diff --git a/util/isolwin.c b/util/isolwin.c
new file mode 100644
index 0000000..b8f7926
--- /dev/null
+++ b/util/isolwin.c
@@ -0,0 +1,293 @@
+/*
+ * 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 <windows.h>
+#include <stdio.h>
+#include <winsock.h>
+#include <io.h>
+#include <conio.h>
+#include <string.h>
+#include <time.h>
+
+#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*/
diff --git a/util/itsol.c b/util/itsol.c
new file mode 100644
index 0000000..dc4d9fb
--- /dev/null
+++ b/util/itsol.c
@@ -0,0 +1,725 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef WIN32
+#include <windows.h>
+#include <winsock.h>
+#include <io.h>
+#include <time.h>
+#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 <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#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 <unistd.h>
+#include <stdint.h>
+#undef POLL_OK
+#else
+#include <getopt.h>
+#include <sys/poll.h>
+#define POLL_OK 1
+#endif
+
+#if defined (HAVE_SYS_TERMIOS_H)
+#include <sys/termios.h>
+#else
+// #if defined(HAVE_TERMIOS_H)
+#include <termios.h>
+#endif
+
+#endif
+
+#include "ipmicmd.h"
+#include "itsol.h"
+
+extern int verbose;
+extern char fdebug; /*from ipmicmd.c*/
+static char * progname = "itsol";
+static char * progver = "2.93";
+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; i<argc; i++) {
+ if (sscanf(argv[i], "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) == 4)
+ recvip = strdup_(argv[i]);
+ else if (sscanf(argv[i], "port=%d", &ip1) == 1)
+ port = ip1;
+ else if (sscanf(argv[i], "rows=%d", &ip1) == 1)
+ rows = ip1;
+ else if (sscanf(argv[i], "cols=%d", &ip1) == 1)
+ cols = ip1;
+ else if (strlen(argv[i]) == 2 && strncmp(argv[i], "ro", 2) == 0)
+ read_only = 1;
+ else if (strlen(argv[i]) == 2 && strncmp(argv[i], "rw", 2) == 0)
+ read_only = 0;
+ else if (strlen(argv[i]) == 7 && strncmp(argv[i], "altterm", 7) == 0)
+ _altterm = 1;
+ else if (strlen(argv[i]) == 4 && strncmp(argv[i], "help", 4) == 0) {
+ print_tsol_usage();
+ return 0;
+ }
+ else {
+ print_tsol_usage();
+ return 0;
+ }
+ }
+
+ get_lan_options(hostname,NULL,NULL,&hauth, &hpriv, &hcipher,NULL,NULL);
+ result = open_sockfd(hostname, &sockfd, &haddr, &haddrlen, 1);
+ if (result) {
+ lperror(LOG_ERR, "Connect to %s failed",hostname);
+ return result;
+ }
+
+#ifdef WIN32
+ /* TODO: implement terminal handling for Windows here. */
+ printf("Windows TSOL terminal handling not yet implemented\n");
+ if (recvip != NULL)
+ result = ipmi_tsol_stop(intf, recvip, port);
+ return LAN_ERR_NOTSUPPORT;
+#elif defined(MACOS)
+ printf("MacOS TSOL terminal handling not yet implemented\n");
+ if (recvip != NULL)
+ result = ipmi_tsol_stop(intf, recvip, port);
+ return LAN_ERR_NOTSUPPORT;
+#else
+ /*
+ * retrieve local IP address if not supplied on command line
+ */
+ if (recvip == NULL) {
+ set_lan_options(hostname,NULL,NULL,hauth, hpriv, hcipher,
+ (void *)&haddr,haddrlen);
+ result = ipmi_open(fdebug); /* must connect first */
+ if (result < 0)
+ return -1;
+
+ memset(&myaddr, 0, sizeof(myaddr));
+ memset(mystr, 0, sizeof(mystr));
+ mylen = sizeof(myaddr);
+ if (getsockname(sockfd, (struct sockaddr *)&myaddr, &mylen) < 0) {
+ lperror(LOG_ERR, "getsockname failed");
+ return -1;
+ }
+
+ recvip = (char *)inet_ntop(((struct sockaddr *)&myaddr)->sa_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 */
+
diff --git a/util/itsol.h b/util/itsol.h
new file mode 100644
index 0000000..ec28d3f
--- /dev/null
+++ b/util/itsol.h
@@ -0,0 +1,66 @@
+/*
+ * 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 <ipmitool/ipmi.h>
+
+#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 */
diff --git a/util/iwdt.c b/util/iwdt.c
new file mode 100644
index 0000000..96d21c0
--- /dev/null
+++ b/util/iwdt.c
@@ -0,0 +1,415 @@
+/*
+ * 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 <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "getopt.h"
+#elif defined(EFI)
+ // EFI: defined (EFI32) || defined (EFI64) || defined(EFIX64)
+ #ifndef NULL
+ #define NULL 0
+ #endif
+ #include <types.h>
+ #include <libdbg.h>
+ #include <unistd.h>
+ #include <errno.h>
+#elif defined(DOS)
+ #include <dos.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include "getopt.h"
+#else
+/* Linux, Solaris, BSD */
+#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"
+
+/*
+ * Global variables
+ */
+static char * progver = "2.93";
+static char * progname = "iwdt";
+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();
+ 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 */
diff --git a/util/md2.c b/util/md2.c
new file mode 100644
index 0000000..f1b4796
--- /dev/null
+++ b/util/md2.c
@@ -0,0 +1,99 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#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 <openssl/evp.h>
+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 */
diff --git a/util/md2.h b/util/md2.h
new file mode 100644
index 0000000..29c77fd
--- /dev/null
+++ b/util/md2.h
@@ -0,0 +1,269 @@
+/*
+ * 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
+ */
+/*
+ Copyright (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, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ A copy of the GNU General Public License is available as
+ /usr/share/common-licenses/GPL-2 in the Debian distribution or on
+ the World Wide Web at http://www.gnu.org/copyleft/gpl.html. You can
+ also obtain it by writing to the Free Software Foundation, Inc.,
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+/* 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 */
diff --git a/util/md5.c b/util/md5.c
new file mode 100644
index 0000000..9f4db4e
--- /dev/null
+++ b/util/md5.c
@@ -0,0 +1,413 @@
+/*
+ * 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
+ <ghost@aladdin.com>. 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 <string.h>
+ 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 <stdio.h> 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 <string.h>
+
+/* $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);
+}
diff --git a/util/mem_if.c b/util/mem_if.c
new file mode 100644
index 0000000..c445138
--- /dev/null
+++ b/util/mem_if.c
@@ -0,0 +1,900 @@
+/*----------------------------------------------------------------------*
+ * 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 <windows.h>
+#include <stdio.h>
+#include <iostream> //deprecated iostream.h
+#include <Objbase.h> //ole32.lib
+#include <comutil.h>
+#include <Wbemcli.h> //Wbemcli.h,Wbemidl.h Wbemuuid.lib
+
+#elif defined(DOS)
+#include <dos.h>
+#include <stdlib.h>
+#include <string.h>
+
+#else // Linux or Solaris
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#endif
+#if defined(SOLARIS) || defined(BSD)
+#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;
+ //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;
+ 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<pSmBios[SMBIOS_TABLE_LENGTH_OFFSET]; iInc++)
+ ucCheckSum += pSmBios[iInc];
+
+ if (ucCheckSum)
+ {
+ UnMapPhysicalMemory(tdVirtualAddress,ulSize);
+ fprintf(stderr, "_SM_ Checksum != 0.\n");
+ return ulSmBiosLen;
+ }
+
+ //save smbios revision for future calls...bcd format
+ s_iTableRev = (pSmBios[SMBIOS_MAJOR_REV_OFFSET]<<NIBBLE_SIZE) | pSmBios[SMBIOS_MINOR_REV_OFFSET];
+
+ //find smbios table entry point and size of tables
+ memcpy(&tdStartAddress,&pSmBios[SMBIOS_TABLE_ENTRY_POINT_OFFSET],4);
+ //sizeof(ULONG));
+ memcpy(&ulSmBiosLen,&pSmBios[SMBIOS_TABLE_SIZE_OFFSET],sizeof(USHORT));
+ memcpy(&ucVal,&pSmBios[SMBIOS_TABLE_SIZE_OFFSET],sizeof(UCHAR));
+ memcpy(&ucVal1,&pSmBios[SMBIOS_TABLE_SIZE_OFFSET+1],sizeof(UCHAR));
+
+
+ //unmap physical memory (f0000-ffffe)
+ UnMapPhysicalMemory(tdVirtualAddress,ulSize);
+
+ if (!MapPhysicalMemory(tdStartAddress,ulSmBiosLen,&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 0;
+ }
+
+ if (fsm_debug) {
+ printf("MapMemory(%lx,%lx) ok = %lx\n",tdStartAddress,
+ ulSmBiosLen,tdVirtualAddress);
+ // dump_buf("Table",(UCHAR *)tdVirtualAddress,256,1);
+ }
+ //set size_t smbios tables starting address to ptr
+ *ptableAddress = (UCHAR*)tdVirtualAddress;
+
+ //Not doing this since the map is needed
+ // UnMapPhysicalMemory(tdVirtualAddress,ulSmBiosLen);
+ // rv = CloseIMemoryInterface();
+ return ulSmBiosLen;
+}
+
+int closeSmBios(UCHAR *ptableAddress, ULONG ulSmBiosLen)
+{
+ int rv;
+ UnMapPhysicalMemory((size_t)ptableAddress,ulSmBiosLen);
+ rv = CloseIMemoryInterface();
+ return(rv);
+}
+#endif // Linux (not WIN32)
+
+#ifdef WIN32
+extern "C" {
+#endif
+///////////////////////////////////////////////////////////////////////////////
+// getSmBiosRev
+// return the revision of smbios...in bcd format
+// Integer
+///////////////////////////////////////////////////////////////////////////////
+int getSmBiosRev()
+{
+ return s_iTableRev;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// get_IpmiStruct
+//////////////////////////////////////////////////////////////////////////////
+// Name: get_IpmiStruct
+// Purpose: find Type 38 record to get the IPMI Version.
+// Returns: 0 for success, or -1 if not found.
+// if success, all 4 parameters will have valid data
+//////////////////////////////////////////////////////////////////////////////
+int get_IpmiStruct(UCHAR *iftype, UCHAR *ver, UCHAR *sa, int *base, UCHAR *inc)
+{
+ UCHAR *VirtualAddress;
+ ULONG SMBiosLen = 0;
+ int length, j, i;
+ UCHAR Type;
+ int rv = -1;
+
+ SMBiosLen = getSmBiosTables( &VirtualAddress);
+ if ((SMBiosLen == 0) || !VirtualAddress) return rv;
+
+ 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 == 38) //Found the IPMI Device Information record
+ {
+ if (fsm_debug) {
+ int j;
+ printf("IPMI record: ");
+ for (j = i; j < i+length; j++)
+ printf("%02x ",VirtualAddress[j]);
+ printf("\n");
+ }
+ /*
+ * Byte 05h is the IPMI version as X.Y
+ * where X is bits 7:4 and Y bits 3:0
+ *
+ * KCS Iv sa nv base_addr
+ * 26 12 01 00 01 20 20 ff a3 0c 00 00 00 00 00 00 00 00
+ * IPMI 2.0 KCS, sa=0x20 Base=0x0ca2, spacing=1
+ * 26 12 73 00 01 20 20 ff a9 0c 00 00 00 00 00 00 40 00
+ * IPMI 2.0 KCS, sa=0x20 Base=0x0ca8, spacing=4
+ * 26 10 44 00 04 15 84 01 01 04 00 00 00 00 00 00
+ * IPMI v1.5 SMBus sa=0x42, base=0x0000000401
+ */
+ *iftype = VirtualAddress[i+4];
+ *ver = VirtualAddress[i+5];
+ *sa = VirtualAddress[i+6];
+ j = VirtualAddress[i+8] +
+ (VirtualAddress[i+9] << 8) +
+ (VirtualAddress[i+10] << 16) +
+ (VirtualAddress[i+11] << 24);
+ /*if odd, then subtract 1 from base addr*/
+ if (j & 0x01) j -= 1;
+ *base = j;
+ /* detect Register Spacing */
+ *inc = 1; /*default*/
+ if ((*iftype != 0x04) && (length >= 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 */
diff --git a/util/mem_if_cpp.cpp b/util/mem_if_cpp.cpp
new file mode 100644
index 0000000..19468f2
--- /dev/null
+++ b/util/mem_if_cpp.cpp
@@ -0,0 +1,5 @@
+// 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"
diff --git a/util/oem_dell.c b/util/oem_dell.c
new file mode 100644
index 0000000..1911d96
--- /dev/null
+++ b/util/oem_dell.c
@@ -0,0 +1,6095 @@
+/*
+ * 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
+* <deepaganesh_paulraj@dell.com>
+*
+* This code implements a dell OEM proprietary commands.
+* This Code is edited and Implemented the License feature for Delloem
+* Author Harsha S <Harsha_S1@dell.com>
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef WIN32
+#include <windows.h>
+#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 <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <ctype.h>
+#include <limits.h>
+#if defined(HPUX)
+/* getopt is defined in stdio.h */
+#elif defined(MACOS)
+/* getopt is defined in unistd.h */
+#include <unistd.h>
+#include <stdint.h>
+#else
+#include <getopt.h>
+#endif
+#endif
+
+#include <time.h>
+#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"
+ };
+
+static char * progver = "2.93";
+static char * progname = "idelloem";
+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 <on | off>");
+ 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 = {0};
+ 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 <command> [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 <command> 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 = {0};
+ 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 = {0};
+ 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 = {0};
+ 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 = {0};
+ 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 = {0};
+ 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 = {0};
+ 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 = {0};
+ 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 = {0};
+ uint8_t data[4];
+ uint8_t command = 0;
+ IPMI_DELL_LCD_CAPS* lcd_caps;
+ char lcdstring[IPMI_DELL_LCD_STRING_LENGTH_MAX+1] = {0};
+ int rc;
+
+
+ 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);
+
+ rc = 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 = {0};
+ uint8_t data[4];
+ IPMI_DELL_LCD_CAPS * lcd_caps;
+ uint8_t command = 0;
+ char lcdstring[IPMI_DELL_LCD_STRING_LENGTH_MAX+1] = {0};
+ int rc;
+
+ 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);
+ rc = 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 = {0};
+ 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 = {0};
+ 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 = {0};
+ 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 = {0};
+ 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 = {0};
+ 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 = {0};
+ 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 <text>}");
+ 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}<text>");
+ 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<active|inactive>");
+ 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<MAX_LOM;i++)
+ {
+#ifdef LOM_OLD
+ EmbeddedNICMacAddress.LOMMacAddress[i].BladSlotNumber = 0;
+ EmbeddedNICMacAddress.LOMMacAddress[i].MacType = LOM_MACTYPE_RESERVED;
+ EmbeddedNICMacAddress.LOMMacAddress[i].EthernetStatus = LOM_ETHERNET_RESERVED;
+ EmbeddedNICMacAddress.LOMMacAddress[i].NICNumber = 0;
+ EmbeddedNICMacAddress.LOMMacAddress[i].Reserved = 0;
+#else
+ EmbeddedNICMacAddress.LOMMacAddress[i].b0 = 0xF0;
+ EmbeddedNICMacAddress.LOMMacAddress[i].b1 = 0x00;
+#endif
+ for (j=0;j<MACADDRESSLENGH;j++)
+ {
+ EmbeddedNICMacAddress.LOMMacAddress[i].MacAddressByte[j] = 0;
+ EmbeddedNICMacAddress_10G.MacAddress[i].MacAddressByte[j] = 0;
+ }
+ }
+}
+
+uint8_t UseVirtualMacAddress = 0;
+#define VIRTUAL_MAC_OFFSET (2)
+static int ipmi_macinfo_drac_idrac_virtual_mac(void* intf,uint8_t NicNum)
+{
+ uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv;
+ struct ipmi_rq req;
+
+ uint8_t msg_data[30];
+ uint8_t VirtualMacAddress [MACADDRESSLENGH];
+ uint8_t input_length=0;
+ uint8_t j;
+ //uint8_t length;
+ uint8_t i;
+
+
+ if (0xff==NicNum || IDRAC_NIC_NUMBER==NicNum )
+ {
+ UseVirtualMacAddress = 0;
+
+ input_length = 0;
+ msg_data[input_length++] = 1; /*Get*/
+
+ req.msg.netfn = IPMI_DELL_OEM_NETFN;
+ req.msg.lun = 0;
+ req.msg.cmd = GET_IDRAC_VIRTUAL_MAC;
+ req.msg.data = msg_data;
+ req.msg.data_len = input_length;
+
+ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len);
+ if (rv) { return rv; }
+
+ if( (IMC_IDRAC_12G_MODULAR == IMC_Type) || (IMC_IDRAC_12G_MONOLITHIC== IMC_Type) ) {
+ // Get the Chasiss Assigned MAC Addresss for 12g Only
+ memcpy(VirtualMacAddress,&rsp[1],MACADDRESSLENGH);
+
+ for (i=0;i<MACADDRESSLENGH;i++)
+ {
+ if (0 != VirtualMacAddress [i])
+ {
+ UseVirtualMacAddress = 1;
+ }
+ }
+ // Get the Server Assigned MAC Addresss for 12g Only
+ if(!UseVirtualMacAddress) {
+ memcpy(VirtualMacAddress,&rsp[1+MACADDRESSLENGH],MACADDRESSLENGH);
+
+ for (i=0;i<MACADDRESSLENGH;i++)
+ {
+ if (0 != VirtualMacAddress [i])
+ {
+ UseVirtualMacAddress = 1;
+ }
+ }
+ }
+ } else {
+ memcpy(VirtualMacAddress,&rsp[VIRTUAL_MAC_OFFSET],MACADDRESSLENGH);
+
+ for (i=0;i<MACADDRESSLENGH;i++)
+ {
+ if (0 != VirtualMacAddress [i])
+ {
+ UseVirtualMacAddress = 1;
+ }
+ }
+ }
+ if (0 == UseVirtualMacAddress)
+ return -1;
+ if (IMC_IDRAC_10G == IMC_Type)
+ printf ("\nDRAC MAC Address ");
+ else if ( (IMC_IDRAC_11G_MODULAR == IMC_Type) || (IMC_IDRAC_11G_MONOLITHIC== IMC_Type) )
+ printf ("\niDRAC6 MAC Address ");
+ else if ( (IMC_IDRAC_12G_MODULAR == IMC_Type) || (IMC_IDRAC_12G_MONOLITHIC== IMC_Type) )
+ printf ("\niDRAC7 MAC Address ");
+
+ for (j=0;j<5;j++)
+ printf("%02x:",VirtualMacAddress[j]);
+ printf("%02x",VirtualMacAddress[j]); /*5*/
+
+ printf ("\n\r");
+
+ }
+ return 0;
+}
+
+
+/*****************************************************************
+* Function Name: ipmi_macinfo_drac_idrac_mac
+*
+* Description: This function retrieves the mac address of DRAC or iDRAC
+* Input: NicNum
+* Output:
+* Return:
+*
+******************************************************************/
+
+static int ipmi_macinfo_drac_idrac_mac(void* intf,uint8_t NicNum)
+{
+ 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 iDRAC6MacAddressByte[MACADDRESSLENGH];
+ uint8_t j;
+
+ ipmi_macinfo_drac_idrac_virtual_mac (intf,NicNum);
+
+
+ if ((0xff==NicNum || IDRAC_NIC_NUMBER==NicNum) && 0 == UseVirtualMacAddress)
+ {
+
+ input_length = 0;
+
+ msg_data[input_length++] = LAN_CHANNEL_NUMBER;
+ msg_data[input_length++] = MAC_ADDR_PARAM;
+ msg_data[input_length++] = 0x00;
+ msg_data[input_length++] = 0x00;
+
+ req.msg.netfn = TRANSPORT_NETFN;
+ req.msg.lun = 0;
+ req.msg.cmd = GET_LAN_PARAM_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 MAC Address: ");
+ if (rv < 0) printf("no response\n");
+ else printf("Completion Code 0x%02x\n", rv);
+ return rv;
+ }
+
+ memcpy(iDRAC6MacAddressByte,&rsp[PARAM_REV_OFFSET],MACADDRESSLENGH);
+
+ if (IMC_IDRAC_10G == IMC_Type)
+ printf ("\n\rDRAC MAC Address ");
+ else if ((IMC_IDRAC_11G_MODULAR == IMC_Type) || (IMC_IDRAC_11G_MONOLITHIC== IMC_Type))
+ printf ("\n\riDRAC6 MAC Address ");
+ else if ((IMC_IDRAC_12G_MODULAR == IMC_Type) || (IMC_IDRAC_12G_MONOLITHIC== IMC_Type))
+ printf ("\n\riDRAC7 MAC Address ");
+ else
+ printf ("\n\riDRAC6 MAC Address ");
+
+ for (j=0;j<5;j++)
+ printf("%02x:",iDRAC6MacAddressByte[j]);
+ printf("%02x",iDRAC6MacAddressByte[j]);
+
+ printf ("\n\r");
+ }
+ return 0;
+}
+
+
+/*****************************************************************
+* Function Name: ipmi_macinfo_10g
+*
+* Description: This function retrieves the mac address of LOMs
+* Input: intf - ipmi interface
+ NicNum - NIC number
+* Output:
+* Return:
+*
+******************************************************************/
+
+static int ipmi_macinfo_10g (void* intf, uint8_t NicNum)
+{
+ 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;
+ uint8_t i;
+
+ uint8_t Total_No_NICs = 0;
+
+
+ InitEmbeddedNICMacAddressValues ();
+
+ memset(msg_data, 0, sizeof(msg_data));
+ input_length = 0;
+ msg_data[input_length++] = 0x00; /* Get Parameter Command */
+ msg_data[input_length++] = EMB_NIC_MAC_ADDRESS_9G_10G; /* OEM Param */
+
+ msg_data[input_length++] = 0x00;
+ msg_data[input_length++] = 0x00;
+
+ memset(&req, 0, sizeof(req));
+
+ req.msg.netfn = APP_NETFN;
+ req.msg.lun = 0;
+ req.msg.cmd = GET_SYSTEM_INFO_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 MAC Address: ");
+ if (rv < 0) printf("no response\n");
+ else printf("Completion Code 0x%02x\n", rv);
+ return rv;
+ }
+ if (fdebug) dump_buf("GetMacResp_10G",rsp,rsp_len,0);
+
+ Total_No_NICs = (uint8_t) rsp[PARAM_REV_OFFSET]; /* Byte 1: Total Number of Embedded NICs */
+
+ if (IDRAC_NIC_NUMBER != NicNum)
+ {
+ if (0xff == NicNum)
+ {
+ printf ("\n\rSystem LOMs");
+ }
+ printf("\n\rNIC Number\tMAC Address\n\r");
+
+ memcpy(&EmbeddedNICMacAddress_10G,&rsp[PARAM_REV_OFFSET+TOTAL_N0_NICS_INDEX],Total_No_NICs* MACADDRESSLENGH);
+
+
+ /*Read the LOM type and Mac Addresses */
+
+ for (i=0;i<Total_No_NICs;i++)
+ {
+ if ((0xff==NicNum) || (i == NicNum) )
+ {
+ printf ("\n\r%d",i);
+ printf ("\t\t");
+ for (j=0;j<5;j++)
+ {
+ printf("%02x:",EmbeddedNICMacAddress_10G.MacAddress[i].MacAddressByte[j]);
+ }
+ printf("%02x",EmbeddedNICMacAddress_10G.MacAddress[i].MacAddressByte[j]);
+ }
+ }
+ printf ("\n\r");
+
+ }
+
+ ipmi_macinfo_drac_idrac_mac(intf,NicNum);
+
+
+ return 0;
+}
+
+
+/*****************************************************************
+* Function Name: ipmi_macinfo_11g
+*
+* Description: This function retrieves the mac address of LOMs
+* Input: intf - ipmi interface
+* Output:
+* Return:
+*
+******************************************************************/
+
+static int ipmi_macinfo_11g (void* intf, uint8_t NicNum)
+{
+ 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 len;
+ uint8_t j;
+ uint8_t offset;
+ uint8_t maxlen;
+ uint8_t loop_count;
+ uint8_t i;
+ uint8_t lom_mactype;
+ uint8_t lom_nicnum;
+ uint8_t lom_ethstat;
+ uint8_t *lom_mac;
+ // uint8_t LOMStatus = 0;
+ // uint8_t PlayingDead = 0;
+
+ offset = 0;
+ len = 8; /*eigher 8 or 16 */
+ maxlen = 64;
+ loop_count = maxlen / len;
+
+ InitEmbeddedNICMacAddressValues ();
+
+ memset(msg_data, 0, sizeof(msg_data));
+ input_length = 0;
+ msg_data[input_length++] = 0x00; /* Get Parameter Command */
+ msg_data[input_length++] = EMB_NIC_MAC_ADDRESS_11G; /* OEM Param */
+
+ msg_data[input_length++] = 0x00;
+ msg_data[input_length++] = 0x00;
+ msg_data[input_length++] = 0x00;
+ msg_data[input_length++] = 0x00;
+
+ memset(&req, 0, sizeof(req));
+
+ req.msg.netfn = APP_NETFN;
+ req.msg.lun = 0;
+ req.msg.cmd = GET_SYSTEM_INFO_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 MAC Address: ");
+ if (rv < 0) printf("no response\n");
+ else printf("Completion Code 0x%02x\n", rv);
+ return rv;
+ }
+
+ len = 8; /*eigher 8 or 16 */
+ maxlen = (uint8_t) rsp[0+PARAM_REV_OFFSET];
+ loop_count = maxlen / len;
+
+ if (IDRAC_NIC_NUMBER != NicNum)
+ {
+ if (0xff == NicNum)
+ {
+ printf ("\n\rSystem LOMs");
+ }
+ printf("\n\rNIC Number\tMAC Address\t\tStatus\n\r");
+
+
+ /*Read the LOM type and Mac Addresses */
+ offset=0;
+ for (i=0;i<loop_count;i++,offset=offset+len)
+ {
+ input_length = 4;
+ msg_data[input_length++] = offset;
+ msg_data[input_length++] = len;
+
+ req.msg.netfn = APP_NETFN;
+ req.msg.lun = 0;
+ req.msg.cmd = GET_SYSTEM_INFO_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 MAC Address: ");
+ if (rv < 0) printf("no response\n");
+ else printf("Completion Code 0x%02x\n", rv);
+ return rv;
+ }
+ if (fdebug) {
+ printf("ipmi_macinfo_11g(%d) i=%d offset=%d\n",NicNum,i,offset);
+ dump_buf("GetMacResp",rsp,rsp_len,0);
+ }
+
+ memcpy(&(EmbeddedNICMacAddress.LOMMacAddress[i]),&rsp[PARAM_REV_OFFSET],len);
+
+#ifdef LOM_OLD
+ lom_ethstat = EmbeddedNICMacAddress.LOMMacAddress[i].EthernetStatus;
+ lom_mactype = EmbeddedNICMacAddress.LOMMacAddress[i].MacType;
+ lom_nicnum = EmbeddedNICMacAddress.LOMMacAddress[i].NICNumber;
+ lom_mac = &EmbeddedNICMacAddress.LOMMacAddress[i].MacAddressByte[0];
+#else
+ lom_ethstat = ((EmbeddedNICMacAddress.LOMMacAddress[i].b0 & 0xc0) >> 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 <NIC number>");
+ 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 <Mode> ");
+ 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 = {0};
+ 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 = {0};
+ 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 = {0};
+ 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 : %ld W\n",powerheadroom.instheadroom);
+ printf ("System Peak Headroom : %ld 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={0};
+
+ 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 = {0};
+ 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 = {0};
+ 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\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 = {0};
+ 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\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={0};
+ //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: %ld Watt\n",ipmipowercap.MaximumPowerConsmp);
+ printf ("Minimum power: %ld Watt\n",ipmipowercap.MinimumPowerConsmp);
+ printf ("Power cap : %ld 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={0};
+ 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 ",
+ 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(((val<ipmipowercap.MinimumPowerConsmp)||(val>ipmipowercap.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(((val<ipmipowercap.MinimumPowerConsmp)||(val>ipmipowercap.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 <watt|btuphr>");
+ lprintf(LOG_NOTICE, "");
+ lprintf(LOG_NOTICE, " powermonitor powerconsumptionhistory <watt|btuphr>");
+ lprintf(LOG_NOTICE, " Displays power consumption history ");
+ lprintf(LOG_NOTICE, "");
+ lprintf(LOG_NOTICE, " powermonitor getpowerbudget");
+ lprintf(LOG_NOTICE, " Displays power cap in <watt|btuphr>");
+ lprintf(LOG_NOTICE, "");
+ lprintf(LOG_NOTICE, " powermonitor setpowerbudget <val><watt|btuphr|percent>");
+ lprintf(LOG_NOTICE, " Allows user to set the power cap in <watt|BTU/hr|percentage>");
+ 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 <b:d.f> <state..>");
+ 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 = {0};
+ 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 = {0};
+ 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 = {0};
+ 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 = {0};
+ 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)
+{
+ 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))
+ {
+ 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) )
+ {
+ 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 */
+ 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 | ");
+ }
+ else if((data1 & 0x0f) == 0x01)
+ {
+ snprintf(desc,SIZE_OF_DESC,"Redundancy Lost | ");
+ }
+ }
+ 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 | ");
+ }
+ else if((data1 & 0x0f) == 0x01)
+ {
+ snprintf(desc,SIZE_OF_DESC,"UnCorrectable ECC | ");
+ }
+ }
+ else if(code == 0x10)
+ {
+ if((data1 & 0x0f) == 0x00)
+ snprintf(desc,SIZE_OF_DESC,"Corr Memory Log Dissabled | ");
+ }
+ }
+ else
+ {
+ if(code == 0x12)
+ {
+ if((data1 & 0x0f) == 0x02)
+ snprintf(desc,SIZE_OF_DESC,"Unknown System Hardware Failure ");
+ }
+ if(code == 0x10)
+ {
+ if((data1 & 0x0f) == 0x03)
+ snprintf(desc,SIZE_OF_DESC,"All Even Logging Dissabled");
+ }
+ }
+ 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 )
+ {
+ if(0x51 == version)
+ {
+ snprintf(tmpdesc, SIZE_OF_DESC, "DIMM %s", ('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[5] = node + 'A';
+ sprintf(tmpdesc,"%d",dimmNum);
+ dimmStr[6] = tmpdesc[0];
+ dimmStr[7] = '\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[4] = tmpdesc[0];
+ dimmStr[5] = '\0';
+ strcat(str, dimmStr);
+ count++;
+ }
+ }
+ }
+ }
+ break;
+ case 0x20:
+ if(((data1 & 0x0f)== 0x00)&&((data1 & 0x80) && (data1 & 0x20)))
+ {
+ 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)
+ {
+ 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)
+ {
+ 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)
+ {
+ 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)
+ {
+ 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
+ }
+ }
+ else
+ {
+
+ 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);
+ }
+ }
+ break;
+ case 0x0F:
+ if(((data1 & 0x0f)== 0x0F)&&(data1 & 0x80))
+ {
+ 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;
+ }
+ }
+ 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";
+ type_str = "";
+ if (rectype == 0x02) type_str = get_sensor_type_desc(stype);
+
+#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);
+ } else if (evt[13] == 0xC1) {
+ if (snum == 0x23) {
+ // evt->data = rec->sel_type.standard_type.event_data[1];
+ pstr = get_dell_evt_desc(evt);
+ }
+ }
+#endif
+ pstr = get_dell_evt_desc(evt);
+ if (pstr != NULL) rv = 0;
+
+ if (rv == 0) {
+ 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 */
diff --git a/util/oem_dell.h b/util/oem_dell.h
new file mode 100644
index 0000000..a17a517
--- /dev/null
+++ b/util/oem_dell.h
@@ -0,0 +1,629 @@
+/****************************************************************************
+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 <config.h>
+#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*/
diff --git a/util/oem_fujitsu.c b/util/oem_fujitsu.c
new file mode 100644
index 0000000..362df96
--- /dev/null
+++ b/util/oem_fujitsu.c
@@ -0,0 +1,773 @@
+/*
+ * 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 <windows.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#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 */
+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);
+}
+
+/* end oem_fujitsu.c */
diff --git a/util/oem_fujitsu.h b/util/oem_fujitsu.h
new file mode 100644
index 0000000..defc6ac
--- /dev/null
+++ b/util/oem_fujitsu.h
@@ -0,0 +1,130 @@
+/*
+ * 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
diff --git a/util/oem_hp.c b/util/oem_hp.c
new file mode 100644
index 0000000..29a813f
--- /dev/null
+++ b/util/oem_hp.c
@@ -0,0 +1,149 @@
+/*
+ * 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 <windows.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include "ipmicmd.h"
+#include "ievents.h"
+#include "isensor.h"
+
+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;
+
+ 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 {
+ if ((reading[2] & 0x40) == 0x40) { /*Init/Unavail state*/
+ strncpy(pstring,"Init",slen);
+ rv = 0;
+ } else if ((sdr[20] & 0xC0) == 0xC0) { /*unit1==discrete*/
+ b = reading[2] & 0x3f;
+ pstr = "DiscreteUnit";
+ if (evtype == 0x0b) pstr = redund_str(b);
+ snprintf(pstring,slen,"%02x%02x %s",reading[3],reading[2],pstr);
+ rv = 0;
+ } else if (evtype == 0x6f) { /*evtype==0x6f special*/
+ pstr = "DiscreteEvt";
+ if (stype == 0x08) { /*Power Supply presence*/
+ if (reading[2] & 0x01) pstr = "Present";
+ else pstr = "Absent";
+ }
+ snprintf(pstring,slen,"%02x%02x %s",reading[3],reading[2],pstr);
+ rv = 0;
+ } else if (evtype == 0x0B) { /*Redundancy*/
+ b = reading[2] & 0x3f;
+ pstr = "DiscretePS"; /*Power Supplies*/
+ if (evtype == 0x0b) pstr = redund_str(b);
+ snprintf(pstring,slen,"%02x%02x %s",reading[3],reading[2],pstr);
+ 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";
+ snprintf(pstring,slen,"%02x%02x %s",reading[3],reading[2],pstr);
+ 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";
+ snprintf(pstring,slen,"%02x%02x %s",reading[3],reading[2],pstr);
+ rv = 0;
+ }
+ }
+ 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;
+}
+
+/* end oem_hp.c */
diff --git a/util/oem_intel.c b/util/oem_intel.c
new file mode 100644
index 0000000..f568300
--- /dev/null
+++ b/util/oem_intel.c
@@ -0,0 +1,1842 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#if defined(DOS)
+#include <dos.h>
+#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
+ */
+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 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;
+ }
+ *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 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_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 {
+ n = sprintf(desc,"DIMM[%d]",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);
+}
+
+/* end oem_intel.c */
diff --git a/util/oem_intel.h b/util/oem_intel.h
new file mode 100644
index 0000000..79587d5
--- /dev/null
+++ b/util/oem_intel.h
@@ -0,0 +1,79 @@
+/*
+ * 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
+
+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);
+
+/* end oem_intel.h */
diff --git a/util/oem_kontron.c b/util/oem_kontron.c
new file mode 100644
index 0000000..263560f
--- /dev/null
+++ b/util/oem_kontron.c
@@ -0,0 +1,1107 @@
+/*
+ * 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
+ * <stephane.filion@ca.kontron.com>
+ *
+ * This code implements an Kontron OEM proprietary commands.
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#include <winsock.h>
+#include <time.h>
+#define uint8_t unsigned char
+#define uint16_t unsigned short
+#define uint32_t unsigned int
+typedef uint32_t socklen_t;
+#else
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ipmicmd.h"
+#include "ievents.h"
+#include "oem_kontron.h"
+
+#define FRU_TYPE_COMPONENT 0x01
+#define FRU_TYPE_BASEBOARD 0x07
+
+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<len; k++)
+ str[k] = bcd_plus[(data[off+k] & 0x0f)];
+ str[k] = '\0';
+ break;
+
+ case 2: /* 6-bit ASCII */
+ for (i=j=0; i<len; i+=3) {
+ u.bits = 0;
+ k = ((len-i) < 3 ? (len-i) : 3);
+#if WORDS_BIGENDIAN
+ u.chars[3] = data[off+i];
+ u.chars[2] = (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 <device>\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;
+ int isdr = 0;
+ 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);
+}
+
+/* end oem_kontron.c */
diff --git a/util/oem_kontron.h b/util/oem_kontron.h
new file mode 100644
index 0000000..b95e6a6
--- /dev/null
+++ b/util/oem_kontron.h
@@ -0,0 +1,80 @@
+/*
+ * 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 */
diff --git a/util/oem_newisys.c b/util/oem_newisys.c
new file mode 100644
index 0000000..7b78532
--- /dev/null
+++ b/util/oem_newisys.c
@@ -0,0 +1,129 @@
+/*
+ * 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 <windows.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include "ipmicmd.h"
+#include "ievents.h"
+
+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;
+}
+
+/* end oem_newisys.c */
diff --git a/util/oem_quanta.c b/util/oem_quanta.c
new file mode 100644
index 0000000..a0ee3bb
--- /dev/null
+++ b/util/oem_quanta.c
@@ -0,0 +1,142 @@
+/*
+ * 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 <windows.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include "ipmicmd.h"
+#include "ievents.h"
+
+extern int decode_sensor_intel_nm(uchar *sdr,uchar *reading,
+ char *pstring,int slen); /*oem_intel.c*/
+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);
+}
+
+/* end oem_quanta.c */
diff --git a/util/oem_sun.c b/util/oem_sun.c
new file mode 100644
index 0000000..da413a8
--- /dev/null
+++ b/util/oem_sun.c
@@ -0,0 +1,1058 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef WIN32
+#include <windows.h>
+#define uint8_t unsigned char
+#define uint16_t unsigned short
+#define uint32_t unsigned int
+#include "getopt.h"
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <ctype.h>
+#include <limits.h>
+#if defined(HPUX)
+/* getopt is defined in stdio.h */
+#elif defined(MACOS)
+/* getopt is defined in unistd.h */
+#include <unistd.h>
+#include <stdint.h>
+#else
+#include <getopt.h>
+#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 */
+static char * progname = "isunoem";
+static char * progver = "2.93";
+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 <command> [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 <userid> <id_rsa.pub>");
+ 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 <userid>");
+ 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 <sensorid> [ledtype]");
+ lprintf(LOG_NOTICE, " Read status of LED found in Generic Device Locator.");
+ lprintf(LOG_NOTICE, "");
+ lprintf(LOG_NOTICE, " led set <sensorid> <ledmode> [ledtype]");
+ lprintf(LOG_NOTICE, " Set mode of LED found in Generic Device Locator.");
+ lprintf(LOG_NOTICE, "");
+ lprintf(LOG_NOTICE, " sbled get <sensorid> [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 <sensorid> <ledmode> [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 <percent>
+ */
+
+ 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 <id> [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 <id> <mode> [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;
+}
diff --git a/util/oem_sun.h b/util/oem_sun.h
new file mode 100644
index 0000000..2f4f8c6
--- /dev/null
+++ b/util/oem_sun.h
@@ -0,0 +1,137 @@
+/*
+ * 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*/
+
diff --git a/util/oem_supermicro.c b/util/oem_supermicro.c
new file mode 100644
index 0000000..528e4f7
--- /dev/null
+++ b/util/oem_supermicro.c
@@ -0,0 +1,595 @@
+/*
+ * 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 <windows.h>
+#include "getopt.h"
+#else
+#if defined(HPUX)
+/* getopt is defined in stdio.h */
+#elif defined(MACOS)
+/* getopt is defined in unistd.h */
+#include <unistd.h>
+#include <sys/time.h>
+#else
+#include <getopt.h>
+#endif
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include "ipmicmd.h"
+#include "ievents.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*/
+
+static char * progver = "2.93";
+static char * progname = "ismcoem";
+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);
+}
+
+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);
+}
+
+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_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 rv = -1;
+ uchar stype;
+ uchar bval;
+ char *pstr = NULL;
+
+ 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];
+ stype = sdr[12];
+ 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 = "00 Low"; break;
+ case 0x0001: pstr = "01 Medium"; break;
+ case 0x0002: pstr = "02 High"; break;
+ case 0x0004: pstr = "04 Overheat"; break;
+ case 0x0007: pstr = "07 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 = "00 Absent"; break; /*bit 0*/
+ case 0x01: pstr = "01 Present"; break; /*bit 0*/
+ case 0x02: pstr = "02 Failure"; break; /*bit 1*/
+ case 0x04: pstr = "04 Predict Fail"; break; /*bit 2*/
+ case 0x08: pstr = "08 Input Lost"; break; /*bit 3*/
+ default: rv = -1; break;
+ }
+ break;
+ default:
+ break;
+ }
+ if (rv == 0) strncpy(pstring, pstr, slen);
+ return(rv);
+}
+
+int decode_mem_supermicro(int prod, uchar b2, uchar b3, char *desc, int *psz)
+{
+ int array, dimm, n;
+ int rv = -1;
+ uchar bdata;
+ if ((desc == NULL) || (psz == NULL)) return -1;
+ if (b2 == 0xff) bdata = b3; /*ff is reserved*/
+ else bdata = b2; /* normal case */
+ array = (bdata & 0xc0) >> 6;
+ dimm = bdata & 0x3f;
+ /* bdata = 0x10 (16.) means CPU 1, DIMM 6 */
+ array = bdata / 10;
+ dimm = bdata % 10;
+
+#ifdef DMIOK
+ /* Use DMI if we get confirmation about array/dimm indices. */
+ if (! is_remote()) {
+ fsm_debug = fdebug;
+ rv = get_MemDesc(array,dimm,desc,psz);
+ /* if (rv != 0) desc has "DIMM[%d}" */
+ }
+#endif
+
+ if (rv != 0) {
+ n = sprintf(desc,"DIMM%d/CPU%d",dimm,array);
+ *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)
+ */
+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 *type_str = "";
+ char *pstr = NULL;
+ int sevid;
+ ushort genid;
+ uchar snum;
+
+ 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);
+ 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";
+ switch((evt[13] &0x0f)) { /*offset/data1 l.o. nibble*/
+ 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;
+ }
+ rv = 0;
+ break;
+ default: pstr = "CpuTemp Event"; break;
+ }
+ 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; }
+ rv = 0;
+ break;
+ default: pstr = "CPLD Event"; break;
+ }
+ break;
+ default: /*other sensor types*/
+ break;
+ }
+ }
+ if (rv == 0) {
+ format_event(id,timestamp, sevid, genid, type_str,
+ snum,NULL,pstr,mybuf,outbuf,outsz);
+ }
+ return(rv);
+}
+
+static void usage(void)
+{
+ printf("Usage: %s <command> [arg]\n",progname);
+ printf(" intrusion = reset chassis intrusion\n");
+ printf(" bmcstatus [enable| disable] = get/set BMC status\n");
+ printf(" firmware = get extra firmware info\n");
+ printf(" lanport [dedicated| lan1| failover] = get/set IPMI LAN port\n");
+ printf("These commands may not work on all SuperMicro systems\n");
+}
+
+static int ipmi_smcoem_main(int argc, char **argv)
+{
+ int rv = 0;
+ char msg[80];
+ uchar val;
+
+ 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],"lanport",9) == 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 {
+ 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 */
diff --git a/util/oem_supermicro.h b/util/oem_supermicro.h
new file mode 100644
index 0000000..daf08d6
--- /dev/null
+++ b/util/oem_supermicro.h
@@ -0,0 +1,56 @@
+/*
+ * 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 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 */
diff --git a/util/subs.c b/util/subs.c
new file mode 100644
index 0000000..9f11423
--- /dev/null
+++ b/util/subs.c
@@ -0,0 +1,848 @@
+/*
+ * 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 <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#ifdef WIN32
+#include <windows.h>
+// #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 <unistd.h>
+#include <syslog.h>
+#include <errno.h>
+#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 (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;
+}
+
+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<len; i++) {
+ if (((i%16) == 0) && (i != 0))
+ fprintf(fp, "\r\n");
+ fprintf(fp, " %2.2x", buf[i]);
+ }
+ fprintf(fp, "\r\n");
+}
+
+const char * buf2str(uchar * buf, int len)
+{
+ static char str[1024];
+ int i;
+ if (len <= 0 || len > sizeof(str)) return NULL;
+ memset(str, 0, sizeof(str));
+ for (i=0; i<len; i++) sprintf(str+i+i, "%2.2x", buf[i]);
+ str[len*2] = '\0';
+ return (const char *)str;
+}
+ushort buf2short(uchar * buf)
+{
+ return (ushort)(buf[1] << 8 | buf[0]);
+}
+ulong buf2long(uchar * buf)
+{
+ return (ulong)(buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]);
+}
+
+#define IPMI_OEM_PICMG 12634
+#define SZUN 32
+const char * oemval2str(ushort oem, uchar val, const struct oemvalstr *vs)
+{
+ static char un_str[SZUN];
+ int i;
+ for (i = 0; vs[i].oem != 0x00 && vs[i].str != NULL; i++) {
+ if ( ( vs[i].oem == oem || vs[i].oem == IPMI_OEM_PICMG )
+ && vs[i].val == val ) {
+ return vs[i].str;
+ }
+ }
+ memset(un_str, 0, SZUN);
+ snprintf(un_str, SZUN, "OEM reserved #%02x", val);
+ return un_str;
+}
+const char * val2str(ushort val, const struct valstr *vs)
+{
+ static char un_str[SZUN];
+ int i;
+ for (i = 0; vs[i].str != NULL; i++) {
+ if (vs[i].val == val) return vs[i].str;
+ }
+ memset(un_str, 0, SZUN);
+ snprintf(un_str, SZUN, "Unknown (0x%x)", val);
+ return un_str;
+}
+ushort str2val( char *str, struct valstr *vs)
+{
+ int i, x, y;
+ for (i = 0; vs[i].str != NULL; i++) {
+ x = strlen_(str);
+ y = strlen_(vs[i].str);
+ if (strncasecmp(vs[i].str, str, (x > y)? x : y) == 0)
+ return vs[i].val;
+ }
+ return vs[i].val;
+}
+
+
+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<errno.h has this also */
+int get_errno(void)
+{
+ return(errno);
+}
+#endif
+
+ /* For a list of all IANA enterprise mfg vendor numbers,
+ * see http://www.iana.org/assignments/enterprise-numbers
+ * Product numbers are different for each mfg vendor. */
+#define N_MFG 43
+static struct { int val; char *pstr; } mfgs[N_MFG] = {
+ {0, " "},
+ {0x0000BA, "Toshiba"},
+ {0x000074, "Hitachi"},
+ {0x00018F, "Hitachi"},
+ {0x000175, "Tatung"},
+ {0x000614, "Performance Technologies"},
+ {0x000F85, "Aelita Software"}, /*3973. HP DL140*/
+ {0x0028B2, "Avocent"},
+ {0x002B5E, "OSA"},
+ {0x0035AE, "Raritan"}, /*13742.*/
+ {0x0051EE, "AMI"},
+ { 94, "Nokia-Siemens"},
+ { 107, "Bull"},
+ { 4337, "Radisys"},
+ { 4542, "ASF"},
+ { 6569, "Inventec"},
+ { 7154, "IPMI forum"},
+ { 11129, "Google"},
+ { 12634, "PICMG"},
+ { 16394, "Pigeon Point"},
+ { 20569, "Inventec ESC"},
+ { 24673, "ServerEngines"},
+ { 27768, "NAT"},
+ {VENDOR_CISCO, "Cisco"}, /*=5771.*/
+ {VENDOR_IBM, "IBM"}, /*0x000002*/
+ {VENDOR_NEWISYS, "Newisys"}, /*=9237. */
+ {VENDOR_XYRATEX, "Xyratex"}, /*=1993. */
+ {VENDOR_QUANTA, "Quanta"}, /*=7244. */
+ {VENDOR_MAGNUM, "Magnum Technologies"}, /*=5593. */
+ {VENDOR_SUPERMICROX, "xSuperMicro"}, /* 47488. used by Winbond/SuperMicro*/
+ {VENDOR_HP, "HP"}, /* 0x00000B for HP */
+ {VENDOR_DELL, "Dell"}, /*0x0002A2*/
+ {VENDOR_KONTRON, "Kontron"}, /*=0x003A98, 15000.*/
+ {VENDOR_SUPERMICRO, "SuperMicro"}, /*=0x002A7C, 10876. used in AOC-SIMSO*/
+ {VENDOR_FUJITSU, "Fujitsu-Siemens"}, /* 0x002880, 10368. */
+ {VENDOR_PEPPERCON, "Peppercon"}, /* 0x0028C5, 10437. now w Raritan*/
+ {VENDOR_MICROSOFT, "Microsoft"}, /*=0x000137, 311.*/
+ {VENDOR_NEC, "NEC"}, /*=0x000077*/
+ {VENDOR_NSC, "NSC"}, /*=0x000322*/
+ {VENDOR_LMC, "LMC"}, /*=0x000878 with SuperMicro*/
+ {VENDOR_TYAN, "Tyan"}, /*=0x0019FD*/
+ {VENDOR_SUN, "Sun"}, /*=0x00002A*/
+ {VENDOR_INTEL, "Intel"} /*=0x000157*/
+};
+
+char * get_iana_str(int mfg)
+{
+ char *mfgstr = "";
+ int i;
+ for (i = 0; i < N_MFG; i++) {
+ if (mfgs[i].val == mfg) {
+ mfgstr = mfgs[i].pstr;
+ break;
+ }
+ }
+ if (i >= 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<u; i++) s = 0; /*spin for u loops*/
+ } else {
+ Sleep(s * 1000);
+ }
+#elif defined(DOS)
+ if (s == 0) delay(u);
+ else delay(s * 1000);
+#else
+ if (s == 0) {
+ usleep(u);
+ } else {
+ sleep(s);
+ }
+#endif
+}
+
+#define SYS_INFO_MAX 64
+
+static int sysinfo_has_len(uchar enc, int vendor)
+{
+ int rv = 1;
+ int vend;
+ if (enc > (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(char *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, uchar *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_WARNING; 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 */